3c290c1a0a1afd511a9c575ce8af72da72903605
[fw/altos] / ao-bringup-avr / ao-uart.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include <avr/io.h>
19 #include <avr/interrupt.h>
20 #define TEENSY 1
21 #if TEENSY
22 #define F_CPU 16000000UL        // 16 MHz
23 #else
24 #define F_CPU  8000000UL        // 8 MHz
25 #endif
26 #include <util/delay.h>
27
28 #define LEDOUT          PORTB7
29 #define LEDPORT         PORTB
30 #define LEDDDR          DDRB
31 #define LEDDDRPIN       DD7
32
33 static void
34 timer1_init(void)
35 {
36         TCCR1A = ((0 << WGM11) |        /* CTC mode, OCR1A */
37                   (0 << WGM10));        /* CTC mode, OCR1A */
38         TCCR1B = ((0 << ICNC1) |        /* no input capture noise canceler */
39                   (0 << ICES1) |        /* input capture on falling edge (don't care) */
40                   (0 << WGM13) |        /* CTC mode, OCR1A */
41                   (1 << WGM12) |        /* CTC mode, OCR1A */
42                   (3 << CS10));         /* clk/64 from prescaler */
43
44 #if TEENSY
45         OCR1A = 2500;                   /* 16MHz clock */
46 #else
47         OCR1A = 1250;                   /* 8MHz clock */
48 #endif
49
50         TIMSK1 = (1 << OCIE1A);         /* Interrupt on compare match */
51 }
52
53 static void
54 clock_init(void)
55 {
56         /* disable RC clock */
57         CLKSEL0 &= ~(1 << RCE);
58
59         /* Disable PLL */
60         PLLCSR &= ~(1 << PLLE);
61
62         /* Enable external clock */
63         CLKSEL0 |= (1 << EXTE);
64
65         /* wait for external clock to be ready */
66         while ((CLKSTA & (1 << EXTON)) == 0)
67                 ;
68
69         /* select external clock */
70         CLKSEL0 |= (1 << CLKS);
71
72         /* Disable the clock prescaler */
73         cli();
74         CLKPR = (1 << CLKPCE);
75         CLKPR = 0;
76         sei();
77
78         /* Set up the PLL to use the crystal */
79
80         /* Use primary system clock as PLL source */
81         PLLFRQ = ((0 << PINMUX) |       /* Use primary clock */
82                   (0 << PLLUSB) |       /* No divide by 2 for USB */
83                   (0 << PLLTM0) |       /* Disable high speed timer */
84                   (0x4 << PDIV0));      /* 48MHz PLL clock */
85
86         /* Set the frequency of the crystal */
87 #if TEENSY
88         PLLCSR |= (1 << PINDIV);        /* For 16MHz crystal on Teensy board */
89 #else
90         PLLCSR &= ~(1 << PINDIV);       /* For 8MHz crystal on TeleScience board */
91 #endif
92
93         /* Enable the PLL */
94         PLLCSR |= (1 << PLLE);
95         while (!(PLLCSR & (1 << PLOCK)))
96                 ;
97 }
98
99 void
100 uart_send(char data)
101 {
102         while (!(UCSR1A & (1 << UDRE1)))
103                 ;
104         UDR1 = data;
105 }
106
107 void
108 uart_init(uint16_t baud)
109 {
110         PRR1 &= ~(1 << PRUSART1);
111         UBRR1L = baud;
112         UBRR1H = baud >> 8;
113         UCSR1A = 0;
114         UCSR1B = ((1 << RXEN1) |        /* Enable receiver */
115                   (1 << TXEN1));        /* Enable transmitter */
116         UCSR1C = ((0 << UMSEL10) |      /* Asynchronous mode */
117                   (0 << UPM10) |        /* No parity */
118                   (0 << USBS1) |        /* 1 stop bit */
119                   (3 << UCSZ10) |       /* 8 bit characters */
120                   (0 << UCPOL1));       /* MBZ for async mode */
121 }
122
123 int main(void)
124 {
125         clock_init();
126         timer1_init();
127         uart_init(832);
128
129         LEDDDR |= (1 << LEDDDRPIN);
130
131         for (;;) {
132                 LEDPORT ^= (1 << LEDOUT);
133                 uart_send('H');
134         }
135 }