Transistor Gijutsu, October 2014, Special Features Chapter 9, Software of the Function Generator トランジスタ技術2014年10月号 特集第9章のソフトウェア わがまま波形発生器のソフトウェア

Dependencies:   USBDevice mbed

Information

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

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

概要

このプログラムは、ソフトウエアDDSにより、任意の波形を出力(2ch)します。 特徴は次のとおりです。

  • PWM出力をDAコンバータとして利用します。
  • 周波数や波形、バースト条件などを個別に設定できる独立した出力を2チャネル持っています。
  • 周波数分解能0.023mHz
  • 周波数範囲0.023mHz~10kHz
  • 各チャネルにそれぞれ、波形の先頭で出力されるトリガ出力があります。
  • 出力波形を関数で定義できます。
  • 休止波数、出力波数、を設定することでバースト波形が出力できます。

ファイル

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

  • DDS.cpp - DDSによる波形発生
  • main.cpp - main()関数

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

Committer:
Dance
Date:
Fri Aug 29 08:33:17 2014 +0000
Revision:
0:f1ecca559ec3
Transistor Gijutsu, October 2014, Special Features Chapter 9; ????????2014?10??????9????????

Who changed what in which revision?

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