Facedancer11 support. Boards just shipped from China.
[goodfet] / firmware / lib / atmega644p.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 
78 led_on()
79 {
80         PLEDOUT |= (1 << PLEDPIN);
81 }
82
83 void
84 led_off()
85 {
86         PLEDOUT &= ~(1 << PLEDPIN);
87 }
88
89 void 
90 donbfet_init()
91 {
92         uint8_t x;
93
94         /* explicitly clear interrupts */
95         cli();
96
97         /* move the vectors */
98
99         /* move interrupts from boot flash section */
100         /* NB */
101         /* you MUST use a variable during this process. even highly optimized,
102          * masking the bit, shifting, ANDing, and setting MCUCR will exceed
103          * 4 CPU cycles! set a variable with the desired value for MCUCR and
104          * then set the register once IVCE is enabled
105          */
106         x = MCUCR & ~(1 << IVSEL);
107
108         /* enable change of interrupt vectors */
109         /* NOTE: setting IVCE disables interrupts until the bit is auto-unset 
110          * 4 cycles after being set or after IVSEL is written
111          */
112         MCUCR |= (1 << IVCE);
113         MCUCR = x;
114
115         /* disable the watchdog timer; this macro will disable interrupts for us */
116         /* NOTE: ensure that the WDRF flag is unset in the MCUSR or we will spinlock
117          * when the watchdog times out
118          */
119         MCUSR &= ~(1 << WDRF);
120         wdt_disable();
121
122         /* init the USART */
123         donbfet_init_uart0();
124
125         /* set the LED as an output */
126         PLEDDIR |= (1 << PLEDPIN);
127         PLEDOUT |= (1 << PLEDPIN);
128
129         /* explicitly enable interrupts */
130         sei();
131 }
132
133 void
134 donbfet_reboot()
135 {
136         MCUSR &= ~(1 << WDRF);
137         wdt_enable(WDTO_15MS);
138         while(1)
139                 _delay_ms(127);
140 }
141
142 void donbfet_init_uart1(){
143 }
144
145 uint8_t
146 donbfet_get_byte(uint16_t v)
147 {
148         /* NB */
149         /* we are only passed in a 16bit word. should 
150          * be increased to 32bit if we want to handle
151          * far reads as well
152          */
153         return pgm_read_byte_near(v);
154 }
155
156 int * 
157 donbfet_ramend(void)
158 {
159         /* NB */
160         /* ATmega644P has 4K SRAM */
161         return (int * )0x1000; 
162 }
163
164 void
165 led_toggle(void)
166 {
167         led_on();
168         _delay_ms(30);
169         led_off();
170 }
171