I think I got flow control working
[slipway.git] / src / edu / berkeley / slipway / slipway_drone.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 #define F_CPU 12000000\r
7 \r
8 #if !defined(__AVR_AT94K__)\r
9 #error you forgot to put -mmcu=at94k on the command line\r
10 #endif\r
11 \r
12 #include <avr/wdt.h>\r
13 #include <util/delay.h>\r
14 #include <avr/io.h>\r
15 #include <avr/interrupt.h>\r
16 \r
17 int err = 0;\r
18 \r
19 void initUART0(unsigned int baudRate, unsigned int doubleRate) {\r
20   UBRRHI  = (((baudRate) >> 8) & 0x000F); \r
21   UBRR0   = ((baudRate) & 0x00FF); \r
22   UCSR0B |= ((1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0)); \r
23 \r
24   if (doubleRate)\r
25     UCSR0A |=  (1 << U2X0);\r
26   else\r
27     UCSR0A &= ~(1 << U2X0);\r
28 }\r
29 \r
30 #define BUFSIZE (1024)\r
31 \r
32 inline void portd(int bit, int on) {\r
33   /*\r
34   if (on) {\r
35     PORTD &= ~(1<<bit);\r
36   } else {\r
37     PORTD |= (1<<bit);\r
38   }\r
39   */\r
40 }\r
41 \r
42 long int numread = 0;\r
43 inline void cts(int c) {\r
44   numread++;\r
45   if (c) {\r
46     PORTE &= ~(1 << 7);\r
47     portd(0, 0);\r
48   } else {\r
49     PORTE |= (1 << 7);\r
50     portd(0, 1);\r
51   }\r
52 }\r
53 \r
54 \r
55 static volatile int sending = 0;\r
56 static volatile int32_t interrupt_count = 0;\r
57 \r
58 // RECV //////////////////////////////////////////////////////////////////////////////\r
59 \r
60 char read_buf[BUFSIZE];\r
61 volatile int read_buf_head;\r
62 volatile int read_buf_tail;\r
63 char write_buf[BUFSIZE];\r
64 volatile int write_buf_head;\r
65 volatile int write_buf_tail;\r
66 \r
67 inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }\r
68 inline int read_full() { return inc(read_buf_tail)==read_buf_head; }\r
69 inline int abs(int x) { return x<0 ? -x : x; }\r
70 inline int read_size() { return read_buf_tail<read_buf_head ? (read_buf_head-read_buf_tail) : (read_buf_tail-read_buf_head); }\r
71 inline int read_empty() { return read_buf_head==read_buf_tail; }\r
72 inline int read_nearlyFull() {\r
73   if (read_buf_tail==read_buf_head) return 0;\r
74   if (read_buf_tail < read_buf_head) return (read_buf_head-read_buf_tail) < (BUFSIZE/2);\r
75   return (read_buf_tail-read_buf_head) > (BUFSIZE/2);\r
76 }\r
77 \r
78 inline int write_full() { return inc(write_buf_tail)==write_buf_head; }\r
79 inline int write_empty() { return write_buf_head==write_buf_tail; }\r
80 inline int write_nearlyFull() {\r
81   if (write_buf_tail==write_buf_head) return 0;\r
82   if (write_buf_tail < write_buf_head) return (write_buf_head-write_buf_tail) < (BUFSIZE/2);\r
83   return (write_buf_tail-write_buf_head) > (BUFSIZE/2);\r
84 }\r
85 \r
86 inline char recv() {\r
87   int q;\r
88   char ret;\r
89   while(read_empty()) cts(1);\r
90   ret = read_buf[read_buf_head];\r
91   read_buf_head = inc(read_buf_head);\r
92   if (!read_nearlyFull()) cts(1);\r
93   if (PORTE & (1<<3)) PORTE &= ~(1<<3);\r
94   else                PORTE |=  (1<<3);\r
95   return ret;\r
96 }\r
97 \r
98 ISR(SIG_UART0_DATA) {\r
99   if (write_empty()) {\r
100     UCSR0B &= ~(1 << UDRIE0);\r
101     return;\r
102   }\r
103   char ret = write_buf[write_buf_head];\r
104   write_buf_head = inc(write_buf_head);\r
105   UDR0 = (int)ret;\r
106   sei();\r
107 }\r
108 \r
109 void send(char c) {\r
110   while (write_full());\r
111   write_buf[write_buf_tail] = c;\r
112   write_buf_tail = inc(write_buf_tail);\r
113   if (PORTE & (1<<2)) PORTE &= ~(1<<2);\r
114   else                PORTE |=  (1<<2);\r
115   UCSR0B |= (1 << UDRIE0);\r
116 }\r
117 \r
118 \r
119 void fpga_interrupts(int on) {\r
120   if (on/* && interrupt_count<301*/) {\r
121     //FISUA = 0x1;\r
122     FISCR = 0x80;\r
123     FISUD = 0x08;\r
124   } else {\r
125     FISUD = 0;\r
126     FISCR = 0;\r
127   }\r
128 }\r
129 \r
130 void init() {\r
131   read_buf_head = 0;\r
132   read_buf_tail = 0;\r
133   write_buf_head = 0;\r
134   write_buf_tail = 0;\r
135   //initUART0(1, 0);  //for slow board\r
136   initUART0(0, 0);  //for slow board\r
137   //initUART0(0, 1);  //for slow board\r
138 }\r
139 \r
140 void conf(int z, int y, int x, int d) {\r
141   FPGAX = x;\r
142   FPGAY = y;\r
143   FPGAZ = z;\r
144   FPGAD = d;\r
145 }\r
146 \r
147 void doreset() {\r
148   int i;\r
149   for(i=0; i<5; i++) {\r
150     PORTD = ~0x01;\r
151     _delay_ms(50);\r
152     PORTD = ~0x02;\r
153     _delay_ms(50);\r
154     PORTD = ~0x04;\r
155     _delay_ms(50);\r
156     PORTD = ~0x08;\r
157     _delay_ms(50);\r
158   }\r
159   PORTD = ~0x00;\r
160   wdt_enable(WDTO_250MS);\r
161   while(1) { }\r
162 }\r
163 \r
164 #define TIMERVAL 100\r
165 int portdc = 0;\r
166 \r
167 ISR(SIG_FPGA_INTERRUPT15) { \r
168   PORTD = portdc++;\r
169   interrupt_count++;\r
170   //PORTD = ~(interrupt_count & 0xff);\r
171   //if (interrupt_count >= 301) fpga_interrupts(0);\r
172   //sei();\r
173   fpga_interrupts(1);\r
174 }\r
175 /*\r
176 ISR(SIG_OVERFLOW0) { \r
177   fpga_interrupts(0);\r
178   PORTD = ~FISUA;\r
179   TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
180   TIMSK |= (1<<TOIE0);        // enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
181   if (sending) UDR1 = FISUA;\r
182   fpga_interrupts(1);\r
183   sei();\r
184\r
185 void init_timer()  { \r
186   TCCR0 |= (1<<CS00);         // set the timer0 prescaler to CK\r
187   TCNT0 = TIMERVAL;           // load the nearest-to-one-second value  into the timer0\r
188   TIMSK |= (1<<TOIE0);        //enable the compare match1 interrupt and the timer/counter0 overflow interrupt\r
189\r
190 */\r
191 ISR(SIG_INTERRUPT0) {   // use interrupt1 since interrupt0 is sent by the watchdog (I think)\r
192   SREG = 0;\r
193   //PORTE |=  (1<<0);\r
194   sei();\r
195 }\r
196 void die() { cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { portd(2,0); portd(2,1); } }\r
197 \r
198 ISR(SIG_UART0_RECV) {\r
199 \r
200   if (UCSR0A & (1 << FE0))    err = 201;//{ portd(2,0); portd(3,1); die(); }  // framing error, lock up with LED=01\r
201   if ((UCSR0A & (1 << OR0)))  err = 202;//{ portd(2,1); portd(3,0); die(); }  // overflow; lock up with LED=10\r
202   if (read_full())            err = 203;//{ portd(2,1); portd(3,1); die(); }  // buffer overrun\r
203 \r
204   read_buf[read_buf_tail] = UDR0;\r
205   read_buf_tail = inc(read_buf_tail);\r
206   if (read_nearlyFull()) cts(0);\r
207   SREG |= 0x80;\r
208   sei();\r
209 }\r
210 \r
211 inline int hex(char c) {\r
212   if (c >= '0' && c <= '9') return (c - '0');\r
213   if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
214   if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
215   return -1;\r
216 }\r
217 \r
218 int main() {\r
219   DDRE = (1<<7) | (1<<5) | (1<<3) | (1<<2);\r
220   PORTE = 0;\r
221 \r
222   init();\r
223 \r
224   EIMF = 0xFF;\r
225   SREG = INT0;\r
226   sei();\r
227 \r
228   PORTE &= ~(1<<7);\r
229 \r
230   int count = 0;\r
231   long long bad = 0;\r
232   int left = 0;\r
233   char v = 0;\r
234   long int oldi = 0;\r
235   cts(0);\r
236   cts(1);\r
237   /*\r
238   while(1) {\r
239     long int i = recv() & 0xff;\r
240     //if (i < 0) err = 200;\r
241     //if (err < 200) {\r
242       long int newi = oldi+1;\r
243       if (newi >= 256) newi -= 256;\r
244       if (i != newi) err++;\r
245       //}\r
246     oldi = i;\r
247 \r
248     send(err >= 10 ? 255 : i);\r
249     //send(err);\r
250   }\r
251   */\r
252 \r
253   PORTE |=  (1<<3);\r
254   recv();\r
255   send('O');\r
256   send('B');\r
257   send('I');\r
258   send('T');\r
259   send('S');\r
260   send('\n');\r
261 \r
262   int x=0, y=0, z=0;\r
263   //while(1) send(/*FISUA*/2);\r
264   for(;;) {\r
265     /*\r
266     if (PORTE & (1<<6)) PORTE &= ~(1<<6);\r
267     else                PORTE |=  (1<<6);\r
268     */\r
269     int i, d=0;\r
270     int r = recv();\r
271     switch(r) {\r
272       case 1:\r
273         z = recv();\r
274         y = recv();\r
275         x = recv();\r
276         d = recv();\r
277         //portd(1,1);\r
278         conf(z, y, x, d);\r
279         //portd(1,0);\r
280         break;\r
281       case 2:\r
282         //fpga_interrupts(0);\r
283         //portd(1,1);\r
284         send(FISUA);\r
285         //portd(1,0);\r
286         //fpga_interrupts(1);\r
287         break;\r
288         /*\r
289       case 3:\r
290         //init_timer();\r
291         break;\r
292       case 4:\r
293         sending = 1;\r
294         break;\r
295       case 5:\r
296         sending = 0;\r
297         break;\r
298       case 6: {\r
299         int32_t local_interrupt_count = interrupt_count;\r
300         interrupt_count = 0;\r
301         send((local_interrupt_count >> 24) & 0xff);\r
302         send((local_interrupt_count >> 16) & 0xff);\r
303         send((local_interrupt_count >>  8) & 0xff);\r
304         send((local_interrupt_count >>  0) & 0xff);\r
305         fpga_interrupts(1);\r
306         break;\r
307       }\r
308         */\r
309         /*\r
310       default: {\r
311         if ((r & 0x80) == 0x80) {\r
312           switch (r & 0x44) {\r
313             case 0x44: z = recv(); break;\r
314             case 0x40: z++;        break;\r
315             case 0x04: z--;        break;\r
316           }\r
317           switch (r & 0x22) {\r
318             case 0x22: y = recv(); break;\r
319             case 0x20: y++;        break;\r
320             case 0x02: y--;        break;\r
321           }\r
322           switch (r & 0x11) {\r
323             case 0x11: x = recv(); break;\r
324             case 0x10: x++;        break;\r
325             case 0x01: x--;        break;\r
326           }\r
327           d = recv();\r
328           portd(1,1);\r
329           conf(z, y, x, d);\r
330           portd(1,0);\r
331           break;\r
332         }\r
333         die();\r
334       }\r
335         */\r
336     }\r
337   }\r
338   return 0;\r
339 \r
340 }  \r
341 \r