src-avr: Get USB on AVR working
[fw/altos] / src-avr / ao_usb_avr.c
1 /*
2  * Copyright © 2011 Keith Packard <keithp@keithp.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 2 of the License.
7  *
8  * This program is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License along
14  * with this program; if not, write to the Free Software Foundation, Inc.,
15  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
16  */
17
18 #include "ao.h"
19 #include "ao_usb.h"
20
21 //#define printf(format, args...)
22
23 struct ao_task __xdata ao_usb_task;
24
25 struct ao_usb_setup {
26         uint8_t         dir_type_recip;
27         uint8_t         request;
28         uint16_t        value;
29         uint16_t        index;
30         uint16_t        length;
31 } __xdata ao_usb_setup;
32
33 static __xdata uint8_t  ao_usb_ep0_state;
34 static const uint8_t * __xdata ao_usb_ep0_in_data;
35 static __xdata uint8_t  ao_usb_ep0_in_len;
36 static __xdata uint8_t  ao_usb_ep0_in_pending;
37 static __xdata uint8_t  ao_usb_addr_pending;
38 static __xdata uint8_t  ao_usb_ep0_in_buf[2];
39 static __xdata uint8_t  ao_usb_ep0_out_len;
40 static __xdata uint8_t *__xdata ao_usb_ep0_out_data;
41
42 static __xdata uint8_t  ao_usb_in_flushed;
43 static __xdata uint8_t  ao_usb_running;
44 static __xdata uint8_t  ao_usb_configuration;
45
46 void
47 ao_usb_set_address(uint8_t address)
48 {
49         UDADDR = (0 << ADDEN) | address;
50         ao_usb_running = 1;
51         ao_usb_addr_pending = 1;
52 }
53
54 #define EP_SIZE(s)      ((s) == 64 ? 0x30 :     \
55                         ((s) == 32 ? 0x20 :     \
56                         ((s) == 16 ? 0x10 :     \
57                                      0x00)))
58
59 static void
60 ao_usb_dump_ep(uint8_t ep)
61 {
62         UENUM = ep;
63         printf ("EP %d: UECONX %02x UECFG0X %02x UECFG1X %02x UEIENX %02x UESTA0X %02x UESTA1X %02X\n",
64                 ep, UECONX, UECFG0X, UECFG1X, UEIENX, UESTA0X, UESTA1X);
65 }
66
67 static void
68 ao_usb_set_ep0(void)
69 {
70         printf ("set_ep0\n");
71         /* Set the CONTROL max packet size, single buffered */
72         UENUM = 0;
73         UECONX = (1 << EPEN);                                   /* Enable */
74
75         UECFG0X = ((0 << EPTYPE0) |                             /* Control */
76                    (0 << EPDIR));                               /* Out (ish) */
77
78         UECFG1X = (EP_SIZE(AO_USB_CONTROL_SIZE) |               /* Size */
79                    (0 << EPBK0) |                               /* Single bank */
80                    (1 << ALLOC));
81
82         UEIENX = ((1 << RXSTPE) |                               /* Enable SETUP interrupt */
83                   (1 << RXOUTE));                               /* Enable OUT interrupt */
84
85 //      ao_usb_dump_ep(0);
86         ao_usb_addr_pending = 0;
87 }
88
89 static void
90 ao_usb_set_configuration(void)
91 {
92         /* Set the IN max packet size, double buffered */
93         UENUM = AO_USB_IN_EP;
94         UECONX = (1 << EPEN);                                   /* Enable */
95
96         UECFG0X = ((2 << EPTYPE0) |                             /* Bulk */
97                    (1 << EPDIR));                               /* In */
98
99         UECFG1X = (EP_SIZE(AO_USB_IN_SIZE) |                    /* Size */
100                    (1 << EPBK0) |                               /* Double bank */
101                    (1 << ALLOC));                               /* Allocate */
102
103         UEIENX = ((1 << TXINE));                                /* Enable IN complete interrupt */
104
105         ao_usb_dump_ep(AO_USB_IN_EP);
106
107         /* Set the OUT max packet size, double buffered */
108         UENUM = AO_USB_OUT_EP;
109         UECONX |= (1 << EPEN);                                  /* Enable */
110
111         UECFG0X = ((2 << EPTYPE0) |                             /* Bulk */
112                    (0 << EPDIR));                               /* Out */
113
114         UECFG1X = (EP_SIZE(AO_USB_OUT_SIZE) |                   /* Size */
115                    (1 << EPBK0) |                               /* Double bank */
116                    (1 << ALLOC));                               /* Allocate */
117
118         UEIENX = ((1 << RXOUTE));                               /* Enable OUT complete interrupt */
119
120         ao_usb_dump_ep(AO_USB_OUT_EP);
121 }
122
123 ISR(USB_GEN_vect)
124 {
125         ao_wakeup(&ao_usb_task);
126 }
127
128
129 __xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8};
130
131 /* Walk through the list of descriptors and find a match
132  */
133 static void
134 ao_usb_get_descriptor(uint16_t value)
135 {
136         const uint8_t           *__xdata descriptor;
137         __xdata uint8_t         type = value >> 8;
138         __xdata uint8_t         index = value;
139
140         descriptor = ao_usb_descriptors;
141         while (descriptor[0] != 0) {
142                 if (descriptor[1] == type && index-- == 0) {
143                         if (type == AO_USB_DESC_CONFIGURATION)
144                                 ao_usb_ep0_in_len = descriptor[2];
145                         else
146                                 ao_usb_ep0_in_len = descriptor[0];
147                         ao_usb_ep0_in_data = descriptor;
148                         break;
149                 }
150                 descriptor += descriptor[0];
151         }
152 }
153
154 static void
155 ao_usb_ep0_set_in_pending(uint8_t in_pending)
156 {
157         ao_usb_ep0_in_pending = in_pending;
158
159         if (in_pending) {
160                 UENUM = 0;
161                 UEIENX = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE));        /* Enable IN interrupt */
162         }
163 }
164
165 /* Send an IN data packet */
166 static void
167 ao_usb_ep0_flush(void)
168 {
169         __xdata uint8_t this_len;
170
171         cli();
172         UENUM = 0;
173         if (!(UEINTX & (1 << TXINI))) {
174                 printf("EP0 not accepting IN data\n");
175                 ao_usb_ep0_set_in_pending(1);
176         } else {
177                 this_len = ao_usb_ep0_in_len;
178                 if (this_len > AO_USB_CONTROL_SIZE)
179                         this_len = AO_USB_CONTROL_SIZE;
180
181                 ao_usb_ep0_in_len -= this_len;
182
183                 /* Set IN interrupt enable */
184                 if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE)
185                         ao_usb_ep0_set_in_pending(0);
186                 else
187                         ao_usb_ep0_set_in_pending(1);
188
189                 printf ("Flush EP0 len %d:", this_len);
190                 while (this_len--) {
191                         uint8_t c = *ao_usb_ep0_in_data++;
192                         printf(" %02x", c);
193                         UEDATX = c;
194                 }
195                 printf ("\n");
196
197                 /* Clear the TXINI bit to send the packet */
198                 UEINTX &= ~(1 << TXINI);
199         }
200         sei();
201 }
202
203 /* Read data from the ep0 OUT fifo */
204 static void
205 ao_usb_ep0_fill(uint8_t len, uint8_t ack)
206 {
207         if (len > ao_usb_ep0_out_len)
208                 len = ao_usb_ep0_out_len;
209         ao_usb_ep0_out_len -= len;
210
211 //      printf ("EP0 UEINTX %02x UEBCLX %d UEBCHX %d\n",
212 //              UEINTX, UEBCLX, UEBCHX);
213         /* Pull all of the data out of the packet */
214         printf ("Fill EP0 len %d:", len);
215         UENUM = 0;
216         while (len--) {
217                 uint8_t c = UEDATX;
218                 *ao_usb_ep0_out_data++ = c;
219                 printf (" %02x", c);
220         }
221         printf ("\n");
222
223         /* ACK the packet */
224         UEINTX &= ~ack;
225 }
226
227 void
228 ao_usb_ep0_queue_byte(uint8_t a)
229 {
230         ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a;
231 }
232
233 static void
234 ao_usb_ep0_setup(void)
235 {
236         /* Pull the setup packet out of the fifo */
237         ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup;
238         ao_usb_ep0_out_len = 8;
239         ao_usb_ep0_fill(8, (1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI));
240         if (ao_usb_ep0_out_len != 0) {
241                 printf ("invalid setup packet length\n");
242                 return;
243         }
244
245         /* Figure out how to ACK the setup packet */
246         if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) {
247                 if (ao_usb_setup.length)
248                         ao_usb_ep0_state = AO_USB_EP0_DATA_IN;
249                 else
250                         ao_usb_ep0_state = AO_USB_EP0_IDLE;
251         } else {
252                 if (ao_usb_setup.length)
253                         ao_usb_ep0_state = AO_USB_EP0_DATA_OUT;
254                 else
255                         ao_usb_ep0_state = AO_USB_EP0_IDLE;
256         }
257 /*
258         UENUM = 0;
259         if (ao_usb_ep0_state == AO_USB_EP0_IDLE)
260                 USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END;
261         else
262                 USBCS0 = USBCS0_CLR_OUTPKT_RDY;
263 */
264
265         ao_usb_ep0_in_data = ao_usb_ep0_in_buf;
266         ao_usb_ep0_in_len = 0;
267         switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) {
268         case AO_USB_TYPE_STANDARD:
269                 printf ("Standard setup packet\n");
270                 switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) {
271                 case AO_USB_RECIP_DEVICE:
272                         printf ("Device setup packet\n");
273                         switch(ao_usb_setup.request) {
274                         case AO_USB_REQ_GET_STATUS:
275                                 printf ("get status\n");
276                                 ao_usb_ep0_queue_byte(0);
277                                 ao_usb_ep0_queue_byte(0);
278                                 break;
279                         case AO_USB_REQ_SET_ADDRESS:
280                                 printf ("set address %d\n", ao_usb_setup.value);
281                                 ao_usb_set_address(ao_usb_setup.value);
282                                 break;
283                         case AO_USB_REQ_GET_DESCRIPTOR:
284                                 printf ("get descriptor %d\n", ao_usb_setup.value);
285                                 ao_usb_get_descriptor(ao_usb_setup.value);
286                                 break;
287                         case AO_USB_REQ_GET_CONFIGURATION:
288                                 printf ("get configuration %d\n", ao_usb_configuration);
289                                 ao_usb_ep0_queue_byte(ao_usb_configuration);
290                                 break;
291                         case AO_USB_REQ_SET_CONFIGURATION:
292                                 ao_usb_configuration = ao_usb_setup.value;
293                                 printf ("set configuration %d\n", ao_usb_configuration);
294                                 ao_usb_set_configuration();
295                                 break;
296                         }
297                         break;
298                 case AO_USB_RECIP_INTERFACE:
299 #ifndef AVR
300                         #pragma disable_warning 110
301 #endif
302                         printf ("Interface setup packet\n");
303                         switch(ao_usb_setup.request) {
304                         case AO_USB_REQ_GET_STATUS:
305                                 ao_usb_ep0_queue_byte(0);
306                                 ao_usb_ep0_queue_byte(0);
307                                 break;
308                         case AO_USB_REQ_GET_INTERFACE:
309                                 ao_usb_ep0_queue_byte(0);
310                                 break;
311                         case AO_USB_REQ_SET_INTERFACE:
312                                 break;
313                         }
314                         break;
315                 case AO_USB_RECIP_ENDPOINT:
316                         printf ("Endpoint setup packet\n");
317                         switch(ao_usb_setup.request) {
318                         case AO_USB_REQ_GET_STATUS:
319                                 ao_usb_ep0_queue_byte(0);
320                                 ao_usb_ep0_queue_byte(0);
321                                 break;
322                         }
323                         break;
324                 }
325                 break;
326         case AO_USB_TYPE_CLASS:
327                 printf ("Class setup packet\n");
328                 switch (ao_usb_setup.request) {
329                 case SET_LINE_CODING:
330                         printf ("set line coding\n");
331                         ao_usb_ep0_out_len = 7;
332                         ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding;
333                         break;
334                 case GET_LINE_CODING:
335                         printf ("get line coding\n");
336                         ao_usb_ep0_in_len = 7;
337                         ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding;
338                         break;
339                 case SET_CONTROL_LINE_STATE:
340                         break;
341                 }
342                 break;
343         }
344         if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) {
345                 if (ao_usb_setup.length < ao_usb_ep0_in_len)
346                         ao_usb_ep0_in_len = ao_usb_setup.length;
347                 printf ("Start ep0 in delivery %d\n", ao_usb_ep0_in_len);
348                 ao_usb_ep0_set_in_pending(1);
349         }
350 }
351
352 /* End point 0 receives all of the control messages. */
353 static void
354 ao_usb_ep0(void)
355 {
356         uint8_t intx, udint;
357
358         printf ("usb task started\n");
359         ao_usb_ep0_state = AO_USB_EP0_IDLE;
360         for (;;) {
361                 cli();
362                 for (;;) {
363                         udint = UDINT;
364                         UDINT = 0;
365 //                      printf ("UDINT %02x\n", udint);
366                         if (udint & (1 << EORSTI)) {
367                                 ao_usb_configuration = 0;
368                                 ao_usb_set_ep0();
369                         }
370                         UENUM = 0;
371                         intx = UEINTX;
372 //                      printf ("UEINTX %02x\n", intx);
373                         if (intx & ((1 << RXSTPI) | (1 << RXOUTI)))
374                                 break;
375                         if ((intx & (1 << TXINI))) {
376                                 if (ao_usb_ep0_in_pending)
377                                         break;
378                                 else
379                                 {
380                                         if (ao_usb_addr_pending) {
381                                                 UDADDR |= (1 << ADDEN);
382                                                 ao_usb_addr_pending = 0;
383                                         }
384                                         UEIENX = ((1 << RXSTPE) | (1 << RXOUTE));       /* Disable IN interrupt */
385                                 }
386                         }
387 //                      printf ("usb task sleeping...\n");
388                         ao_sleep(&ao_usb_task);
389                 }
390                 sei();
391 //              printf ("UEINTX for ep0 is %02x\n", intx);
392                 if (intx & (1 << RXSTPI)) {
393                         ao_usb_ep0_setup();
394                 }
395                 if (intx & (1 << RXOUTI)) {
396                         ao_usb_ep0_fill(UEBCLX, (1 << RXOUTI));
397                         ao_usb_ep0_set_in_pending(1);
398                 }
399                 if (intx & (1 << TXINI) && ao_usb_ep0_in_pending) {
400                         printf ("continue sending ep0 IN data\n");
401                         ao_usb_ep0_flush();
402                 }
403         }
404 }
405
406 /* Wait for a free IN buffer */
407 static void
408 ao_usb_in_wait(void)
409 {
410         for (;;) {
411                 /* Check if the current buffer is writable */
412                 UENUM = AO_USB_IN_EP;
413                 if (UEINTX & (1 << RWAL))
414                         break;
415
416                 /* Wait for an IN buffer to be ready */
417                 for (;;) {
418                         UENUM = AO_USB_IN_EP;
419                         if ((UEINTX & (1 << TXINI)))
420                                 break;
421                         ao_sleep(&ao_usb_in_flushed);
422                 }
423                 /* Ack the interrupt */
424                 UEINTX &= ~(1 << TXINI);
425         }
426 }
427
428 /* Queue the current IN buffer for transmission */
429 static void
430 ao_usb_in_send(void)
431 {
432         UENUM = AO_USB_IN_EP;
433         UEINTX &= ~(1 << FIFOCON);
434 }
435
436 void
437 ao_usb_flush(void) __critical
438 {
439         if (!ao_usb_running)
440                 return;
441
442         /* Anytime we've sent a character since
443          * the last time we flushed, we'll need
444          * to send a packet -- the only other time
445          * we would send a packet is when that
446          * packet was full, in which case we now
447          * want to send an empty packet
448          */
449         if (!ao_usb_in_flushed) {
450                 ao_usb_in_flushed = 1;
451                 ao_usb_in_wait();
452                 ao_usb_in_send();
453         }
454 }
455
456 void
457 ao_usb_putchar(char c) __critical __reentrant
458 {
459         if (!ao_usb_running)
460                 return;
461
462         ao_usb_in_flushed = 0;
463
464         ao_usb_in_wait();
465
466         /* Queue a byte */
467         UENUM = AO_USB_IN_EP;
468         UEDATX = c;
469
470         /* Send the packet when full */
471         if ((UEINTX & (1 << RWAL)) == 0)
472                 ao_usb_in_send();
473 }
474
475 static char
476 _ao_usb_pollchar(void)
477 {
478         char c;
479         uint8_t intx;
480
481         for (;;) {
482                 UENUM = AO_USB_OUT_EP;
483                 intx = UEINTX;
484                 printf("usb_pollchar UEINTX %02d\n", intx);
485                 if (intx & (1 << RWAL))
486                         break;
487
488                 if (intx & (1 << FIFOCON)) {
489                         /* Ack the last packet */
490                         UEINTX &= ~(1 << FIFOCON);
491                 }
492
493                 /* Check to see if a packet has arrived */
494                 if ((intx & (1 << RXOUTI)) == 0)
495                         return AO_READ_AGAIN;
496
497                 /* Ack the interrupt */
498                 UEINTX &= ~(1 << RXOUTI);
499         }
500
501         /* Pull a character out of the fifo */
502         c = UEDATX;
503         return c;
504 }
505
506 char
507 ao_usb_pollchar(void)
508 {
509         char    c;
510         cli();
511         c = _ao_usb_pollchar();
512         sei();
513         return c;
514 }
515
516 char
517 ao_usb_getchar(void) __critical
518 {
519         char    c;
520
521         cli();
522         while ((c = ao_usb_pollchar()) == AO_READ_AGAIN)
523                 ao_sleep(&ao_stdin_ready);
524         sei();
525         return c;
526 }
527
528 /* Endpoint interrupt */
529 ISR(USB_COM_vect)
530 {
531         uint8_t i = UEINT;
532
533         ao_led_toggle(AO_LED_RED);
534         UEINT = 0;
535         if (i & (1 << 0))
536                 ao_wakeup(&ao_usb_task);
537         if (i & (1 << AO_USB_IN_EP))
538                 ao_wakeup(&ao_usb_in_flushed);
539         if (i & (1 << AO_USB_OUT_EP))
540                 ao_wakeup(&ao_stdin_ready);
541 }
542
543 #if AVR_VCC_5V
544 #define AO_PAD_REGULATOR_INIT   (1 << UVREGE)   /* Turn on pad regulator */
545 #endif
546 #if AVR_VCC_3V3
547 #define AO_PAD_REGULATOR_INIT   0               /* Turn off pad regulator */
548 #endif
549
550 #if AVR_CLOCK == 16000000UL
551 #define AO_USB_PLL_INPUT_PRESCALER      (1 << PINDIV)   /* Divide 16MHz clock by 2 */
552 #endif
553 #if AVR_CLOCK == 8000000UL
554 #define AO_USB_PLL_INPUT_PRESCALER      0               /* Don't divide clock */
555 #endif
556
557 void
558 ao_usb_disable(void)
559 {
560         /* Unplug from the bus */
561         UDCON = (1 << DETACH);
562
563         /* Disable the interface */
564         USBCON = 0;
565
566         /* Disable the PLL */
567         PLLCSR = 0;
568
569         /* Turn off the pad regulator */
570         UHWCON = 0;
571 }
572
573 #define AO_USB_CON ((1 << USBE) |       /* USB enable */ \
574                     (0 << RSTCPU) |     /* do not reset CPU */  \
575                     (0 << LSM) |        /* Full speed mode */   \
576                     (0 << RMWKUP))      /* no remote wake-up */ \
577
578 void
579 ao_usb_enable(void)
580 {
581         /* Configure pad regulator */
582         UHWCON = AO_PAD_REGULATOR_INIT;
583
584         /* Enable USB device, but freeze the clocks until initialized */
585         USBCON = AO_USB_CON | (1 <<FRZCLK);
586
587         /* Enable PLL with appropriate divider */
588         PLLCSR = AO_USB_PLL_INPUT_PRESCALER | (1 << PLLE);
589
590         /* Wait for PLL to lock */
591         loop_until_bit_is_set(PLLCSR, (1 << PLOCK));
592
593         /* Enable USB, enable the VBUS pad */
594         USBCON = AO_USB_CON | (1 << OTGPADE);
595
596         /* Enable global interrupts */
597         UDIEN = (1 << EORSTE);          /* End of reset interrupt */
598
599         ao_usb_configuration = 0;
600
601         printf ("ao_usb_enable\n");
602
603         UDCON = (0 << DETACH);  /* Clear the DETACH bit to plug into the bus */
604 }
605
606 struct ao_task __xdata ao_usb_echo_task;
607
608 static void
609 ao_usb_echo(void)
610 {
611         char    c;
612
613         for (;;) {
614                 c = ao_usb_getchar();
615                 ao_usb_putchar(c);
616                 ao_usb_flush();
617         }
618 }
619
620 void
621 ao_usb_init(void)
622 {
623         ao_usb_enable();
624
625         printf ("ao_usb_init\n");
626         ao_add_task(&ao_usb_task, ao_usb_ep0, "usb");
627         ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo");
628 //      ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
629 }