Transistor Gijutsu, October 2014, Special Features Chapter 8,Software of the thermistor thermometer of 0.001 ° resolution, トランジスタ技術2014年10月号 特集第8章のソフトウェア 0.001℃分解能で気配もキャッチ「超敏感肌温度計」

Dependencies:   USBDevice mbed

Information

tg_201410s8_AD7714 トランジスタ技術 2014年 10月号 第8章のソフトウェア

Program for Section 8 in October. 2014 issue of the Transistor Gijutsu
(Japanese electronics magazine)

概要

このプログラムは、サーミスタの抵抗値変化をAD7714(24bitADC)で測定し、抵抗値を温度値に変換することで、0.001℃程度の分解能で温度変化を測定します。

ファイル

このソフトウエアは、次のファイルから構成されています。

  • AD7714.cpp - AD7714の内部レジスタを設定
  • Thermistor.cpp - サーミスタの抵抗値から温度値に変換
  • ExpAvr.cpp - 指数平均によるソフトウエアLPF
  • main.cpp - main()関数

詳細については、10月号の記事および上記ファイル中のコメントを参照してください。

Committer:
Dance
Date:
Fri Aug 29 08:38:36 2014 +0000
Revision:
0:de885a6da962
Transistor Gijutsu, October 2014, Special Features Chapter 8; ????????2014?10??????8????????

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Dance 0:de885a6da962 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
Dance 0:de885a6da962 2 *
Dance 0:de885a6da962 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
Dance 0:de885a6da962 4 * and associated documentation files (the "Software"), to deal in the Software without
Dance 0:de885a6da962 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
Dance 0:de885a6da962 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
Dance 0:de885a6da962 7 * Software is furnished to do so, subject to the following conditions:
Dance 0:de885a6da962 8 *
Dance 0:de885a6da962 9 * The above copyright notice and this permission notice shall be included in all copies or
Dance 0:de885a6da962 10 * substantial portions of the Software.
Dance 0:de885a6da962 11 *
Dance 0:de885a6da962 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
Dance 0:de885a6da962 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Dance 0:de885a6da962 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
Dance 0:de885a6da962 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Dance 0:de885a6da962 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Dance 0:de885a6da962 17 */
Dance 0:de885a6da962 18
Dance 0:de885a6da962 19 #if defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC1347) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68)
Dance 0:de885a6da962 20
Dance 0:de885a6da962 21 #if defined(TARGET_LPC1347)
Dance 0:de885a6da962 22 #define USB_IRQ USB_IRQ_IRQn
Dance 0:de885a6da962 23 #elif defined(TARGET_LPC11U24) || defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501) || defined(TARGET_LPC11U68)
Dance 0:de885a6da962 24 #define USB_IRQ USB_IRQn
Dance 0:de885a6da962 25 #endif
Dance 0:de885a6da962 26
Dance 0:de885a6da962 27 #include "USBHAL.h"
Dance 0:de885a6da962 28
Dance 0:de885a6da962 29 USBHAL * USBHAL::instance;
Dance 0:de885a6da962 30
Dance 0:de885a6da962 31 // Valid physical endpoint numbers are 0 to (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
Dance 0:de885a6da962 32 #define LAST_PHYSICAL_ENDPOINT (NUMBER_OF_PHYSICAL_ENDPOINTS-1)
Dance 0:de885a6da962 33
Dance 0:de885a6da962 34 // Convert physical endpoint number to register bit
Dance 0:de885a6da962 35 #define EP(endpoint) (1UL<<endpoint)
Dance 0:de885a6da962 36
Dance 0:de885a6da962 37 // Convert physical to logical
Dance 0:de885a6da962 38 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
Dance 0:de885a6da962 39
Dance 0:de885a6da962 40 // Get endpoint direction
Dance 0:de885a6da962 41 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
Dance 0:de885a6da962 42 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
Dance 0:de885a6da962 43
Dance 0:de885a6da962 44 // USB RAM
Dance 0:de885a6da962 45 #define USB_RAM_START (0x20004000)
Dance 0:de885a6da962 46 #define USB_RAM_SIZE (0x00000800)
Dance 0:de885a6da962 47
Dance 0:de885a6da962 48 // SYSAHBCLKCTRL
Dance 0:de885a6da962 49 #define CLK_USB (1UL<<14)
Dance 0:de885a6da962 50 #define CLK_USBRAM (1UL<<27)
Dance 0:de885a6da962 51
Dance 0:de885a6da962 52 // USB Information register
Dance 0:de885a6da962 53 #define FRAME_NR(a) ((a) & 0x7ff) // Frame number
Dance 0:de885a6da962 54
Dance 0:de885a6da962 55 // USB Device Command/Status register
Dance 0:de885a6da962 56 #define DEV_ADDR_MASK (0x7f) // Device address
Dance 0:de885a6da962 57 #define DEV_ADDR(a) ((a) & DEV_ADDR_MASK)
Dance 0:de885a6da962 58 #define DEV_EN (1UL<<7) // Device enable
Dance 0:de885a6da962 59 #define SETUP (1UL<<8) // SETUP token received
Dance 0:de885a6da962 60 #define PLL_ON (1UL<<9) // PLL enabled in suspend
Dance 0:de885a6da962 61 #define DCON (1UL<<16) // Device status - connect
Dance 0:de885a6da962 62 #define DSUS (1UL<<17) // Device status - suspend
Dance 0:de885a6da962 63 #define DCON_C (1UL<<24) // Connect change
Dance 0:de885a6da962 64 #define DSUS_C (1UL<<25) // Suspend change
Dance 0:de885a6da962 65 #define DRES_C (1UL<<26) // Reset change
Dance 0:de885a6da962 66 #define VBUSDEBOUNCED (1UL<<28) // Vbus detected
Dance 0:de885a6da962 67
Dance 0:de885a6da962 68 // Endpoint Command/Status list
Dance 0:de885a6da962 69 #define CMDSTS_A (1UL<<31) // Active
Dance 0:de885a6da962 70 #define CMDSTS_D (1UL<<30) // Disable
Dance 0:de885a6da962 71 #define CMDSTS_S (1UL<<29) // Stall
Dance 0:de885a6da962 72 #define CMDSTS_TR (1UL<<28) // Toggle Reset
Dance 0:de885a6da962 73 #define CMDSTS_RF (1UL<<27) // Rate Feedback mode
Dance 0:de885a6da962 74 #define CMDSTS_TV (1UL<<27) // Toggle Value
Dance 0:de885a6da962 75 #define CMDSTS_T (1UL<<26) // Endpoint Type
Dance 0:de885a6da962 76 #define CMDSTS_NBYTES(n) (((n)&0x3ff)<<16) // Number of bytes
Dance 0:de885a6da962 77 #define CMDSTS_ADDRESS_OFFSET(a) (((a)>>6)&0xffff) // Buffer start address
Dance 0:de885a6da962 78
Dance 0:de885a6da962 79 #define BYTES_REMAINING(s) (((s)>>16)&0x3ff) // Bytes remaining after transfer
Dance 0:de885a6da962 80
Dance 0:de885a6da962 81 // USB Non-endpoint interrupt sources
Dance 0:de885a6da962 82 #define FRAME_INT (1UL<<30)
Dance 0:de885a6da962 83 #define DEV_INT (1UL<<31)
Dance 0:de885a6da962 84
Dance 0:de885a6da962 85 static volatile int epComplete = 0;
Dance 0:de885a6da962 86
Dance 0:de885a6da962 87 // One entry for a double-buffered logical endpoint in the endpoint
Dance 0:de885a6da962 88 // command/status list. Endpoint 0 is single buffered, out[1] is used
Dance 0:de885a6da962 89 // for the SETUP packet and in[1] is not used
Dance 0:de885a6da962 90 typedef struct {
Dance 0:de885a6da962 91 uint32_t out[2];
Dance 0:de885a6da962 92 uint32_t in[2];
Dance 0:de885a6da962 93 } PACKED EP_COMMAND_STATUS;
Dance 0:de885a6da962 94
Dance 0:de885a6da962 95 typedef struct {
Dance 0:de885a6da962 96 uint8_t out[MAX_PACKET_SIZE_EP0];
Dance 0:de885a6da962 97 uint8_t in[MAX_PACKET_SIZE_EP0];
Dance 0:de885a6da962 98 uint8_t setup[SETUP_PACKET_SIZE];
Dance 0:de885a6da962 99 } PACKED CONTROL_TRANSFER;
Dance 0:de885a6da962 100
Dance 0:de885a6da962 101 typedef struct {
Dance 0:de885a6da962 102 uint32_t maxPacket;
Dance 0:de885a6da962 103 uint32_t buffer[2];
Dance 0:de885a6da962 104 uint32_t options;
Dance 0:de885a6da962 105 } PACKED EP_STATE;
Dance 0:de885a6da962 106
Dance 0:de885a6da962 107 static volatile EP_STATE endpointState[NUMBER_OF_PHYSICAL_ENDPOINTS];
Dance 0:de885a6da962 108
Dance 0:de885a6da962 109 // Pointer to the endpoint command/status list
Dance 0:de885a6da962 110 static EP_COMMAND_STATUS *ep = NULL;
Dance 0:de885a6da962 111
Dance 0:de885a6da962 112 // Pointer to endpoint 0 data (IN/OUT and SETUP)
Dance 0:de885a6da962 113 static CONTROL_TRANSFER *ct = NULL;
Dance 0:de885a6da962 114
Dance 0:de885a6da962 115 // Shadow DEVCMDSTAT register to avoid accidentally clearing flags or
Dance 0:de885a6da962 116 // initiating a remote wakeup event.
Dance 0:de885a6da962 117 static volatile uint32_t devCmdStat;
Dance 0:de885a6da962 118
Dance 0:de885a6da962 119 // Pointers used to allocate USB RAM
Dance 0:de885a6da962 120 static uint32_t usbRamPtr = USB_RAM_START;
Dance 0:de885a6da962 121 static uint32_t epRamPtr = 0; // Buffers for endpoints > 0 start here
Dance 0:de885a6da962 122
Dance 0:de885a6da962 123 #define ROUND_UP_TO_MULTIPLE(x, m) ((((x)+((m)-1))/(m))*(m))
Dance 0:de885a6da962 124
Dance 0:de885a6da962 125 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size);
Dance 0:de885a6da962 126 void USBMemCopy(uint8_t *dst, uint8_t *src, uint32_t size) {
Dance 0:de885a6da962 127 if (size > 0) {
Dance 0:de885a6da962 128 do {
Dance 0:de885a6da962 129 *dst++ = *src++;
Dance 0:de885a6da962 130 } while (--size > 0);
Dance 0:de885a6da962 131 }
Dance 0:de885a6da962 132 }
Dance 0:de885a6da962 133
Dance 0:de885a6da962 134
Dance 0:de885a6da962 135 USBHAL::USBHAL(void) {
Dance 0:de885a6da962 136 NVIC_DisableIRQ(USB_IRQ);
Dance 0:de885a6da962 137
Dance 0:de885a6da962 138 // fill in callback array
Dance 0:de885a6da962 139 epCallback[0] = &USBHAL::EP1_OUT_callback;
Dance 0:de885a6da962 140 epCallback[1] = &USBHAL::EP1_IN_callback;
Dance 0:de885a6da962 141 epCallback[2] = &USBHAL::EP2_OUT_callback;
Dance 0:de885a6da962 142 epCallback[3] = &USBHAL::EP2_IN_callback;
Dance 0:de885a6da962 143 epCallback[4] = &USBHAL::EP3_OUT_callback;
Dance 0:de885a6da962 144 epCallback[5] = &USBHAL::EP3_IN_callback;
Dance 0:de885a6da962 145 epCallback[6] = &USBHAL::EP4_OUT_callback;
Dance 0:de885a6da962 146 epCallback[7] = &USBHAL::EP4_IN_callback;
Dance 0:de885a6da962 147
Dance 0:de885a6da962 148 #if defined(TARGET_LPC11U35_401) || defined(TARGET_LPC11U35_501)
Dance 0:de885a6da962 149 // USB_VBUS input with pull-down
Dance 0:de885a6da962 150 LPC_IOCON->PIO0_3 = 0x00000009;
Dance 0:de885a6da962 151 #endif
Dance 0:de885a6da962 152
Dance 0:de885a6da962 153 // nUSB_CONNECT output
Dance 0:de885a6da962 154 LPC_IOCON->PIO0_6 = 0x00000001;
Dance 0:de885a6da962 155
Dance 0:de885a6da962 156 // Enable clocks (USB registers, USB RAM)
Dance 0:de885a6da962 157 LPC_SYSCON->SYSAHBCLKCTRL |= CLK_USB | CLK_USBRAM;
Dance 0:de885a6da962 158
Dance 0:de885a6da962 159 // Ensure device disconnected (DCON not set)
Dance 0:de885a6da962 160 LPC_USB->DEVCMDSTAT = 0;
Dance 0:de885a6da962 161
Dance 0:de885a6da962 162 // to ensure that the USB host sees the device as
Dance 0:de885a6da962 163 // disconnected if the target CPU is reset.
Dance 0:de885a6da962 164 wait(0.3);
Dance 0:de885a6da962 165
Dance 0:de885a6da962 166 // Reserve space in USB RAM for endpoint command/status list
Dance 0:de885a6da962 167 // Must be 256 byte aligned
Dance 0:de885a6da962 168 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 256);
Dance 0:de885a6da962 169 ep = (EP_COMMAND_STATUS *)usbRamPtr;
Dance 0:de885a6da962 170 usbRamPtr += (sizeof(EP_COMMAND_STATUS) * NUMBER_OF_LOGICAL_ENDPOINTS);
Dance 0:de885a6da962 171 LPC_USB->EPLISTSTART = (uint32_t)(ep) & 0xffffff00;
Dance 0:de885a6da962 172
Dance 0:de885a6da962 173 // Reserve space in USB RAM for Endpoint 0
Dance 0:de885a6da962 174 // Must be 64 byte aligned
Dance 0:de885a6da962 175 usbRamPtr = ROUND_UP_TO_MULTIPLE(usbRamPtr, 64);
Dance 0:de885a6da962 176 ct = (CONTROL_TRANSFER *)usbRamPtr;
Dance 0:de885a6da962 177 usbRamPtr += sizeof(CONTROL_TRANSFER);
Dance 0:de885a6da962 178 LPC_USB->DATABUFSTART =(uint32_t)(ct) & 0xffc00000;
Dance 0:de885a6da962 179
Dance 0:de885a6da962 180 // Setup command/status list for EP0
Dance 0:de885a6da962 181 ep[0].out[0] = 0;
Dance 0:de885a6da962 182 ep[0].in[0] = 0;
Dance 0:de885a6da962 183 ep[0].out[1] = CMDSTS_ADDRESS_OFFSET((uint32_t)ct->setup);
Dance 0:de885a6da962 184
Dance 0:de885a6da962 185 // Route all interrupts to IRQ, some can be routed to
Dance 0:de885a6da962 186 // USB_FIQ if you wish.
Dance 0:de885a6da962 187 LPC_USB->INTROUTING = 0;
Dance 0:de885a6da962 188
Dance 0:de885a6da962 189 // Set device address 0, enable USB device, no remote wakeup
Dance 0:de885a6da962 190 devCmdStat = DEV_ADDR(0) | DEV_EN | DSUS;
Dance 0:de885a6da962 191 LPC_USB->DEVCMDSTAT = devCmdStat;
Dance 0:de885a6da962 192
Dance 0:de885a6da962 193 // Enable interrupts for device events and EP0
Dance 0:de885a6da962 194 LPC_USB->INTEN = DEV_INT | EP(EP0IN) | EP(EP0OUT) | FRAME_INT;
Dance 0:de885a6da962 195 instance = this;
Dance 0:de885a6da962 196
Dance 0:de885a6da962 197 //attach IRQ handler and enable interrupts
Dance 0:de885a6da962 198 NVIC_SetVector(USB_IRQ, (uint32_t)&_usbisr);
Dance 0:de885a6da962 199 }
Dance 0:de885a6da962 200
Dance 0:de885a6da962 201 USBHAL::~USBHAL(void) {
Dance 0:de885a6da962 202 // Ensure device disconnected (DCON not set)
Dance 0:de885a6da962 203 LPC_USB->DEVCMDSTAT = 0;
Dance 0:de885a6da962 204 // Disable USB interrupts
Dance 0:de885a6da962 205 NVIC_DisableIRQ(USB_IRQ);
Dance 0:de885a6da962 206 }
Dance 0:de885a6da962 207
Dance 0:de885a6da962 208 void USBHAL::connect(void) {
Dance 0:de885a6da962 209 NVIC_EnableIRQ(USB_IRQ);
Dance 0:de885a6da962 210 devCmdStat |= DCON;
Dance 0:de885a6da962 211 LPC_USB->DEVCMDSTAT = devCmdStat;
Dance 0:de885a6da962 212 }
Dance 0:de885a6da962 213
Dance 0:de885a6da962 214 void USBHAL::disconnect(void) {
Dance 0:de885a6da962 215 NVIC_DisableIRQ(USB_IRQ);
Dance 0:de885a6da962 216 devCmdStat &= ~DCON;
Dance 0:de885a6da962 217 LPC_USB->DEVCMDSTAT = devCmdStat;
Dance 0:de885a6da962 218 }
Dance 0:de885a6da962 219
Dance 0:de885a6da962 220 void USBHAL::configureDevice(void) {
Dance 0:de885a6da962 221 // Not required
Dance 0:de885a6da962 222 }
Dance 0:de885a6da962 223
Dance 0:de885a6da962 224 void USBHAL::unconfigureDevice(void) {
Dance 0:de885a6da962 225 // Not required
Dance 0:de885a6da962 226 }
Dance 0:de885a6da962 227
Dance 0:de885a6da962 228 void USBHAL::EP0setup(uint8_t *buffer) {
Dance 0:de885a6da962 229 // Copy setup packet data
Dance 0:de885a6da962 230 USBMemCopy(buffer, ct->setup, SETUP_PACKET_SIZE);
Dance 0:de885a6da962 231 }
Dance 0:de885a6da962 232
Dance 0:de885a6da962 233 void USBHAL::EP0read(void) {
Dance 0:de885a6da962 234 // Start an endpoint 0 read
Dance 0:de885a6da962 235
Dance 0:de885a6da962 236 // The USB ISR will call USBDevice_EP0out() when a packet has been read,
Dance 0:de885a6da962 237 // the USBDevice layer then calls USBBusInterface_EP0getReadResult() to
Dance 0:de885a6da962 238 // read the data.
Dance 0:de885a6da962 239
Dance 0:de885a6da962 240 ep[0].out[0] = CMDSTS_A |CMDSTS_NBYTES(MAX_PACKET_SIZE_EP0) \
Dance 0:de885a6da962 241 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out);
Dance 0:de885a6da962 242 }
Dance 0:de885a6da962 243
Dance 0:de885a6da962 244 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
Dance 0:de885a6da962 245 // Complete an endpoint 0 read
Dance 0:de885a6da962 246 uint32_t bytesRead;
Dance 0:de885a6da962 247
Dance 0:de885a6da962 248 // Find how many bytes were read
Dance 0:de885a6da962 249 bytesRead = MAX_PACKET_SIZE_EP0 - BYTES_REMAINING(ep[0].out[0]);
Dance 0:de885a6da962 250
Dance 0:de885a6da962 251 // Copy data
Dance 0:de885a6da962 252 USBMemCopy(buffer, ct->out, bytesRead);
Dance 0:de885a6da962 253 return bytesRead;
Dance 0:de885a6da962 254 }
Dance 0:de885a6da962 255
Dance 0:de885a6da962 256
Dance 0:de885a6da962 257 void USBHAL::EP0readStage(void) {
Dance 0:de885a6da962 258 // Not required
Dance 0:de885a6da962 259 }
Dance 0:de885a6da962 260
Dance 0:de885a6da962 261 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
Dance 0:de885a6da962 262 // Start and endpoint 0 write
Dance 0:de885a6da962 263
Dance 0:de885a6da962 264 // The USB ISR will call USBDevice_EP0in() when the data has
Dance 0:de885a6da962 265 // been written, the USBDevice layer then calls
Dance 0:de885a6da962 266 // USBBusInterface_EP0getWriteResult() to complete the transaction.
Dance 0:de885a6da962 267
Dance 0:de885a6da962 268 // Copy data
Dance 0:de885a6da962 269 USBMemCopy(ct->in, buffer, size);
Dance 0:de885a6da962 270
Dance 0:de885a6da962 271 // Start transfer
Dance 0:de885a6da962 272 ep[0].in[0] = CMDSTS_A | CMDSTS_NBYTES(size) \
Dance 0:de885a6da962 273 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->in);
Dance 0:de885a6da962 274 }
Dance 0:de885a6da962 275
Dance 0:de885a6da962 276
Dance 0:de885a6da962 277 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
Dance 0:de885a6da962 278 uint8_t bf = 0;
Dance 0:de885a6da962 279 uint32_t flags = 0;
Dance 0:de885a6da962 280
Dance 0:de885a6da962 281 //check which buffer must be filled
Dance 0:de885a6da962 282 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Dance 0:de885a6da962 283 // Double buffered
Dance 0:de885a6da962 284 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 285 bf = 1;
Dance 0:de885a6da962 286 } else {
Dance 0:de885a6da962 287 bf = 0;
Dance 0:de885a6da962 288 }
Dance 0:de885a6da962 289 }
Dance 0:de885a6da962 290
Dance 0:de885a6da962 291 // if isochronous endpoint, T = 1
Dance 0:de885a6da962 292 if(endpointState[endpoint].options & ISOCHRONOUS)
Dance 0:de885a6da962 293 {
Dance 0:de885a6da962 294 flags |= CMDSTS_T;
Dance 0:de885a6da962 295 }
Dance 0:de885a6da962 296
Dance 0:de885a6da962 297 //Active the endpoint for reading
Dance 0:de885a6da962 298 ep[PHY_TO_LOG(endpoint)].out[bf] = CMDSTS_A | CMDSTS_NBYTES(maximumSize) \
Dance 0:de885a6da962 299 | CMDSTS_ADDRESS_OFFSET((uint32_t)ct->out) | flags;
Dance 0:de885a6da962 300 return EP_PENDING;
Dance 0:de885a6da962 301 }
Dance 0:de885a6da962 302
Dance 0:de885a6da962 303 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t *data, uint32_t *bytesRead) {
Dance 0:de885a6da962 304
Dance 0:de885a6da962 305 uint8_t bf = 0;
Dance 0:de885a6da962 306
Dance 0:de885a6da962 307 if (!(epComplete & EP(endpoint)))
Dance 0:de885a6da962 308 return EP_PENDING;
Dance 0:de885a6da962 309 else {
Dance 0:de885a6da962 310 epComplete &= ~EP(endpoint);
Dance 0:de885a6da962 311
Dance 0:de885a6da962 312 //check which buffer has been filled
Dance 0:de885a6da962 313 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Dance 0:de885a6da962 314 // Double buffered (here we read the previous buffer which was used)
Dance 0:de885a6da962 315 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 316 bf = 0;
Dance 0:de885a6da962 317 } else {
Dance 0:de885a6da962 318 bf = 1;
Dance 0:de885a6da962 319 }
Dance 0:de885a6da962 320 }
Dance 0:de885a6da962 321
Dance 0:de885a6da962 322 // Find how many bytes were read
Dance 0:de885a6da962 323 *bytesRead = (uint32_t) (endpointState[endpoint].maxPacket - BYTES_REMAINING(ep[PHY_TO_LOG(endpoint)].out[bf]));
Dance 0:de885a6da962 324
Dance 0:de885a6da962 325 // Copy data
Dance 0:de885a6da962 326 USBMemCopy(data, ct->out, *bytesRead);
Dance 0:de885a6da962 327 return EP_COMPLETED;
Dance 0:de885a6da962 328 }
Dance 0:de885a6da962 329 }
Dance 0:de885a6da962 330
Dance 0:de885a6da962 331 void USBHAL::EP0getWriteResult(void) {
Dance 0:de885a6da962 332 // Not required
Dance 0:de885a6da962 333 }
Dance 0:de885a6da962 334
Dance 0:de885a6da962 335 void USBHAL::EP0stall(void) {
Dance 0:de885a6da962 336 ep[0].in[0] = CMDSTS_S;
Dance 0:de885a6da962 337 ep[0].out[0] = CMDSTS_S;
Dance 0:de885a6da962 338 }
Dance 0:de885a6da962 339
Dance 0:de885a6da962 340 void USBHAL::setAddress(uint8_t address) {
Dance 0:de885a6da962 341 devCmdStat &= ~DEV_ADDR_MASK;
Dance 0:de885a6da962 342 devCmdStat |= DEV_ADDR(address);
Dance 0:de885a6da962 343 LPC_USB->DEVCMDSTAT = devCmdStat;
Dance 0:de885a6da962 344 }
Dance 0:de885a6da962 345
Dance 0:de885a6da962 346 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
Dance 0:de885a6da962 347 uint32_t flags = 0;
Dance 0:de885a6da962 348 uint32_t bf;
Dance 0:de885a6da962 349
Dance 0:de885a6da962 350 // Validate parameters
Dance 0:de885a6da962 351 if (data == NULL) {
Dance 0:de885a6da962 352 return EP_INVALID;
Dance 0:de885a6da962 353 }
Dance 0:de885a6da962 354
Dance 0:de885a6da962 355 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Dance 0:de885a6da962 356 return EP_INVALID;
Dance 0:de885a6da962 357 }
Dance 0:de885a6da962 358
Dance 0:de885a6da962 359 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
Dance 0:de885a6da962 360 return EP_INVALID;
Dance 0:de885a6da962 361 }
Dance 0:de885a6da962 362
Dance 0:de885a6da962 363 if (size > endpointState[endpoint].maxPacket) {
Dance 0:de885a6da962 364 return EP_INVALID;
Dance 0:de885a6da962 365 }
Dance 0:de885a6da962 366
Dance 0:de885a6da962 367 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Dance 0:de885a6da962 368 // Double buffered
Dance 0:de885a6da962 369 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 370 bf = 1;
Dance 0:de885a6da962 371 } else {
Dance 0:de885a6da962 372 bf = 0;
Dance 0:de885a6da962 373 }
Dance 0:de885a6da962 374 } else {
Dance 0:de885a6da962 375 // Single buffered
Dance 0:de885a6da962 376 bf = 0;
Dance 0:de885a6da962 377 }
Dance 0:de885a6da962 378
Dance 0:de885a6da962 379 // Check if already active
Dance 0:de885a6da962 380 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
Dance 0:de885a6da962 381 return EP_INVALID;
Dance 0:de885a6da962 382 }
Dance 0:de885a6da962 383
Dance 0:de885a6da962 384 // Check if stalled
Dance 0:de885a6da962 385 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
Dance 0:de885a6da962 386 return EP_STALLED;
Dance 0:de885a6da962 387 }
Dance 0:de885a6da962 388
Dance 0:de885a6da962 389 // Copy data to USB RAM
Dance 0:de885a6da962 390 USBMemCopy((uint8_t *)endpointState[endpoint].buffer[bf], data, size);
Dance 0:de885a6da962 391
Dance 0:de885a6da962 392 // Add options
Dance 0:de885a6da962 393 if (endpointState[endpoint].options & RATE_FEEDBACK_MODE) {
Dance 0:de885a6da962 394 flags |= CMDSTS_RF;
Dance 0:de885a6da962 395 }
Dance 0:de885a6da962 396
Dance 0:de885a6da962 397 if (endpointState[endpoint].options & ISOCHRONOUS) {
Dance 0:de885a6da962 398 flags |= CMDSTS_T;
Dance 0:de885a6da962 399 }
Dance 0:de885a6da962 400
Dance 0:de885a6da962 401 // Add transfer
Dance 0:de885a6da962 402 ep[PHY_TO_LOG(endpoint)].in[bf] = CMDSTS_ADDRESS_OFFSET( \
Dance 0:de885a6da962 403 endpointState[endpoint].buffer[bf]) \
Dance 0:de885a6da962 404 | CMDSTS_NBYTES(size) | CMDSTS_A | flags;
Dance 0:de885a6da962 405
Dance 0:de885a6da962 406 return EP_PENDING;
Dance 0:de885a6da962 407 }
Dance 0:de885a6da962 408
Dance 0:de885a6da962 409 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
Dance 0:de885a6da962 410 uint32_t bf;
Dance 0:de885a6da962 411
Dance 0:de885a6da962 412 // Validate parameters
Dance 0:de885a6da962 413 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Dance 0:de885a6da962 414 return EP_INVALID;
Dance 0:de885a6da962 415 }
Dance 0:de885a6da962 416
Dance 0:de885a6da962 417 if (OUT_EP(endpoint)) {
Dance 0:de885a6da962 418 return EP_INVALID;
Dance 0:de885a6da962 419 }
Dance 0:de885a6da962 420
Dance 0:de885a6da962 421 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Dance 0:de885a6da962 422 // Double buffered // TODO: FIX THIS
Dance 0:de885a6da962 423 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 424 bf = 1;
Dance 0:de885a6da962 425 } else {
Dance 0:de885a6da962 426 bf = 0;
Dance 0:de885a6da962 427 }
Dance 0:de885a6da962 428 } else {
Dance 0:de885a6da962 429 // Single buffered
Dance 0:de885a6da962 430 bf = 0;
Dance 0:de885a6da962 431 }
Dance 0:de885a6da962 432
Dance 0:de885a6da962 433 // Check if endpoint still active
Dance 0:de885a6da962 434 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_A) {
Dance 0:de885a6da962 435 return EP_PENDING;
Dance 0:de885a6da962 436 }
Dance 0:de885a6da962 437
Dance 0:de885a6da962 438 // Check if stalled
Dance 0:de885a6da962 439 if (ep[PHY_TO_LOG(endpoint)].in[bf] & CMDSTS_S) {
Dance 0:de885a6da962 440 return EP_STALLED;
Dance 0:de885a6da962 441 }
Dance 0:de885a6da962 442
Dance 0:de885a6da962 443 return EP_COMPLETED;
Dance 0:de885a6da962 444 }
Dance 0:de885a6da962 445
Dance 0:de885a6da962 446 void USBHAL::stallEndpoint(uint8_t endpoint) {
Dance 0:de885a6da962 447
Dance 0:de885a6da962 448 // FIX: should this clear active bit?
Dance 0:de885a6da962 449 if (IN_EP(endpoint)) {
Dance 0:de885a6da962 450 ep[PHY_TO_LOG(endpoint)].in[0] |= CMDSTS_S;
Dance 0:de885a6da962 451 ep[PHY_TO_LOG(endpoint)].in[1] |= CMDSTS_S;
Dance 0:de885a6da962 452 } else {
Dance 0:de885a6da962 453 ep[PHY_TO_LOG(endpoint)].out[0] |= CMDSTS_S;
Dance 0:de885a6da962 454 ep[PHY_TO_LOG(endpoint)].out[1] |= CMDSTS_S;
Dance 0:de885a6da962 455 }
Dance 0:de885a6da962 456 }
Dance 0:de885a6da962 457
Dance 0:de885a6da962 458 void USBHAL::unstallEndpoint(uint8_t endpoint) {
Dance 0:de885a6da962 459 if (LPC_USB->EPBUFCFG & EP(endpoint)) {
Dance 0:de885a6da962 460 // Double buffered
Dance 0:de885a6da962 461 if (IN_EP(endpoint)) {
Dance 0:de885a6da962 462 ep[PHY_TO_LOG(endpoint)].in[0] = 0; // S = 0
Dance 0:de885a6da962 463 ep[PHY_TO_LOG(endpoint)].in[1] = 0; // S = 0
Dance 0:de885a6da962 464
Dance 0:de885a6da962 465 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 466 ep[PHY_TO_LOG(endpoint)].in[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 467 } else {
Dance 0:de885a6da962 468 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 469 }
Dance 0:de885a6da962 470 } else {
Dance 0:de885a6da962 471 ep[PHY_TO_LOG(endpoint)].out[0] = 0; // S = 0
Dance 0:de885a6da962 472 ep[PHY_TO_LOG(endpoint)].out[1] = 0; // S = 0
Dance 0:de885a6da962 473
Dance 0:de885a6da962 474 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 475 ep[PHY_TO_LOG(endpoint)].out[1] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 476 } else {
Dance 0:de885a6da962 477 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 478 }
Dance 0:de885a6da962 479 }
Dance 0:de885a6da962 480 } else {
Dance 0:de885a6da962 481 // Single buffered
Dance 0:de885a6da962 482 if (IN_EP(endpoint)) {
Dance 0:de885a6da962 483 ep[PHY_TO_LOG(endpoint)].in[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 484 } else {
Dance 0:de885a6da962 485 ep[PHY_TO_LOG(endpoint)].out[0] = CMDSTS_TR; // S = 0, TR = 1, TV = 0
Dance 0:de885a6da962 486 }
Dance 0:de885a6da962 487 }
Dance 0:de885a6da962 488 }
Dance 0:de885a6da962 489
Dance 0:de885a6da962 490 bool USBHAL::getEndpointStallState(unsigned char endpoint) {
Dance 0:de885a6da962 491 if (IN_EP(endpoint)) {
Dance 0:de885a6da962 492 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 493 if (ep[PHY_TO_LOG(endpoint)].in[1] & CMDSTS_S) {
Dance 0:de885a6da962 494 return true;
Dance 0:de885a6da962 495 }
Dance 0:de885a6da962 496 } else {
Dance 0:de885a6da962 497 if (ep[PHY_TO_LOG(endpoint)].in[0] & CMDSTS_S) {
Dance 0:de885a6da962 498 return true;
Dance 0:de885a6da962 499 }
Dance 0:de885a6da962 500 }
Dance 0:de885a6da962 501 } else {
Dance 0:de885a6da962 502 if (LPC_USB->EPINUSE & EP(endpoint)) {
Dance 0:de885a6da962 503 if (ep[PHY_TO_LOG(endpoint)].out[1] & CMDSTS_S) {
Dance 0:de885a6da962 504 return true;
Dance 0:de885a6da962 505 }
Dance 0:de885a6da962 506 } else {
Dance 0:de885a6da962 507 if (ep[PHY_TO_LOG(endpoint)].out[0] & CMDSTS_S) {
Dance 0:de885a6da962 508 return true;
Dance 0:de885a6da962 509 }
Dance 0:de885a6da962 510 }
Dance 0:de885a6da962 511 }
Dance 0:de885a6da962 512
Dance 0:de885a6da962 513 return false;
Dance 0:de885a6da962 514 }
Dance 0:de885a6da962 515
Dance 0:de885a6da962 516 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t options) {
Dance 0:de885a6da962 517 uint32_t tmpEpRamPtr;
Dance 0:de885a6da962 518
Dance 0:de885a6da962 519 if (endpoint > LAST_PHYSICAL_ENDPOINT) {
Dance 0:de885a6da962 520 return false;
Dance 0:de885a6da962 521 }
Dance 0:de885a6da962 522
Dance 0:de885a6da962 523 // Not applicable to the control endpoints
Dance 0:de885a6da962 524 if ((endpoint==EP0IN) || (endpoint==EP0OUT)) {
Dance 0:de885a6da962 525 return false;
Dance 0:de885a6da962 526 }
Dance 0:de885a6da962 527
Dance 0:de885a6da962 528 // Allocate buffers in USB RAM
Dance 0:de885a6da962 529 tmpEpRamPtr = epRamPtr;
Dance 0:de885a6da962 530
Dance 0:de885a6da962 531 // Must be 64 byte aligned
Dance 0:de885a6da962 532 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
Dance 0:de885a6da962 533
Dance 0:de885a6da962 534 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
Dance 0:de885a6da962 535 // Out of memory
Dance 0:de885a6da962 536 return false;
Dance 0:de885a6da962 537 }
Dance 0:de885a6da962 538
Dance 0:de885a6da962 539 // Allocate first buffer
Dance 0:de885a6da962 540 endpointState[endpoint].buffer[0] = tmpEpRamPtr;
Dance 0:de885a6da962 541 tmpEpRamPtr += maxPacket;
Dance 0:de885a6da962 542
Dance 0:de885a6da962 543 if (!(options & SINGLE_BUFFERED)) {
Dance 0:de885a6da962 544 // Must be 64 byte aligned
Dance 0:de885a6da962 545 tmpEpRamPtr = ROUND_UP_TO_MULTIPLE(tmpEpRamPtr, 64);
Dance 0:de885a6da962 546
Dance 0:de885a6da962 547 if ((tmpEpRamPtr + maxPacket) > (USB_RAM_START + USB_RAM_SIZE)) {
Dance 0:de885a6da962 548 // Out of memory
Dance 0:de885a6da962 549 return false;
Dance 0:de885a6da962 550 }
Dance 0:de885a6da962 551
Dance 0:de885a6da962 552 // Allocate second buffer
Dance 0:de885a6da962 553 endpointState[endpoint].buffer[1] = tmpEpRamPtr;
Dance 0:de885a6da962 554 tmpEpRamPtr += maxPacket;
Dance 0:de885a6da962 555 }
Dance 0:de885a6da962 556
Dance 0:de885a6da962 557 // Commit to this USB RAM allocation
Dance 0:de885a6da962 558 epRamPtr = tmpEpRamPtr;
Dance 0:de885a6da962 559
Dance 0:de885a6da962 560 // Remaining endpoint state values
Dance 0:de885a6da962 561 endpointState[endpoint].maxPacket = maxPacket;
Dance 0:de885a6da962 562 endpointState[endpoint].options = options;
Dance 0:de885a6da962 563
Dance 0:de885a6da962 564 // Enable double buffering if required
Dance 0:de885a6da962 565 if (options & SINGLE_BUFFERED) {
Dance 0:de885a6da962 566 LPC_USB->EPBUFCFG &= ~EP(endpoint);
Dance 0:de885a6da962 567 } else {
Dance 0:de885a6da962 568 // Double buffered
Dance 0:de885a6da962 569 LPC_USB->EPBUFCFG |= EP(endpoint);
Dance 0:de885a6da962 570 }
Dance 0:de885a6da962 571
Dance 0:de885a6da962 572 // Enable interrupt
Dance 0:de885a6da962 573 LPC_USB->INTEN |= EP(endpoint);
Dance 0:de885a6da962 574
Dance 0:de885a6da962 575 // Enable endpoint
Dance 0:de885a6da962 576 unstallEndpoint(endpoint);
Dance 0:de885a6da962 577 return true;
Dance 0:de885a6da962 578 }
Dance 0:de885a6da962 579
Dance 0:de885a6da962 580 void USBHAL::remoteWakeup(void) {
Dance 0:de885a6da962 581 // Clearing DSUS bit initiates a remote wakeup if the
Dance 0:de885a6da962 582 // device is currently enabled and suspended - otherwise
Dance 0:de885a6da962 583 // it has no effect.
Dance 0:de885a6da962 584 LPC_USB->DEVCMDSTAT = devCmdStat & ~DSUS;
Dance 0:de885a6da962 585 }
Dance 0:de885a6da962 586
Dance 0:de885a6da962 587
Dance 0:de885a6da962 588 static void disableEndpoints(void) {
Dance 0:de885a6da962 589 uint32_t logEp;
Dance 0:de885a6da962 590
Dance 0:de885a6da962 591 // Ref. Table 158 "When a bus reset is received, software
Dance 0:de885a6da962 592 // must set the disable bit of all endpoints to 1".
Dance 0:de885a6da962 593
Dance 0:de885a6da962 594 for (logEp = 1; logEp < NUMBER_OF_LOGICAL_ENDPOINTS; logEp++) {
Dance 0:de885a6da962 595 ep[logEp].out[0] = CMDSTS_D;
Dance 0:de885a6da962 596 ep[logEp].out[1] = CMDSTS_D;
Dance 0:de885a6da962 597 ep[logEp].in[0] = CMDSTS_D;
Dance 0:de885a6da962 598 ep[logEp].in[1] = CMDSTS_D;
Dance 0:de885a6da962 599 }
Dance 0:de885a6da962 600
Dance 0:de885a6da962 601 // Start of USB RAM for endpoints > 0
Dance 0:de885a6da962 602 epRamPtr = usbRamPtr;
Dance 0:de885a6da962 603 }
Dance 0:de885a6da962 604
Dance 0:de885a6da962 605
Dance 0:de885a6da962 606
Dance 0:de885a6da962 607 void USBHAL::_usbisr(void) {
Dance 0:de885a6da962 608 instance->usbisr();
Dance 0:de885a6da962 609 }
Dance 0:de885a6da962 610
Dance 0:de885a6da962 611 void USBHAL::usbisr(void) {
Dance 0:de885a6da962 612 // Start of frame
Dance 0:de885a6da962 613 if (LPC_USB->INTSTAT & FRAME_INT) {
Dance 0:de885a6da962 614 // Clear SOF interrupt
Dance 0:de885a6da962 615 LPC_USB->INTSTAT = FRAME_INT;
Dance 0:de885a6da962 616
Dance 0:de885a6da962 617 // SOF event, read frame number
Dance 0:de885a6da962 618 SOF(FRAME_NR(LPC_USB->INFO));
Dance 0:de885a6da962 619 }
Dance 0:de885a6da962 620
Dance 0:de885a6da962 621 // Device state
Dance 0:de885a6da962 622 if (LPC_USB->INTSTAT & DEV_INT) {
Dance 0:de885a6da962 623 LPC_USB->INTSTAT = DEV_INT;
Dance 0:de885a6da962 624
Dance 0:de885a6da962 625 if (LPC_USB->DEVCMDSTAT & DSUS_C) {
Dance 0:de885a6da962 626 // Suspend status changed
Dance 0:de885a6da962 627 LPC_USB->DEVCMDSTAT = devCmdStat | DSUS_C;
Dance 0:de885a6da962 628 if((LPC_USB->DEVCMDSTAT & DSUS) != 0) {
Dance 0:de885a6da962 629 suspendStateChanged(1);
Dance 0:de885a6da962 630 }
Dance 0:de885a6da962 631 }
Dance 0:de885a6da962 632
Dance 0:de885a6da962 633 if (LPC_USB->DEVCMDSTAT & DRES_C) {
Dance 0:de885a6da962 634 // Bus reset
Dance 0:de885a6da962 635 LPC_USB->DEVCMDSTAT = devCmdStat | DRES_C;
Dance 0:de885a6da962 636
Dance 0:de885a6da962 637 suspendStateChanged(0);
Dance 0:de885a6da962 638
Dance 0:de885a6da962 639 // Disable endpoints > 0
Dance 0:de885a6da962 640 disableEndpoints();
Dance 0:de885a6da962 641
Dance 0:de885a6da962 642 // Bus reset event
Dance 0:de885a6da962 643 busReset();
Dance 0:de885a6da962 644 }
Dance 0:de885a6da962 645 }
Dance 0:de885a6da962 646
Dance 0:de885a6da962 647 // Endpoint 0
Dance 0:de885a6da962 648 if (LPC_USB->INTSTAT & EP(EP0OUT)) {
Dance 0:de885a6da962 649 // Clear EP0OUT/SETUP interrupt
Dance 0:de885a6da962 650 LPC_USB->INTSTAT = EP(EP0OUT);
Dance 0:de885a6da962 651
Dance 0:de885a6da962 652 // Check if SETUP
Dance 0:de885a6da962 653 if (LPC_USB->DEVCMDSTAT & SETUP) {
Dance 0:de885a6da962 654 // Clear Active and Stall bits for EP0
Dance 0:de885a6da962 655 // Documentation does not make it clear if we must use the
Dance 0:de885a6da962 656 // EPSKIP register to achieve this, Fig. 16 and NXP reference
Dance 0:de885a6da962 657 // code suggests we can just clear the Active bits - check with
Dance 0:de885a6da962 658 // NXP to be sure.
Dance 0:de885a6da962 659 ep[0].in[0] = 0;
Dance 0:de885a6da962 660 ep[0].out[0] = 0;
Dance 0:de885a6da962 661
Dance 0:de885a6da962 662 // Clear EP0IN interrupt
Dance 0:de885a6da962 663 LPC_USB->INTSTAT = EP(EP0IN);
Dance 0:de885a6da962 664
Dance 0:de885a6da962 665 // Clear SETUP (and INTONNAK_CI/O) in device status register
Dance 0:de885a6da962 666 LPC_USB->DEVCMDSTAT = devCmdStat | SETUP;
Dance 0:de885a6da962 667
Dance 0:de885a6da962 668 // EP0 SETUP event (SETUP data received)
Dance 0:de885a6da962 669 EP0setupCallback();
Dance 0:de885a6da962 670 } else {
Dance 0:de885a6da962 671 // EP0OUT ACK event (OUT data received)
Dance 0:de885a6da962 672 EP0out();
Dance 0:de885a6da962 673 }
Dance 0:de885a6da962 674 }
Dance 0:de885a6da962 675
Dance 0:de885a6da962 676 if (LPC_USB->INTSTAT & EP(EP0IN)) {
Dance 0:de885a6da962 677 // Clear EP0IN interrupt
Dance 0:de885a6da962 678 LPC_USB->INTSTAT = EP(EP0IN);
Dance 0:de885a6da962 679
Dance 0:de885a6da962 680 // EP0IN ACK event (IN data sent)
Dance 0:de885a6da962 681 EP0in();
Dance 0:de885a6da962 682 }
Dance 0:de885a6da962 683
Dance 0:de885a6da962 684 for (uint8_t num = 2; num < 5*2; num++) {
Dance 0:de885a6da962 685 if (LPC_USB->INTSTAT & EP(num)) {
Dance 0:de885a6da962 686 LPC_USB->INTSTAT = EP(num);
Dance 0:de885a6da962 687 epComplete |= EP(num);
Dance 0:de885a6da962 688 if ((instance->*(epCallback[num - 2]))()) {
Dance 0:de885a6da962 689 epComplete &= ~EP(num);
Dance 0:de885a6da962 690 }
Dance 0:de885a6da962 691 }
Dance 0:de885a6da962 692 }
Dance 0:de885a6da962 693 }
Dance 0:de885a6da962 694
Dance 0:de885a6da962 695 #endif