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 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   fpga_interrupts(1);\r
137   sei();\r
138 }\r
139 \r
140 volatile int dead = 0;\r
141 \r
142 ISR(SIG_OVERFLOW1) { \r
143   upper = upper + 1;\r
144 \r
145   if (!dead) {\r
146     if (PORTE & (1<<5)) PORTE &= ~(1<<5);\r
147     else                PORTE |=  (1<<5);\r
148   }\r
149 \r
150   TCNT1 = 0;\r
151   sei();\r
152 }\r
153 \r
154 //void die() { dead = 1; cli(); PORTE|=(1<<5); _delay_ms(2000); while(1) { } }\r
155 \r
156 void die(int two, int three, int five) {\r
157   dead = 1;\r
158   PORTE &~ ((1<<2) | (1<<3) | (1<<5));\r
159   if (two) PORTE |= (1<<2);\r
160   if (three) PORTE |= (1<<3);\r
161   if (five) PORTE |= (1<<5);\r
162   while(1) { }\r
163 }\r
164 \r
165 ISR(SIG_UART0_RECV) {\r
166   if (UCSR0A & (1 << FE0))   die(0, 0, 1);\r
167   if ((UCSR0A & (1 << OR0))) die(0, 1, 1);\r
168   if (read_full()) die(1, 0, 1);\r
169 \r
170   read_buf[read_buf_tail] = UDR0;\r
171   read_buf_tail = inc(read_buf_tail);\r
172   if (read_nearlyFull()) cts(0);\r
173   SREG |= 0x80;\r
174   sei();\r
175 }\r
176 \r
177 inline int hex(char c) {\r
178   if (c >= '0' && c <= '9') return (c - '0');\r
179   if (c >= 'a' && c <= 'f') return ((c - 'a') + 0xa);\r
180   if (c >= 'A' && c <= 'F') return ((c - 'A') + 0xa);\r
181   return -1;\r
182 }\r
183 \r
184 int readFPGA() {\r
185   fpga_interrupts(0);\r
186   int ret = FISUA;\r
187   fpga_interrupts(1);\r
188   return ret;\r
189 }\r
190 \r
191 int main() {\r
192   DDRE  = (1<<7) | (1<<5) | (1<<3) | (1<<2);\r
193   PORTE = 0;\r
194 \r
195   PORTE |=  (1<<5);\r
196 \r
197   read_buf_head = 0;\r
198   read_buf_tail = 0;\r
199   write_buf_head = 0;\r
200   write_buf_tail = 0;\r
201   initUART0(1, 0);  //for slow board\r
202 \r
203   EIMF = 0xFF;\r
204   SREG = INT0;\r
205   sei();\r
206 \r
207   TCNT1 = 0;\r
208   TIFR&=~(1<<TOV1);\r
209   TIMSK|=(1<<TOIE1);\r
210   TCCR1B = 3;\r
211 \r
212   cts(0);\r
213   cts(1);\r
214 \r
215   int x=0, y=0, z=0;\r
216   int flag=0;\r
217   for(;;) {\r
218     int i, d=0;\r
219     int r = recv();\r
220     switch(r) {\r
221       case 0:\r
222         send('O');\r
223         send('B');\r
224         send('I');\r
225         send('T');\r
226         send('S');\r
227         fpga_interrupts(1);\r
228         if (flag) die(1, 1, 1);\r
229         break;\r
230 \r
231       case 1:\r
232         z = recv();\r
233         y = recv();\r
234         x = recv();\r
235         d = recv();\r
236         conf(z, y, x, d);\r
237         break;\r
238 \r
239       case 2:\r
240         flag=1;\r
241         send(readFPGA());\r
242         break;\r
243 \r
244       case 3: {\r
245         int32_t local_interrupt_count = interrupt_count;\r
246         interrupt_count = 0;\r
247         send((local_interrupt_count >> 24) & 0xff);\r
248         send((local_interrupt_count >> 16) & 0xff);\r
249         send((local_interrupt_count >>  8) & 0xff);\r
250         send((local_interrupt_count >>  0) & 0xff);\r
251  \r
252         int32_t local_timer = TCNT1;\r
253         int32_t local_upper = upper;\r
254         TCCR1B = 0;\r
255         TIFR&=~(1<<TOV1);\r
256         TIMSK|=(1<<TOIE1);\r
257         upper = 0;\r
258         TCNT1 = 0;\r
259         TCCR1B = 3;\r
260         send((local_upper >>  8) & 0xff);\r
261         send((local_upper >>  0) & 0xff);\r
262         send((local_timer >>  8) & 0xff);\r
263         send((local_timer >>  0) & 0xff);\r
264         break;\r
265       }\r
266 \r
267         /*\r
268       case 3:\r
269         //init_timer();\r
270         break;\r
271       case 4:\r
272         sending = 1;\r
273         break;\r
274       case 5:\r
275         sending = 0;\r
276         break;\r
277         */\r
278     }\r
279   }\r
280   return 0;\r
281 \r
282 }  \r
283 \r