c1264e7ac67be7ecd87f64b21c2436b6d567cef4
[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 volatile int32_t upper = 0;\r
17 \r
18 int err = 0;\r
19 \r
20 void initUART0(unsigned int baudRate, unsigned int doubleRate) {\r
21   UBRRHI  = (((baudRate) >> 8) & 0x000F); \r
22   UBRR0   = ((baudRate) & 0x00FF); \r
23   UCSR0B |= ((1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0)); \r
24 \r
25   if (doubleRate)\r
26     UCSR0A |=  (1 << U2X0);\r
27   else\r
28     UCSR0A &= ~(1 << U2X0);\r
29 }\r
30 \r
31 #define BUFSIZE (1024)\r
32 \r
33 long int numread = 0;\r
34 inline void cts(int c) {\r
35   numread++;\r
36   if (c) {\r
37     PORTE &= ~(1 << 7);\r
38   } else {\r
39     PORTE |= (1 << 7);\r
40   }\r
41 }\r
42 \r
43 \r
44 static volatile int sending = 0;\r
45 static volatile int32_t interrupt_count = 0;\r
46 \r
47 // RECV //////////////////////////////////////////////////////////////////////////////\r
48 \r
49 char read_buf[BUFSIZE];\r
50 volatile int read_buf_head;\r
51 volatile int read_buf_tail;\r
52 char write_buf[BUFSIZE];\r
53 volatile int write_buf_head;\r
54 volatile int write_buf_tail;\r
55 \r
56 inline int inc(int x) { x++; if (x>=BUFSIZE) x=0; return x; }\r
57 inline int read_full() { return inc(read_buf_tail)==read_buf_head; }\r
58 inline int abs(int x) { return x<0 ? -x : x; }\r
59 inline int read_size() { return read_buf_tail<read_buf_head ? (read_buf_head-read_buf_tail) : (read_buf_tail-read_buf_head); }\r
60 inline int read_empty() { return read_buf_head==read_buf_tail; }\r
61 inline int read_nearlyFull() {\r
62   if (read_buf_tail==read_buf_head) return 0;\r
63   if (read_buf_tail < read_buf_head) return (read_buf_head-read_buf_tail) < (BUFSIZE/2);\r
64   return (read_buf_tail-read_buf_head) > (BUFSIZE/2);\r
65 }\r
66 \r
67 inline int write_full() { return inc(write_buf_tail)==write_buf_head; }\r
68 inline int write_empty() { return write_buf_head==write_buf_tail; }\r
69 inline int write_nearlyFull() {\r
70   if (write_buf_tail==write_buf_head) return 0;\r
71   if (write_buf_tail < write_buf_head) return (write_buf_head-write_buf_tail) < (BUFSIZE/2);\r
72   return (write_buf_tail-write_buf_head) > (BUFSIZE/2);\r
73 }\r
74 \r
75 int32_t timer = 0;\r
76 \r
77 inline char recv() {\r
78   int q;\r
79   char ret;\r
80 \r
81   PORTE |=  (1<<3);\r
82   while(read_empty()) cts(1);\r
83   PORTE &= ~(1<<3);\r
84 \r
85   ret = read_buf[read_buf_head];\r
86   read_buf_head = inc(read_buf_head);\r
87   if (!read_nearlyFull()) cts(1);\r
88   return ret;\r
89 }\r
90 \r
91 // Interrupt Handlers //////////////////////////////////////////////////////////////////////////////\r
92 \r
93 ISR(SIG_UART0_DATA) {\r
94   if (write_empty()) {\r
95     UCSR0B &= ~(1 << UDRIE0);\r
96     return;\r
97   }\r
98   char ret = write_buf[write_buf_head];\r
99   write_buf_head = inc(write_buf_head);\r
100   UDR0 = (int)ret;\r
101   sei();\r
102 }\r
103 \r
104 void send(char c) {\r
105   PORTE |=  (1<<2);\r
106   while (write_full());\r
107   PORTE &= ~(1<<2);\r
108   write_buf[write_buf_tail] = c;\r
109   write_buf_tail = inc(write_buf_tail);\r
110   UCSR0B |= (1 << UDRIE0);\r
111 }\r
112 \r
113 \r
114 void fpga_interrupts(int on) {\r
115   if (on) {\r
116     //FISUA = 0x1;\r
117     FISCR = 0x80;\r
118     FISUA = 0x01;\r
119   } else {\r
120     FISUA = 0;\r
121     FISCR = 0;\r
122   }\r
123 }\r
124 \r
125 inline void conf(int z, int y, int x, int d) {\r
126   FPGAX = x;\r
127   FPGAY = y;\r
128   FPGAZ = z;\r
129   FPGAD = d;\r
130 }\r
131 \r
132 #define TIMERVAL 100\r
133 \r
134 ISR(SIG_FPGA_INTERRUPT0) { \r
135   interrupt_count++;\r
136   sei();\r
137 }\r
138 \r
139 volatile int dead = 0;\r
140 \r
141 ISR(SIG_OVERFLOW1) { \r
142   upper = upper + 1;\r
143 \r
144   if (!dead) {\r
145     if (PORTE & (1<<5)) PORTE &= ~(1<<5);\r
146     else                PORTE |=  (1<<5);\r
147   }\r
148 \r
149   TCNT1 = 0;\r
150   sei();\r
151 }\r
152 \r
153 //void die() { dead = 1; cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { } }\r
154 \r
155 void die(int two, int three, int five) {\r
156   dead = 1;\r
157   PORTE &~ ((1<<2) | (1<<3) | (1<<5));\r
158   if (two) PORTE |= (1<<2);\r
159   if (three) PORTE |= (1<<3);\r
160   if (five) PORTE |= (1<<5);\r
161   while(1) { }\r
162 }\r
163 \r
164 ISR(SIG_UART0_RECV) {\r
165   if (UCSR0A & (1 << FE0))   die(0, 0, 1);\r
166   if ((UCSR0A & (1 << OR0))) die(1, 1, 1);\r
167   if (read_full()) die(1, 0, 1);\r
168 \r
169   read_buf[read_buf_tail] = UDR0;\r
170   read_buf_tail = inc(read_buf_tail);\r
171   if (read_nearlyFull()) cts(0);\r
172   SREG |= 0x80;\r
173   sei();\r
174 }\r
175 \r
176 inline int hex(char c) {\r
177   if (c >= '0' && c <= '9') return (c - '0');\r
178   if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
179   if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
180   return -1;\r
181 }\r
182 \r
183 int readFPGA() {\r
184   fpga_interrupts(0);\r
185   int ret = FISUA;\r
186   fpga_interrupts(1);\r
187   return ret;\r
188 }\r
189 \r
190 int main() {\r
191   DDRE  = (1<<7) | (1<<5) | (1<<3) | (1<<2);\r
192   PORTE = 0;\r
193 \r
194   PORTE |=  (1<<5);\r
195 \r
196   read_buf_head = 0;\r
197   read_buf_tail = 0;\r
198   write_buf_head = 0;\r
199   write_buf_tail = 0;\r
200   initUART0(1, 0);  //for slow board\r
201 \r
202   EIMF = 0xFF;\r
203   SREG = INT0;\r
204   sei();\r
205 \r
206   TCNT1 = 0;\r
207   TIFR&=~(1<<TOV1);\r
208   TIMSK|=(1<<TOIE1);\r
209   TCCR1B = 3;\r
210 \r
211   cts(0);\r
212   cts(1);\r
213 \r
214   int x=0, y=0, z=0;\r
215   int flag=0;\r
216   for(;;) {\r
217     int i, d=0;\r
218     int r = recv();\r
219     switch(r) {\r
220       case 0:\r
221         send('O');\r
222         send('B');\r
223         send('I');\r
224         send('T');\r
225         send('S');\r
226         fpga_interrupts(1);\r
227         if (flag) die(0, 1, 1);\r
228         break;\r
229 \r
230       case 1:\r
231         z = recv();\r
232         y = recv();\r
233         x = recv();\r
234         d = recv();\r
235         conf(z, y, x, d);\r
236         break;\r
237 \r
238       case 2:\r
239         flag=1;\r
240         send(readFPGA());\r
241         break;\r
242 \r
243       case 3: {\r
244         int32_t local_interrupt_count = interrupt_count;\r
245         interrupt_count = 0;\r
246         send((local_interrupt_count >> 24) & 0xff);\r
247         send((local_interrupt_count >> 16) & 0xff);\r
248         send((local_interrupt_count >>  8) & 0xff);\r
249         send((local_interrupt_count >>  0) & 0xff);\r
250  \r
251         int32_t local_timer = TCNT1;\r
252         int32_t local_upper = upper;\r
253         TCCR1B = 0;\r
254         TIFR&=~(1<<TOV1);\r
255         TIMSK|=(1<<TOIE1);\r
256         upper = 0;\r
257         TCNT1 = 0;\r
258         TCCR1B = 3;\r
259         send((local_upper >>  8) & 0xff);\r
260         send((local_upper >>  0) & 0xff);\r
261         send((local_timer >>  8) & 0xff);\r
262         send((local_timer >>  0) & 0xff);\r
263         break;\r
264       }\r
265 \r
266         /*\r
267       case 3:\r
268         //init_timer();\r
269         break;\r
270       case 4:\r
271         sending = 1;\r
272         break;\r
273       case 5:\r
274         sending = 0;\r
275         break;\r
276         */\r
277     }\r
278   }\r
279   return 0;\r
280 \r
281 }  \r
282 \r