06253adf6235727452df60a5995ff2f4d04a75f7
[slipway.git] / src / edu / berkeley / obits / device / atmel / AvrDrone.c
1 //\r
2 // YOU MUST COMPILE THIS WITH -O3 OR THE AVR WILL NOT BE ABLE TO KEEP UP!!!!\r
3 //\r
4 \r
5 #define F_CPU 3960000\r
6 \r
7 #if !defined(__AVR_AT94K__)\r
8 #error you forgot to put -mmcu=at94k on the command line\r
9 #endif\r
10 \r
11 #include <avr/wdt.h>\r
12 #include <util/delay.h>\r
13 #include <avr/io.h>\r
14 #include <avr/interrupt.h>\r
15 \r
16 unsigned char val = 0;\r
17 \r
18 volatile unsigned char dataReady = 0;\r
19 volatile unsigned char data = 0;\r
20 \r
21 void initUART1(unsigned int baudRate, unsigned int doubleRate) {\r
22   UBRRHI = (((baudRate) >> 8) & 0x000F); \r
23   UBRR1  = ((baudRate) & 0x00FF); \r
24   UCSR1B |= ((1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1)); \r
25   /*\r
26   if (doubleRate)\r
27     UCSR1A |= (1 << U2X1);\r
28   else\r
29     UCSR1A &= ~(1 << U2X1);\r
30   */\r
31 }\r
32 \r
33 #define BUFSIZE (1024 *2)\r
34 static char buf[BUFSIZE];\r
35 volatile static int head = 0;\r
36 volatile static int tail = 0;\r
37 \r
38 void send(char c) {\r
39   while(!(UCSR1A & (1 << UDRE1)));           /* Wait for data Regiester to be empty */\r
40   UDR1 = (int)c;\r
41 }\r
42 \r
43 inline void portd(int bit, int on) {\r
44   if (on) {\r
45     PORTD &= ~(1<<bit);\r
46   } else {\r
47     PORTD |= (1<<bit);\r
48   }\r
49 }\r
50 inline void cts(int c) {\r
51   if (c) {\r
52     PORTE &= ~(1 << 4);\r
53     portd(0, 1);\r
54   } else {\r
55     PORTE |= (1 << 4);\r
56     portd(0, 0);\r
57   }\r
58 }\r
59 \r
60 inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }\r
61 inline int full() { return inc(tail)==head; }\r
62 inline int nearlyFull() {\r
63   if (tail==head) return 0;\r
64   if (tail < head) return (head-tail) < (BUFSIZE/2);\r
65   return (tail-head) > (BUFSIZE/2);\r
66 }\r
67 inline int empty() { return head==tail; }\r
68 \r
69 inline char recv() {\r
70   int q;\r
71   char ret;\r
72   while(empty()) cts(1);\r
73   ret = buf[head];\r
74   head = inc(head);\r
75   if (!nearlyFull()) cts(0);\r
76   return ret;\r
77 }\r
78 \r
79 void init() {\r
80   EIMF  = 0xFF;                          /* Enalbe External Interrrupt*/  \r
81   DDRD = 0xFF;                           /* Configure PORTD as Output */\r
82   DDRE = 1 << 4;                         /* ability to write to E */\r
83   initUART1(1, 0);\r
84   SREG |= 0x80;\r
85   sei();\r
86 }\r
87 \r
88 \r
89 \r
90 void conf(int z, int y, int x, int d) {\r
91   FPGAX = x;\r
92   FPGAY = y;\r
93   FPGAZ = z;\r
94   FPGAD = d;\r
95 }\r
96 \r
97 void doreset() {\r
98   int i;\r
99   for(i=0; i<5; i++) {\r
100     PORTD = ~0x01;\r
101     _delay_ms(50);\r
102     PORTD = ~0x02;\r
103     _delay_ms(50);\r
104     PORTD = ~0x04;\r
105     _delay_ms(50);\r
106     PORTD = ~0x08;\r
107     _delay_ms(50);\r
108   }\r
109   PORTD = ~0x00;\r
110   wdt_enable(WDTO_250MS);\r
111   while(1) { }\r
112 }\r
113 \r
114 #define TIMERVAL 100\r
115 ISR(SIG_OVERFLOW0) { \r
116   PORTD = ~FISUA;\r
117   TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
118   TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
119   sei();\r
120\r
121 void init_timer()  { \r
122   TCCR0 |= (1<<CS00);         // set the timer0 prescaler to CK\r
123   TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
124   TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
125\r
126 \r
127 ISR(SIG_INTERRUPT1) {   // use interrupt1 since interrupt0 is sent by the watchdog (I think)\r
128   doreset();\r
129 }\r
130 \r
131 void die() { cli(); cts(0); _delay_ms(2000); while(1) { } }\r
132 ISR(SIG_UART1_RECV) {\r
133   if (UCSR1A & (1 << FE1))   { portd(2,0); portd(3,1); die(); }  // framing error, lock up with LED=01\r
134   if ((UCSR1A & (1 << OR1))) { portd(2,1); portd(3,0); die(); }  // overflow; lock up with LED=10\r
135   if (full())                { portd(2,1); portd(3,1); die(); }  // buffer overrun\r
136   buf[tail] = UDR1;\r
137   tail = inc(tail);\r
138   SREG |= 0x80;\r
139   sei();\r
140   if (nearlyFull()) cts(0);\r
141 }\r
142 \r
143 inline int hex(char c) {\r
144   if (c >= '0' && c <= '9') return (c - '0');\r
145   if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
146   if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
147   return -1;\r
148 }\r
149 \r
150 int main() {\r
151   int count;\r
152   init();\r
153   cts(0);\r
154   send('O');\r
155   send('B');\r
156   send('I');\r
157   send('T');\r
158   send('S');\r
159   send('\n');\r
160   cts(1);\r
161   for(;;) {\r
162     int i, x=0, y=0, z=0, d=0;\r
163     switch(recv()) {\r
164       case 1:\r
165         z = recv();\r
166         y = recv();\r
167         x = recv();\r
168         d = recv();\r
169         portd(1,1);\r
170         conf(z, y, x, d);\r
171         portd(1,0);\r
172         break;\r
173       case 2:\r
174         portd(1,1);\r
175         send(FISUA);\r
176         portd(1,0);\r
177         break;\r
178       case 3:\r
179         init_timer();\r
180         break;\r
181       default: die();\r
182     }\r
183   }\r
184   return 0;\r
185 }  \r
186 \r