MIDI Stop Controller V1.0 suitable for driving Hauptwerk digital organ software. Written for the KL25Z uses BusInOut and will drive up to 16 illuminated push buttons each switch uses a single I/O pin to both drive the LED and act as a switch input. Pressing a button will alternately send MIDI note on / off messages and turn the LED on or off. If corresponding MIDI note on/off messages are received these will be used to drive the LEDs in preference to the locally generated LED signals. The MIDI channel used to send can be selected by jumpers on 4 pins of the J2 header.
USBDevice/USBHAL_KL25Z.cpp@0:aac55e1fc12f, 2013-09-14 (annotated)
- Committer:
- djbottrill
- Date:
- Sat Sep 14 21:32:06 2013 +0000
- Revision:
- 0:aac55e1fc12f
V1.0 MIDI Stop Controller
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
djbottrill | 0:aac55e1fc12f | 1 | /* Copyright (c) 2010-2011 mbed.org, MIT License |
djbottrill | 0:aac55e1fc12f | 2 | * |
djbottrill | 0:aac55e1fc12f | 3 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
djbottrill | 0:aac55e1fc12f | 4 | * and associated documentation files (the "Software"), to deal in the Software without |
djbottrill | 0:aac55e1fc12f | 5 | * restriction, including without limitation the rights to use, copy, modify, merge, publish, |
djbottrill | 0:aac55e1fc12f | 6 | * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the |
djbottrill | 0:aac55e1fc12f | 7 | * Software is furnished to do so, subject to the following conditions: |
djbottrill | 0:aac55e1fc12f | 8 | * |
djbottrill | 0:aac55e1fc12f | 9 | * The above copyright notice and this permission notice shall be included in all copies or |
djbottrill | 0:aac55e1fc12f | 10 | * substantial portions of the Software. |
djbottrill | 0:aac55e1fc12f | 11 | * |
djbottrill | 0:aac55e1fc12f | 12 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
djbottrill | 0:aac55e1fc12f | 13 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
djbottrill | 0:aac55e1fc12f | 14 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
djbottrill | 0:aac55e1fc12f | 15 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
djbottrill | 0:aac55e1fc12f | 16 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
djbottrill | 0:aac55e1fc12f | 17 | */ |
djbottrill | 0:aac55e1fc12f | 18 | |
djbottrill | 0:aac55e1fc12f | 19 | #if defined(TARGET_KL25Z) |
djbottrill | 0:aac55e1fc12f | 20 | |
djbottrill | 0:aac55e1fc12f | 21 | #include "USBHAL.h" |
djbottrill | 0:aac55e1fc12f | 22 | |
djbottrill | 0:aac55e1fc12f | 23 | USBHAL * USBHAL::instance; |
djbottrill | 0:aac55e1fc12f | 24 | |
djbottrill | 0:aac55e1fc12f | 25 | static volatile int epComplete = 0; |
djbottrill | 0:aac55e1fc12f | 26 | |
djbottrill | 0:aac55e1fc12f | 27 | // Convert physical endpoint number to register bit |
djbottrill | 0:aac55e1fc12f | 28 | #define EP(endpoint) (1<<(endpoint)) |
djbottrill | 0:aac55e1fc12f | 29 | |
djbottrill | 0:aac55e1fc12f | 30 | // Convert physical to logical |
djbottrill | 0:aac55e1fc12f | 31 | #define PHY_TO_LOG(endpoint) ((endpoint)>>1) |
djbottrill | 0:aac55e1fc12f | 32 | |
djbottrill | 0:aac55e1fc12f | 33 | // Get endpoint direction |
djbottrill | 0:aac55e1fc12f | 34 | #define IN_EP(endpoint) ((endpoint) & 1U ? true : false) |
djbottrill | 0:aac55e1fc12f | 35 | #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true) |
djbottrill | 0:aac55e1fc12f | 36 | |
djbottrill | 0:aac55e1fc12f | 37 | #define BD_OWN_MASK (1<<7) |
djbottrill | 0:aac55e1fc12f | 38 | #define BD_DATA01_MASK (1<<6) |
djbottrill | 0:aac55e1fc12f | 39 | #define BD_KEEP_MASK (1<<5) |
djbottrill | 0:aac55e1fc12f | 40 | #define BD_NINC_MASK (1<<4) |
djbottrill | 0:aac55e1fc12f | 41 | #define BD_DTS_MASK (1<<3) |
djbottrill | 0:aac55e1fc12f | 42 | #define BD_STALL_MASK (1<<2) |
djbottrill | 0:aac55e1fc12f | 43 | |
djbottrill | 0:aac55e1fc12f | 44 | #define TX 1 |
djbottrill | 0:aac55e1fc12f | 45 | #define RX 0 |
djbottrill | 0:aac55e1fc12f | 46 | #define ODD 0 |
djbottrill | 0:aac55e1fc12f | 47 | #define EVEN 1 |
djbottrill | 0:aac55e1fc12f | 48 | // this macro waits a physical endpoint number |
djbottrill | 0:aac55e1fc12f | 49 | #define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd))) |
djbottrill | 0:aac55e1fc12f | 50 | |
djbottrill | 0:aac55e1fc12f | 51 | #define SETUP_TOKEN 0x0D |
djbottrill | 0:aac55e1fc12f | 52 | #define IN_TOKEN 0x09 |
djbottrill | 0:aac55e1fc12f | 53 | #define OUT_TOKEN 0x01 |
djbottrill | 0:aac55e1fc12f | 54 | #define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F) |
djbottrill | 0:aac55e1fc12f | 55 | |
djbottrill | 0:aac55e1fc12f | 56 | // for each endpt: 8 bytes |
djbottrill | 0:aac55e1fc12f | 57 | typedef struct BDT { |
djbottrill | 0:aac55e1fc12f | 58 | uint8_t info; // BD[0:7] |
djbottrill | 0:aac55e1fc12f | 59 | uint8_t dummy; // RSVD: BD[8:15] |
djbottrill | 0:aac55e1fc12f | 60 | uint16_t byte_count; // BD[16:32] |
djbottrill | 0:aac55e1fc12f | 61 | uint32_t address; // Addr |
djbottrill | 0:aac55e1fc12f | 62 | } BDT; |
djbottrill | 0:aac55e1fc12f | 63 | |
djbottrill | 0:aac55e1fc12f | 64 | |
djbottrill | 0:aac55e1fc12f | 65 | // there are: |
djbottrill | 0:aac55e1fc12f | 66 | // * 16 bidirectionnal endpt -> 32 physical endpt |
djbottrill | 0:aac55e1fc12f | 67 | // * as there are ODD and EVEN buffer -> 32*2 bdt |
djbottrill | 0:aac55e1fc12f | 68 | __attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2]; |
djbottrill | 0:aac55e1fc12f | 69 | uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2]; |
djbottrill | 0:aac55e1fc12f | 70 | uint8_t * endpoint_buffer_iso[2*2]; |
djbottrill | 0:aac55e1fc12f | 71 | |
djbottrill | 0:aac55e1fc12f | 72 | static uint8_t set_addr = 0; |
djbottrill | 0:aac55e1fc12f | 73 | static uint8_t addr = 0; |
djbottrill | 0:aac55e1fc12f | 74 | |
djbottrill | 0:aac55e1fc12f | 75 | static uint32_t Data1 = 0x55555555; |
djbottrill | 0:aac55e1fc12f | 76 | |
djbottrill | 0:aac55e1fc12f | 77 | static uint32_t frameNumber() { |
djbottrill | 0:aac55e1fc12f | 78 | return((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF)); |
djbottrill | 0:aac55e1fc12f | 79 | } |
djbottrill | 0:aac55e1fc12f | 80 | |
djbottrill | 0:aac55e1fc12f | 81 | uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) { |
djbottrill | 0:aac55e1fc12f | 82 | return 0; |
djbottrill | 0:aac55e1fc12f | 83 | } |
djbottrill | 0:aac55e1fc12f | 84 | |
djbottrill | 0:aac55e1fc12f | 85 | USBHAL::USBHAL(void) { |
djbottrill | 0:aac55e1fc12f | 86 | // Disable IRQ |
djbottrill | 0:aac55e1fc12f | 87 | NVIC_DisableIRQ(USB0_IRQn); |
djbottrill | 0:aac55e1fc12f | 88 | |
djbottrill | 0:aac55e1fc12f | 89 | // fill in callback array |
djbottrill | 0:aac55e1fc12f | 90 | epCallback[0] = &USBHAL::EP1_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 91 | epCallback[1] = &USBHAL::EP1_IN_callback; |
djbottrill | 0:aac55e1fc12f | 92 | epCallback[2] = &USBHAL::EP2_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 93 | epCallback[3] = &USBHAL::EP2_IN_callback; |
djbottrill | 0:aac55e1fc12f | 94 | epCallback[4] = &USBHAL::EP3_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 95 | epCallback[5] = &USBHAL::EP3_IN_callback; |
djbottrill | 0:aac55e1fc12f | 96 | epCallback[6] = &USBHAL::EP4_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 97 | epCallback[7] = &USBHAL::EP4_IN_callback; |
djbottrill | 0:aac55e1fc12f | 98 | epCallback[8] = &USBHAL::EP5_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 99 | epCallback[9] = &USBHAL::EP5_IN_callback; |
djbottrill | 0:aac55e1fc12f | 100 | epCallback[10] = &USBHAL::EP6_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 101 | epCallback[11] = &USBHAL::EP6_IN_callback; |
djbottrill | 0:aac55e1fc12f | 102 | epCallback[12] = &USBHAL::EP7_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 103 | epCallback[13] = &USBHAL::EP7_IN_callback; |
djbottrill | 0:aac55e1fc12f | 104 | epCallback[14] = &USBHAL::EP8_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 105 | epCallback[15] = &USBHAL::EP8_IN_callback; |
djbottrill | 0:aac55e1fc12f | 106 | epCallback[16] = &USBHAL::EP9_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 107 | epCallback[17] = &USBHAL::EP9_IN_callback; |
djbottrill | 0:aac55e1fc12f | 108 | epCallback[18] = &USBHAL::EP10_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 109 | epCallback[19] = &USBHAL::EP10_IN_callback; |
djbottrill | 0:aac55e1fc12f | 110 | epCallback[20] = &USBHAL::EP11_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 111 | epCallback[21] = &USBHAL::EP11_IN_callback; |
djbottrill | 0:aac55e1fc12f | 112 | epCallback[22] = &USBHAL::EP12_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 113 | epCallback[23] = &USBHAL::EP12_IN_callback; |
djbottrill | 0:aac55e1fc12f | 114 | epCallback[24] = &USBHAL::EP13_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 115 | epCallback[25] = &USBHAL::EP13_IN_callback; |
djbottrill | 0:aac55e1fc12f | 116 | epCallback[26] = &USBHAL::EP14_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 117 | epCallback[27] = &USBHAL::EP14_IN_callback; |
djbottrill | 0:aac55e1fc12f | 118 | epCallback[28] = &USBHAL::EP15_OUT_callback; |
djbottrill | 0:aac55e1fc12f | 119 | epCallback[29] = &USBHAL::EP15_IN_callback; |
djbottrill | 0:aac55e1fc12f | 120 | |
djbottrill | 0:aac55e1fc12f | 121 | |
djbottrill | 0:aac55e1fc12f | 122 | // choose usb src as PLL |
djbottrill | 0:aac55e1fc12f | 123 | SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK); |
djbottrill | 0:aac55e1fc12f | 124 | |
djbottrill | 0:aac55e1fc12f | 125 | // enable OTG clock |
djbottrill | 0:aac55e1fc12f | 126 | SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK; |
djbottrill | 0:aac55e1fc12f | 127 | |
djbottrill | 0:aac55e1fc12f | 128 | // Attach IRQ |
djbottrill | 0:aac55e1fc12f | 129 | instance = this; |
djbottrill | 0:aac55e1fc12f | 130 | NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr); |
djbottrill | 0:aac55e1fc12f | 131 | NVIC_EnableIRQ(USB0_IRQn); |
djbottrill | 0:aac55e1fc12f | 132 | |
djbottrill | 0:aac55e1fc12f | 133 | // USB Module Configuration |
djbottrill | 0:aac55e1fc12f | 134 | // Reset USB Module |
djbottrill | 0:aac55e1fc12f | 135 | USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK; |
djbottrill | 0:aac55e1fc12f | 136 | while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK); |
djbottrill | 0:aac55e1fc12f | 137 | |
djbottrill | 0:aac55e1fc12f | 138 | // Set BDT Base Register |
djbottrill | 0:aac55e1fc12f | 139 | USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8); |
djbottrill | 0:aac55e1fc12f | 140 | USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16); |
djbottrill | 0:aac55e1fc12f | 141 | USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24); |
djbottrill | 0:aac55e1fc12f | 142 | |
djbottrill | 0:aac55e1fc12f | 143 | // Clear interrupt flag |
djbottrill | 0:aac55e1fc12f | 144 | USB0->ISTAT = 0xff; |
djbottrill | 0:aac55e1fc12f | 145 | |
djbottrill | 0:aac55e1fc12f | 146 | // USB Interrupt Enablers |
djbottrill | 0:aac55e1fc12f | 147 | USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK | |
djbottrill | 0:aac55e1fc12f | 148 | USB_INTEN_SOFTOKEN_MASK | |
djbottrill | 0:aac55e1fc12f | 149 | USB_INTEN_ERROREN_MASK | |
djbottrill | 0:aac55e1fc12f | 150 | USB_INTEN_USBRSTEN_MASK; |
djbottrill | 0:aac55e1fc12f | 151 | |
djbottrill | 0:aac55e1fc12f | 152 | // Disable weak pull downs |
djbottrill | 0:aac55e1fc12f | 153 | USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK); |
djbottrill | 0:aac55e1fc12f | 154 | |
djbottrill | 0:aac55e1fc12f | 155 | USB0->USBTRC0 |= 0x40; |
djbottrill | 0:aac55e1fc12f | 156 | } |
djbottrill | 0:aac55e1fc12f | 157 | |
djbottrill | 0:aac55e1fc12f | 158 | USBHAL::~USBHAL(void) { } |
djbottrill | 0:aac55e1fc12f | 159 | |
djbottrill | 0:aac55e1fc12f | 160 | void USBHAL::connect(void) { |
djbottrill | 0:aac55e1fc12f | 161 | // enable USB |
djbottrill | 0:aac55e1fc12f | 162 | USB0->CTL |= USB_CTL_USBENSOFEN_MASK; |
djbottrill | 0:aac55e1fc12f | 163 | // Pull up enable |
djbottrill | 0:aac55e1fc12f | 164 | USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK; |
djbottrill | 0:aac55e1fc12f | 165 | } |
djbottrill | 0:aac55e1fc12f | 166 | |
djbottrill | 0:aac55e1fc12f | 167 | void USBHAL::disconnect(void) { |
djbottrill | 0:aac55e1fc12f | 168 | // disable USB |
djbottrill | 0:aac55e1fc12f | 169 | USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK; |
djbottrill | 0:aac55e1fc12f | 170 | // Pull up disable |
djbottrill | 0:aac55e1fc12f | 171 | USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK; |
djbottrill | 0:aac55e1fc12f | 172 | } |
djbottrill | 0:aac55e1fc12f | 173 | |
djbottrill | 0:aac55e1fc12f | 174 | void USBHAL::configureDevice(void) { |
djbottrill | 0:aac55e1fc12f | 175 | // not needed |
djbottrill | 0:aac55e1fc12f | 176 | } |
djbottrill | 0:aac55e1fc12f | 177 | |
djbottrill | 0:aac55e1fc12f | 178 | void USBHAL::unconfigureDevice(void) { |
djbottrill | 0:aac55e1fc12f | 179 | // not needed |
djbottrill | 0:aac55e1fc12f | 180 | } |
djbottrill | 0:aac55e1fc12f | 181 | |
djbottrill | 0:aac55e1fc12f | 182 | void USBHAL::setAddress(uint8_t address) { |
djbottrill | 0:aac55e1fc12f | 183 | // we don't set the address now otherwise the usb controller does not ack |
djbottrill | 0:aac55e1fc12f | 184 | // we set a flag instead |
djbottrill | 0:aac55e1fc12f | 185 | // see usbisr when an IN token is received |
djbottrill | 0:aac55e1fc12f | 186 | set_addr = 1; |
djbottrill | 0:aac55e1fc12f | 187 | addr = address; |
djbottrill | 0:aac55e1fc12f | 188 | } |
djbottrill | 0:aac55e1fc12f | 189 | |
djbottrill | 0:aac55e1fc12f | 190 | bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) { |
djbottrill | 0:aac55e1fc12f | 191 | uint32_t handshake_flag = 0; |
djbottrill | 0:aac55e1fc12f | 192 | uint8_t * buf; |
djbottrill | 0:aac55e1fc12f | 193 | |
djbottrill | 0:aac55e1fc12f | 194 | if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { |
djbottrill | 0:aac55e1fc12f | 195 | return false; |
djbottrill | 0:aac55e1fc12f | 196 | } |
djbottrill | 0:aac55e1fc12f | 197 | |
djbottrill | 0:aac55e1fc12f | 198 | uint32_t log_endpoint = PHY_TO_LOG(endpoint); |
djbottrill | 0:aac55e1fc12f | 199 | |
djbottrill | 0:aac55e1fc12f | 200 | if ((flags & ISOCHRONOUS) == 0) { |
djbottrill | 0:aac55e1fc12f | 201 | handshake_flag = USB_ENDPT_EPHSHK_MASK; |
djbottrill | 0:aac55e1fc12f | 202 | if (IN_EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 203 | endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )] = (uint8_t *) malloc (64*2); |
djbottrill | 0:aac55e1fc12f | 204 | buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )][0]; |
djbottrill | 0:aac55e1fc12f | 205 | } else { |
djbottrill | 0:aac55e1fc12f | 206 | endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )] = (uint8_t *) malloc (64*2); |
djbottrill | 0:aac55e1fc12f | 207 | buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )][0]; |
djbottrill | 0:aac55e1fc12f | 208 | } |
djbottrill | 0:aac55e1fc12f | 209 | } else { |
djbottrill | 0:aac55e1fc12f | 210 | if (IN_EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 211 | endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2); |
djbottrill | 0:aac55e1fc12f | 212 | buf = &endpoint_buffer_iso[2][0]; |
djbottrill | 0:aac55e1fc12f | 213 | } else { |
djbottrill | 0:aac55e1fc12f | 214 | endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2); |
djbottrill | 0:aac55e1fc12f | 215 | buf = &endpoint_buffer_iso[0][0]; |
djbottrill | 0:aac55e1fc12f | 216 | } |
djbottrill | 0:aac55e1fc12f | 217 | } |
djbottrill | 0:aac55e1fc12f | 218 | |
djbottrill | 0:aac55e1fc12f | 219 | // IN endpt -> device to host (TX) |
djbottrill | 0:aac55e1fc12f | 220 | if (IN_EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 221 | USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) |
djbottrill | 0:aac55e1fc12f | 222 | USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran |
djbottrill | 0:aac55e1fc12f | 223 | bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf; |
djbottrill | 0:aac55e1fc12f | 224 | bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0; |
djbottrill | 0:aac55e1fc12f | 225 | } |
djbottrill | 0:aac55e1fc12f | 226 | // OUT endpt -> host to device (RX) |
djbottrill | 0:aac55e1fc12f | 227 | else { |
djbottrill | 0:aac55e1fc12f | 228 | USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint) |
djbottrill | 0:aac55e1fc12f | 229 | USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran. |
djbottrill | 0:aac55e1fc12f | 230 | bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket; |
djbottrill | 0:aac55e1fc12f | 231 | bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf; |
djbottrill | 0:aac55e1fc12f | 232 | bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK; |
djbottrill | 0:aac55e1fc12f | 233 | bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0; |
djbottrill | 0:aac55e1fc12f | 234 | } |
djbottrill | 0:aac55e1fc12f | 235 | |
djbottrill | 0:aac55e1fc12f | 236 | Data1 |= (1 << endpoint); |
djbottrill | 0:aac55e1fc12f | 237 | |
djbottrill | 0:aac55e1fc12f | 238 | return true; |
djbottrill | 0:aac55e1fc12f | 239 | } |
djbottrill | 0:aac55e1fc12f | 240 | |
djbottrill | 0:aac55e1fc12f | 241 | // read setup packet |
djbottrill | 0:aac55e1fc12f | 242 | void USBHAL::EP0setup(uint8_t *buffer) { |
djbottrill | 0:aac55e1fc12f | 243 | uint32_t sz; |
djbottrill | 0:aac55e1fc12f | 244 | endpointReadResult(EP0OUT, buffer, &sz); |
djbottrill | 0:aac55e1fc12f | 245 | } |
djbottrill | 0:aac55e1fc12f | 246 | |
djbottrill | 0:aac55e1fc12f | 247 | void USBHAL::EP0readStage(void) { |
djbottrill | 0:aac55e1fc12f | 248 | Data1 &= ~1UL; // set DATA0 |
djbottrill | 0:aac55e1fc12f | 249 | bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK); |
djbottrill | 0:aac55e1fc12f | 250 | } |
djbottrill | 0:aac55e1fc12f | 251 | |
djbottrill | 0:aac55e1fc12f | 252 | void USBHAL::EP0read(void) { |
djbottrill | 0:aac55e1fc12f | 253 | uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0); |
djbottrill | 0:aac55e1fc12f | 254 | bdt[idx].byte_count = MAX_PACKET_SIZE_EP0; |
djbottrill | 0:aac55e1fc12f | 255 | } |
djbottrill | 0:aac55e1fc12f | 256 | |
djbottrill | 0:aac55e1fc12f | 257 | uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) { |
djbottrill | 0:aac55e1fc12f | 258 | uint32_t sz; |
djbottrill | 0:aac55e1fc12f | 259 | endpointReadResult(EP0OUT, buffer, &sz); |
djbottrill | 0:aac55e1fc12f | 260 | return sz; |
djbottrill | 0:aac55e1fc12f | 261 | } |
djbottrill | 0:aac55e1fc12f | 262 | |
djbottrill | 0:aac55e1fc12f | 263 | void USBHAL::EP0write(uint8_t *buffer, uint32_t size) { |
djbottrill | 0:aac55e1fc12f | 264 | endpointWrite(EP0IN, buffer, size); |
djbottrill | 0:aac55e1fc12f | 265 | } |
djbottrill | 0:aac55e1fc12f | 266 | |
djbottrill | 0:aac55e1fc12f | 267 | void USBHAL::EP0getWriteResult(void) { |
djbottrill | 0:aac55e1fc12f | 268 | } |
djbottrill | 0:aac55e1fc12f | 269 | |
djbottrill | 0:aac55e1fc12f | 270 | void USBHAL::EP0stall(void) { |
djbottrill | 0:aac55e1fc12f | 271 | stallEndpoint(EP0OUT); |
djbottrill | 0:aac55e1fc12f | 272 | } |
djbottrill | 0:aac55e1fc12f | 273 | |
djbottrill | 0:aac55e1fc12f | 274 | EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) { |
djbottrill | 0:aac55e1fc12f | 275 | endpoint = PHY_TO_LOG(endpoint); |
djbottrill | 0:aac55e1fc12f | 276 | uint32_t idx = EP_BDT_IDX(endpoint, RX, 0); |
djbottrill | 0:aac55e1fc12f | 277 | bdt[idx].byte_count = maximumSize; |
djbottrill | 0:aac55e1fc12f | 278 | return EP_PENDING; |
djbottrill | 0:aac55e1fc12f | 279 | } |
djbottrill | 0:aac55e1fc12f | 280 | |
djbottrill | 0:aac55e1fc12f | 281 | EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) { |
djbottrill | 0:aac55e1fc12f | 282 | uint32_t n, sz, idx, setup = 0; |
djbottrill | 0:aac55e1fc12f | 283 | uint8_t not_iso; |
djbottrill | 0:aac55e1fc12f | 284 | uint8_t * ep_buf; |
djbottrill | 0:aac55e1fc12f | 285 | |
djbottrill | 0:aac55e1fc12f | 286 | uint32_t log_endpoint = PHY_TO_LOG(endpoint); |
djbottrill | 0:aac55e1fc12f | 287 | |
djbottrill | 0:aac55e1fc12f | 288 | if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { |
djbottrill | 0:aac55e1fc12f | 289 | return EP_INVALID; |
djbottrill | 0:aac55e1fc12f | 290 | } |
djbottrill | 0:aac55e1fc12f | 291 | |
djbottrill | 0:aac55e1fc12f | 292 | // if read on a IN endpoint -> error |
djbottrill | 0:aac55e1fc12f | 293 | if (IN_EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 294 | return EP_INVALID; |
djbottrill | 0:aac55e1fc12f | 295 | } |
djbottrill | 0:aac55e1fc12f | 296 | |
djbottrill | 0:aac55e1fc12f | 297 | idx = EP_BDT_IDX(log_endpoint, RX, 0); |
djbottrill | 0:aac55e1fc12f | 298 | sz = bdt[idx].byte_count; |
djbottrill | 0:aac55e1fc12f | 299 | not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK; |
djbottrill | 0:aac55e1fc12f | 300 | |
djbottrill | 0:aac55e1fc12f | 301 | //for isochronous endpoint, we don't wait an interrupt |
djbottrill | 0:aac55e1fc12f | 302 | if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) { |
djbottrill | 0:aac55e1fc12f | 303 | return EP_PENDING; |
djbottrill | 0:aac55e1fc12f | 304 | } |
djbottrill | 0:aac55e1fc12f | 305 | |
djbottrill | 0:aac55e1fc12f | 306 | if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) { |
djbottrill | 0:aac55e1fc12f | 307 | setup = 1; |
djbottrill | 0:aac55e1fc12f | 308 | } |
djbottrill | 0:aac55e1fc12f | 309 | |
djbottrill | 0:aac55e1fc12f | 310 | // non iso endpoint |
djbottrill | 0:aac55e1fc12f | 311 | if (not_iso) { |
djbottrill | 0:aac55e1fc12f | 312 | ep_buf = endpoint_buffer[idx]; |
djbottrill | 0:aac55e1fc12f | 313 | } else { |
djbottrill | 0:aac55e1fc12f | 314 | ep_buf = endpoint_buffer_iso[0]; |
djbottrill | 0:aac55e1fc12f | 315 | } |
djbottrill | 0:aac55e1fc12f | 316 | |
djbottrill | 0:aac55e1fc12f | 317 | for (n = 0; n < sz; n++) { |
djbottrill | 0:aac55e1fc12f | 318 | buffer[n] = ep_buf[n]; |
djbottrill | 0:aac55e1fc12f | 319 | } |
djbottrill | 0:aac55e1fc12f | 320 | |
djbottrill | 0:aac55e1fc12f | 321 | if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) { |
djbottrill | 0:aac55e1fc12f | 322 | if (setup && (buffer[6] == 0)) // if no setup data stage, |
djbottrill | 0:aac55e1fc12f | 323 | Data1 &= ~1UL; // set DATA0 |
djbottrill | 0:aac55e1fc12f | 324 | else |
djbottrill | 0:aac55e1fc12f | 325 | Data1 ^= (1 << endpoint); |
djbottrill | 0:aac55e1fc12f | 326 | } |
djbottrill | 0:aac55e1fc12f | 327 | |
djbottrill | 0:aac55e1fc12f | 328 | if (((Data1 >> endpoint) & 1)) { |
djbottrill | 0:aac55e1fc12f | 329 | bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK; |
djbottrill | 0:aac55e1fc12f | 330 | } |
djbottrill | 0:aac55e1fc12f | 331 | else { |
djbottrill | 0:aac55e1fc12f | 332 | bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK; |
djbottrill | 0:aac55e1fc12f | 333 | } |
djbottrill | 0:aac55e1fc12f | 334 | |
djbottrill | 0:aac55e1fc12f | 335 | USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK; |
djbottrill | 0:aac55e1fc12f | 336 | *bytesRead = sz; |
djbottrill | 0:aac55e1fc12f | 337 | |
djbottrill | 0:aac55e1fc12f | 338 | epComplete &= ~EP(endpoint); |
djbottrill | 0:aac55e1fc12f | 339 | return EP_COMPLETED; |
djbottrill | 0:aac55e1fc12f | 340 | } |
djbottrill | 0:aac55e1fc12f | 341 | |
djbottrill | 0:aac55e1fc12f | 342 | EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) { |
djbottrill | 0:aac55e1fc12f | 343 | uint32_t idx, n; |
djbottrill | 0:aac55e1fc12f | 344 | uint8_t * ep_buf; |
djbottrill | 0:aac55e1fc12f | 345 | |
djbottrill | 0:aac55e1fc12f | 346 | if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) { |
djbottrill | 0:aac55e1fc12f | 347 | return EP_INVALID; |
djbottrill | 0:aac55e1fc12f | 348 | } |
djbottrill | 0:aac55e1fc12f | 349 | |
djbottrill | 0:aac55e1fc12f | 350 | // if write on a OUT endpoint -> error |
djbottrill | 0:aac55e1fc12f | 351 | if (OUT_EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 352 | return EP_INVALID; |
djbottrill | 0:aac55e1fc12f | 353 | } |
djbottrill | 0:aac55e1fc12f | 354 | |
djbottrill | 0:aac55e1fc12f | 355 | idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0); |
djbottrill | 0:aac55e1fc12f | 356 | bdt[idx].byte_count = size; |
djbottrill | 0:aac55e1fc12f | 357 | |
djbottrill | 0:aac55e1fc12f | 358 | |
djbottrill | 0:aac55e1fc12f | 359 | // non iso endpoint |
djbottrill | 0:aac55e1fc12f | 360 | if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) { |
djbottrill | 0:aac55e1fc12f | 361 | ep_buf = endpoint_buffer[idx]; |
djbottrill | 0:aac55e1fc12f | 362 | } else { |
djbottrill | 0:aac55e1fc12f | 363 | ep_buf = endpoint_buffer_iso[2]; |
djbottrill | 0:aac55e1fc12f | 364 | } |
djbottrill | 0:aac55e1fc12f | 365 | |
djbottrill | 0:aac55e1fc12f | 366 | for (n = 0; n < size; n++) { |
djbottrill | 0:aac55e1fc12f | 367 | ep_buf[n] = data[n]; |
djbottrill | 0:aac55e1fc12f | 368 | } |
djbottrill | 0:aac55e1fc12f | 369 | |
djbottrill | 0:aac55e1fc12f | 370 | if ((Data1 >> endpoint) & 1) { |
djbottrill | 0:aac55e1fc12f | 371 | bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK; |
djbottrill | 0:aac55e1fc12f | 372 | } else { |
djbottrill | 0:aac55e1fc12f | 373 | bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK; |
djbottrill | 0:aac55e1fc12f | 374 | } |
djbottrill | 0:aac55e1fc12f | 375 | |
djbottrill | 0:aac55e1fc12f | 376 | Data1 ^= (1 << endpoint); |
djbottrill | 0:aac55e1fc12f | 377 | |
djbottrill | 0:aac55e1fc12f | 378 | return EP_PENDING; |
djbottrill | 0:aac55e1fc12f | 379 | } |
djbottrill | 0:aac55e1fc12f | 380 | |
djbottrill | 0:aac55e1fc12f | 381 | EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) { |
djbottrill | 0:aac55e1fc12f | 382 | if (epComplete & EP(endpoint)) { |
djbottrill | 0:aac55e1fc12f | 383 | epComplete &= ~EP(endpoint); |
djbottrill | 0:aac55e1fc12f | 384 | return EP_COMPLETED; |
djbottrill | 0:aac55e1fc12f | 385 | } |
djbottrill | 0:aac55e1fc12f | 386 | |
djbottrill | 0:aac55e1fc12f | 387 | return EP_PENDING; |
djbottrill | 0:aac55e1fc12f | 388 | } |
djbottrill | 0:aac55e1fc12f | 389 | |
djbottrill | 0:aac55e1fc12f | 390 | void USBHAL::stallEndpoint(uint8_t endpoint) { |
djbottrill | 0:aac55e1fc12f | 391 | USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK; |
djbottrill | 0:aac55e1fc12f | 392 | } |
djbottrill | 0:aac55e1fc12f | 393 | |
djbottrill | 0:aac55e1fc12f | 394 | void USBHAL::unstallEndpoint(uint8_t endpoint) { |
djbottrill | 0:aac55e1fc12f | 395 | USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; |
djbottrill | 0:aac55e1fc12f | 396 | } |
djbottrill | 0:aac55e1fc12f | 397 | |
djbottrill | 0:aac55e1fc12f | 398 | bool USBHAL::getEndpointStallState(uint8_t endpoint) { |
djbottrill | 0:aac55e1fc12f | 399 | uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK); |
djbottrill | 0:aac55e1fc12f | 400 | return (stall) ? true : false; |
djbottrill | 0:aac55e1fc12f | 401 | } |
djbottrill | 0:aac55e1fc12f | 402 | |
djbottrill | 0:aac55e1fc12f | 403 | void USBHAL::remoteWakeup(void) { |
djbottrill | 0:aac55e1fc12f | 404 | // [TODO] |
djbottrill | 0:aac55e1fc12f | 405 | } |
djbottrill | 0:aac55e1fc12f | 406 | |
djbottrill | 0:aac55e1fc12f | 407 | |
djbottrill | 0:aac55e1fc12f | 408 | void USBHAL::_usbisr(void) { |
djbottrill | 0:aac55e1fc12f | 409 | instance->usbisr(); |
djbottrill | 0:aac55e1fc12f | 410 | } |
djbottrill | 0:aac55e1fc12f | 411 | |
djbottrill | 0:aac55e1fc12f | 412 | |
djbottrill | 0:aac55e1fc12f | 413 | void USBHAL::usbisr(void) { |
djbottrill | 0:aac55e1fc12f | 414 | uint8_t i; |
djbottrill | 0:aac55e1fc12f | 415 | uint8_t istat = USB0->ISTAT; |
djbottrill | 0:aac55e1fc12f | 416 | |
djbottrill | 0:aac55e1fc12f | 417 | // reset interrupt |
djbottrill | 0:aac55e1fc12f | 418 | if (istat & USB_ISTAT_USBRST_MASK) { |
djbottrill | 0:aac55e1fc12f | 419 | // disable all endpt |
djbottrill | 0:aac55e1fc12f | 420 | for(i = 0; i < 16; i++) { |
djbottrill | 0:aac55e1fc12f | 421 | USB0->ENDPOINT[i].ENDPT = 0x00; |
djbottrill | 0:aac55e1fc12f | 422 | } |
djbottrill | 0:aac55e1fc12f | 423 | |
djbottrill | 0:aac55e1fc12f | 424 | // enable control endpoint |
djbottrill | 0:aac55e1fc12f | 425 | realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0); |
djbottrill | 0:aac55e1fc12f | 426 | realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0); |
djbottrill | 0:aac55e1fc12f | 427 | |
djbottrill | 0:aac55e1fc12f | 428 | Data1 = 0x55555555; |
djbottrill | 0:aac55e1fc12f | 429 | USB0->CTL |= USB_CTL_ODDRST_MASK; |
djbottrill | 0:aac55e1fc12f | 430 | |
djbottrill | 0:aac55e1fc12f | 431 | USB0->ISTAT = 0xFF; // clear all interrupt status flags |
djbottrill | 0:aac55e1fc12f | 432 | USB0->ERRSTAT = 0xFF; // clear all error flags |
djbottrill | 0:aac55e1fc12f | 433 | USB0->ERREN = 0xFF; // enable error interrupt sources |
djbottrill | 0:aac55e1fc12f | 434 | USB0->ADDR = 0x00; // set default address |
djbottrill | 0:aac55e1fc12f | 435 | |
djbottrill | 0:aac55e1fc12f | 436 | return; |
djbottrill | 0:aac55e1fc12f | 437 | } |
djbottrill | 0:aac55e1fc12f | 438 | |
djbottrill | 0:aac55e1fc12f | 439 | // resume interrupt |
djbottrill | 0:aac55e1fc12f | 440 | if (istat & USB_ISTAT_RESUME_MASK) { |
djbottrill | 0:aac55e1fc12f | 441 | USB0->ISTAT = USB_ISTAT_RESUME_MASK; |
djbottrill | 0:aac55e1fc12f | 442 | } |
djbottrill | 0:aac55e1fc12f | 443 | |
djbottrill | 0:aac55e1fc12f | 444 | // SOF interrupt |
djbottrill | 0:aac55e1fc12f | 445 | if (istat & USB_ISTAT_SOFTOK_MASK) { |
djbottrill | 0:aac55e1fc12f | 446 | USB0->ISTAT = USB_ISTAT_SOFTOK_MASK; |
djbottrill | 0:aac55e1fc12f | 447 | // SOF event, read frame number |
djbottrill | 0:aac55e1fc12f | 448 | SOF(frameNumber()); |
djbottrill | 0:aac55e1fc12f | 449 | } |
djbottrill | 0:aac55e1fc12f | 450 | |
djbottrill | 0:aac55e1fc12f | 451 | // stall interrupt |
djbottrill | 0:aac55e1fc12f | 452 | if (istat & 1<<7) { |
djbottrill | 0:aac55e1fc12f | 453 | if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK) |
djbottrill | 0:aac55e1fc12f | 454 | USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK; |
djbottrill | 0:aac55e1fc12f | 455 | USB0->ISTAT |= USB_ISTAT_STALL_MASK; |
djbottrill | 0:aac55e1fc12f | 456 | } |
djbottrill | 0:aac55e1fc12f | 457 | |
djbottrill | 0:aac55e1fc12f | 458 | // token interrupt |
djbottrill | 0:aac55e1fc12f | 459 | if (istat & 1<<3) { |
djbottrill | 0:aac55e1fc12f | 460 | uint32_t num = (USB0->STAT >> 4) & 0x0F; |
djbottrill | 0:aac55e1fc12f | 461 | uint32_t dir = (USB0->STAT >> 3) & 0x01; |
djbottrill | 0:aac55e1fc12f | 462 | uint32_t ev_odd = (USB0->STAT >> 2) & 0x01; |
djbottrill | 0:aac55e1fc12f | 463 | |
djbottrill | 0:aac55e1fc12f | 464 | // setup packet |
djbottrill | 0:aac55e1fc12f | 465 | if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) { |
djbottrill | 0:aac55e1fc12f | 466 | Data1 &= ~0x02; |
djbottrill | 0:aac55e1fc12f | 467 | bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK; |
djbottrill | 0:aac55e1fc12f | 468 | bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK; |
djbottrill | 0:aac55e1fc12f | 469 | |
djbottrill | 0:aac55e1fc12f | 470 | // EP0 SETUP event (SETUP data received) |
djbottrill | 0:aac55e1fc12f | 471 | EP0setupCallback(); |
djbottrill | 0:aac55e1fc12f | 472 | |
djbottrill | 0:aac55e1fc12f | 473 | } else { |
djbottrill | 0:aac55e1fc12f | 474 | // OUT packet |
djbottrill | 0:aac55e1fc12f | 475 | if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) { |
djbottrill | 0:aac55e1fc12f | 476 | if (num == 0) |
djbottrill | 0:aac55e1fc12f | 477 | EP0out(); |
djbottrill | 0:aac55e1fc12f | 478 | else { |
djbottrill | 0:aac55e1fc12f | 479 | epComplete |= (1 << EP(num)); |
djbottrill | 0:aac55e1fc12f | 480 | if ((instance->*(epCallback[EP(num) - 2]))()) { |
djbottrill | 0:aac55e1fc12f | 481 | epComplete &= ~(1 << EP(num)); |
djbottrill | 0:aac55e1fc12f | 482 | } |
djbottrill | 0:aac55e1fc12f | 483 | } |
djbottrill | 0:aac55e1fc12f | 484 | } |
djbottrill | 0:aac55e1fc12f | 485 | |
djbottrill | 0:aac55e1fc12f | 486 | // IN packet |
djbottrill | 0:aac55e1fc12f | 487 | if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) { |
djbottrill | 0:aac55e1fc12f | 488 | if (num == 0) { |
djbottrill | 0:aac55e1fc12f | 489 | EP0in(); |
djbottrill | 0:aac55e1fc12f | 490 | if (set_addr == 1) { |
djbottrill | 0:aac55e1fc12f | 491 | USB0->ADDR = addr & 0x7F; |
djbottrill | 0:aac55e1fc12f | 492 | set_addr = 0; |
djbottrill | 0:aac55e1fc12f | 493 | } |
djbottrill | 0:aac55e1fc12f | 494 | } |
djbottrill | 0:aac55e1fc12f | 495 | else { |
djbottrill | 0:aac55e1fc12f | 496 | epComplete |= (1 << (EP(num) + 1)); |
djbottrill | 0:aac55e1fc12f | 497 | if ((instance->*(epCallback[EP(num) + 1 - 2]))()) { |
djbottrill | 0:aac55e1fc12f | 498 | epComplete &= ~(1 << (EP(num) + 1)); |
djbottrill | 0:aac55e1fc12f | 499 | } |
djbottrill | 0:aac55e1fc12f | 500 | } |
djbottrill | 0:aac55e1fc12f | 501 | } |
djbottrill | 0:aac55e1fc12f | 502 | } |
djbottrill | 0:aac55e1fc12f | 503 | |
djbottrill | 0:aac55e1fc12f | 504 | USB0->ISTAT = USB_ISTAT_TOKDNE_MASK; |
djbottrill | 0:aac55e1fc12f | 505 | } |
djbottrill | 0:aac55e1fc12f | 506 | |
djbottrill | 0:aac55e1fc12f | 507 | // sleep interrupt |
djbottrill | 0:aac55e1fc12f | 508 | if (istat & 1<<4) { |
djbottrill | 0:aac55e1fc12f | 509 | USB0->ISTAT |= USB_ISTAT_SLEEP_MASK; |
djbottrill | 0:aac55e1fc12f | 510 | } |
djbottrill | 0:aac55e1fc12f | 511 | |
djbottrill | 0:aac55e1fc12f | 512 | // error interrupt |
djbottrill | 0:aac55e1fc12f | 513 | if (istat & USB_ISTAT_ERROR_MASK) { |
djbottrill | 0:aac55e1fc12f | 514 | USB0->ERRSTAT = 0xFF; |
djbottrill | 0:aac55e1fc12f | 515 | USB0->ISTAT |= USB_ISTAT_ERROR_MASK; |
djbottrill | 0:aac55e1fc12f | 516 | } |
djbottrill | 0:aac55e1fc12f | 517 | } |
djbottrill | 0:aac55e1fc12f | 518 | |
djbottrill | 0:aac55e1fc12f | 519 | |
djbottrill | 0:aac55e1fc12f | 520 | #endif |