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