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