turn ftdi driver into echo server
[goodfet] / firmware / lib / atmega1284p.c
1 #include "platform.h"
2
3 #include <avr/io.h>
4 #include <util/delay.h>
5
6 //! Receive a byte.
7 unsigned char serial0_rx(){
8   while( !(UCSR0A & (1 << RXC0)) );
9   return UDR0;
10 }
11
12 //! Receive a byte.
13 unsigned char serial1_rx(){
14   return 0;
15 }
16
17 //! Transmit a byte.
18 void serial0_tx(unsigned char x){
19   while (!(UCSR0A & (1<<UDRE0)) );
20   UDR0 = x;
21 }
22
23 //! Transmit a byte on the second UART.
24 void serial1_tx(unsigned char x){
25 }
26
27 //! Set the baud rate.
28 void setbaud0(unsigned char rate){
29         /* disable briefly */
30         UCSR0B = 0;
31
32         UBRR0L = 4;   /* 500,000 baud at 20MHz */
33         //UBRR0L = 1;   /* 500,000 baud at 8MHz */
34         //UBRR0L = 103; /* 9600 baud */
35         // XXX UBRR0L = 8;     /* 115200 baud ERROR RATE TOO HIGH */
36         UBRR0H = 0;
37
38         UCSR0A = (1 << U2X0);   /* double the baud rate */
39         UCSR0C = (3 << UCSZ00); /* 8N1 */
40
41         /* enabling rx/tx must be done after frame/baud setup */
42         UCSR0B = ((1 << TXEN0) | (1 << RXEN0));
43
44   return;
45   
46 }
47
48 //! Set the baud rate of the second uart.
49 void setbaud1(unsigned char rate){
50   //http://mspgcc.sourceforge.net/baudrate.html
51   switch(rate){
52   case 1://9600 baud
53     
54     break;
55   case 2://19200 baud
56     
57     break;
58   case 3://38400 baud
59     
60     break;
61   case 4://57600 baud
62     
63     break;
64   default:
65   case 5://115200 baud
66     
67     break;
68   }
69 }
70
71
72 void donbfet_init_uart0(){
73   setbaud0(0);
74   _delay_ms(500); //takes a bit to stabilize
75 }
76
77 void led_init(){
78   
79 }
80
81 void  led_on() {
82         PLEDOUT |= (1 << PLEDPIN);
83 }
84
85 void led_off() {
86         PLEDOUT &= ~(1 << PLEDPIN);
87 }
88
89 void donbfet_init(){
90         uint8_t x;
91
92         /* explicitly clear interrupts */
93         cli();
94
95         /* move the vectors */
96
97         /* move interrupts from boot flash section */
98         /* NB */
99         /* you MUST use a variable during this process. even highly optimized,
100          * masking the bit, shifting, ANDing, and setting MCUCR will exceed
101          * 4 CPU cycles! set a variable with the desired value for MCUCR and
102          * then set the register once IVCE is enabled
103          */
104         x = MCUCR & ~(1 << IVSEL);
105
106         /* enable change of interrupt vectors */
107         /* NOTE: setting IVCE disables interrupts until the bit is auto-unset 
108          * 4 cycles after being set or after IVSEL is written
109          */
110         MCUCR |= (1 << IVCE);
111         MCUCR = x;
112
113         /* disable the watchdog timer; this macro will disable interrupts for us */
114         /* NOTE: ensure that the WDRF flag is unset in the MCUSR or we will spinlock
115          * when the watchdog times out
116          */
117         MCUSR &= ~(1 << WDRF);
118         wdt_disable();
119
120         /* init the USART */
121         donbfet_init_uart0();
122
123         /* set the LED as an output */
124         PLEDDIR |= (1 << PLEDPIN);
125         PLEDOUT |= (1 << PLEDPIN);
126
127         /* explicitly enable interrupts */
128         sei();
129 }
130
131 void
132 donbfet_reboot()
133 {
134         MCUSR &= ~(1 << WDRF);
135         wdt_enable(WDTO_15MS);
136         while(1)
137                 _delay_ms(127);
138 }
139
140 void donbfet_init_uart1(){
141 }
142
143 uint8_t
144 donbfet_get_byte(uint16_t v)
145 {
146         /* NB */
147         /* we are only passed in a 16bit word. should 
148          * be increased to 32bit if we want to handle
149          * far reads as well
150          */
151 /* XXX should be far on the 1284P, but there are bugs with flash reads using _far */
152 /* XXX until the bugs are figured out (probably my fault?) use _near */
153         return pgm_read_byte_near(v);
154 }
155
156 int * 
157 donbfet_ramend(void)
158 {
159         /* NB */
160         /* ATmega1284P has 16K SRAM */
161         return (int * )0x4000; 
162 }
163
164 void
165 led_toggle(void)
166 {
167         led_on();
168         _delay_ms(30);
169         led_off();
170 }
171