USBMouse Example

Dependencies:   mbed

Committer:
simon
Date:
Wed Apr 07 13:42:47 2010 +0000
Revision:
1:eb68149218fd

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
simon 1:eb68149218fd 1 /* usbdc.cpp */
simon 1:eb68149218fd 2 /* USB device controller */
simon 1:eb68149218fd 3 /* Copyright (c) Phil Wright 2008 */
simon 1:eb68149218fd 4
simon 1:eb68149218fd 5 #include "mbed.h"
simon 1:eb68149218fd 6 #include "usbdc.h"
simon 1:eb68149218fd 7 #include "cmsis.h"
simon 1:eb68149218fd 8
simon 1:eb68149218fd 9 #ifdef TARGET_LPC2368
simon 1:eb68149218fd 10 #undef LPC_USB_BASE
simon 1:eb68149218fd 11 #define LPC_USB_BASE (0xFFE0C000) /* TODO */
simon 1:eb68149218fd 12 #endif
simon 1:eb68149218fd 13
simon 1:eb68149218fd 14 /* Power Control for Peripherals register */
simon 1:eb68149218fd 15 #define PCUSB ((unsigned long)1<<31)
simon 1:eb68149218fd 16
simon 1:eb68149218fd 17 /* USB Clock Control register */
simon 1:eb68149218fd 18 #define DEV_CLK_EN ((unsigned long)1<<1)
simon 1:eb68149218fd 19 #define AHB_CLK_EN ((unsigned long)1<<4)
simon 1:eb68149218fd 20
simon 1:eb68149218fd 21 /* USB Clock Status register */
simon 1:eb68149218fd 22 #define DEV_CLK_ON ((unsigned long)1<<1)
simon 1:eb68149218fd 23 #define AHB_CLK_ON ((unsigned long)1<<4)
simon 1:eb68149218fd 24
simon 1:eb68149218fd 25 /* USB Device Interupt registers */
simon 1:eb68149218fd 26 #define FRAME ((unsigned long)1<<0)
simon 1:eb68149218fd 27 #define EP_FAST ((unsigned long)1<<1)
simon 1:eb68149218fd 28 #define EP_SLOW ((unsigned long)1<<2)
simon 1:eb68149218fd 29 #define DEV_STAT ((unsigned long)1<<3)
simon 1:eb68149218fd 30 #define CCEMPTY ((unsigned long)1<<4)
simon 1:eb68149218fd 31 #define CDFULL ((unsigned long)1<<5)
simon 1:eb68149218fd 32 #define RxENDPKT ((unsigned long)1<<6)
simon 1:eb68149218fd 33 #define TxENDPKT ((unsigned long)1<<7)
simon 1:eb68149218fd 34 #define EP_RLZED ((unsigned long)1<<8)
simon 1:eb68149218fd 35 #define ERR_INT ((unsigned long)1<<9)
simon 1:eb68149218fd 36
simon 1:eb68149218fd 37 /* Endpoint Interrupt Registers */
simon 1:eb68149218fd 38 #define EP(endpoint) (1<<endpoint)
simon 1:eb68149218fd 39
simon 1:eb68149218fd 40 /* USB Control register */
simon 1:eb68149218fd 41 #define RD_EN (1<<0)
simon 1:eb68149218fd 42 #define WR_EN (1<<1)
simon 1:eb68149218fd 43 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
simon 1:eb68149218fd 44
simon 1:eb68149218fd 45 /* USB Receive Packet Length register */
simon 1:eb68149218fd 46 #define DV ((unsigned long)1<<10)
simon 1:eb68149218fd 47 #define PKT_RDY ((unsigned long)1<<11)
simon 1:eb68149218fd 48 #define PKT_LNGTH_MASK (0x3ff)
simon 1:eb68149218fd 49
simon 1:eb68149218fd 50 /* Serial Interface Engine (SIE) */
simon 1:eb68149218fd 51 #define SIE_WRITE (0x01)
simon 1:eb68149218fd 52 #define SIE_READ (0x02)
simon 1:eb68149218fd 53 #define SIE_COMMAND (0x05)
simon 1:eb68149218fd 54 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
simon 1:eb68149218fd 55
simon 1:eb68149218fd 56 /* SIE Command codes */
simon 1:eb68149218fd 57 #define SIE_CMD_SET_ADDRESS (0xD0)
simon 1:eb68149218fd 58 #define SIE_CMD_CONFIGURE_DEVICE (0xD8)
simon 1:eb68149218fd 59 #define SIE_CMD_SET_MODE (0xF3)
simon 1:eb68149218fd 60 #define SIE_CMD_READ_FRAME_NUMBER (0xF5)
simon 1:eb68149218fd 61 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
simon 1:eb68149218fd 62 #define SIE_CMD_SET_DEVICE_STATUS (0xFE)
simon 1:eb68149218fd 63 #define SIE_CMD_GET_DEVICE_STATUS (0xFE)
simon 1:eb68149218fd 64 #define SIE_CMD_GET_ERROR_CODE (0xFF)
simon 1:eb68149218fd 65 #define SIE_CMD_READ_ERROR_STATUS (0xFB)
simon 1:eb68149218fd 66
simon 1:eb68149218fd 67 #define SIE_CMD_SELECT_ENDPOINT(endpoint) (0x00+endpoint)
simon 1:eb68149218fd 68 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
simon 1:eb68149218fd 69 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint) (0x40+endpoint)
simon 1:eb68149218fd 70
simon 1:eb68149218fd 71 #define SIE_CMD_CLEAR_BUFFER (0xF2)
simon 1:eb68149218fd 72 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
simon 1:eb68149218fd 73
simon 1:eb68149218fd 74 /* SIE Device Status register */
simon 1:eb68149218fd 75 #define SIE_DS_CON (1<<0)
simon 1:eb68149218fd 76 #define SIE_DS_CON_CH (1<<1)
simon 1:eb68149218fd 77 #define SIE_DS_SUS (1<<2)
simon 1:eb68149218fd 78 #define SIE_DS_SUS_CH (1<<3)
simon 1:eb68149218fd 79 #define SIE_DS_RST (1<<4)
simon 1:eb68149218fd 80
simon 1:eb68149218fd 81 /* SIE Device Set Address register */
simon 1:eb68149218fd 82 #define SIE_DSA_DEV_EN (1<<7)
simon 1:eb68149218fd 83
simon 1:eb68149218fd 84 /* SIE Configue Device register */
simon 1:eb68149218fd 85 #define SIE_CONF_DEVICE (1<<0)
simon 1:eb68149218fd 86
simon 1:eb68149218fd 87 /* Select Endpoint register */
simon 1:eb68149218fd 88 #define SIE_SE_FE (1<<0)
simon 1:eb68149218fd 89 #define SIE_SE_ST (1<<1)
simon 1:eb68149218fd 90 #define SIE_SE_STP (1<<2)
simon 1:eb68149218fd 91 #define SIE_SE_PO (1<<3)
simon 1:eb68149218fd 92 #define SIE_SE_EPN (1<<4)
simon 1:eb68149218fd 93 #define SIE_SE_B_1_FULL (1<<5)
simon 1:eb68149218fd 94 #define SIE_SE_B_2_FULL (1<<6)
simon 1:eb68149218fd 95
simon 1:eb68149218fd 96 /* Set Endpoint Status command */
simon 1:eb68149218fd 97 #define SIE_SES_ST (1<<0)
simon 1:eb68149218fd 98 #define SIE_SES_DA (1<<5)
simon 1:eb68149218fd 99 #define SIE_SES_RF_MO (1<<6)
simon 1:eb68149218fd 100 #define SIE_SES_CND_ST (1<<7)
simon 1:eb68149218fd 101
simon 1:eb68149218fd 102 usbdc *usbdc::instance;
simon 1:eb68149218fd 103
simon 1:eb68149218fd 104 usbdc::usbdc()
simon 1:eb68149218fd 105 {
simon 1:eb68149218fd 106 #ifdef TARGET_LPC1768
simon 1:eb68149218fd 107 LPC_SC->USBCLKCFG=5; /* TODO */
simon 1:eb68149218fd 108 #endif
simon 1:eb68149218fd 109
simon 1:eb68149218fd 110 /* Enable power to USB device controller */
simon 1:eb68149218fd 111 LPC_SC->PCONP |= PCUSB;
simon 1:eb68149218fd 112
simon 1:eb68149218fd 113 /* Enable USB clocks */
simon 1:eb68149218fd 114 LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
simon 1:eb68149218fd 115 while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
simon 1:eb68149218fd 116
simon 1:eb68149218fd 117 /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
simon 1:eb68149218fd 118 LPC_PINCON->PINSEL1 &= 0xc3ffffff;
simon 1:eb68149218fd 119 LPC_PINCON->PINSEL1 |= 0x14000000;
simon 1:eb68149218fd 120
simon 1:eb68149218fd 121 #ifdef ENABLE_VBUS
simon 1:eb68149218fd 122 /* Configure pin P1.30 to be VBUS */
simon 1:eb68149218fd 123 LPC_PINCON->PINSEL3 &= 0xcfffffff;
simon 1:eb68149218fd 124 LPC_PINCON->PINSEL3 |= 0x20000000;
simon 1:eb68149218fd 125
simon 1:eb68149218fd 126 /* Configure pin P1.30 to have pull-down */
simon 1:eb68149218fd 127 LPC_PINCON->PINMODE3 |= 0x30000000;
simon 1:eb68149218fd 128 #endif
simon 1:eb68149218fd 129
simon 1:eb68149218fd 130 /* Configure pin P2.9 to be Connect */
simon 1:eb68149218fd 131 LPC_PINCON->PINSEL4 &= 0xfffcffff;
simon 1:eb68149218fd 132 LPC_PINCON->PINSEL4 |= 0x00040000;
simon 1:eb68149218fd 133
simon 1:eb68149218fd 134 /* Connect must be low for at least 2.5uS */
simon 1:eb68149218fd 135 wait_ms(1);
simon 1:eb68149218fd 136
simon 1:eb68149218fd 137 /* Attach IRQ */
simon 1:eb68149218fd 138 instance = this;
simon 1:eb68149218fd 139 NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
simon 1:eb68149218fd 140 NVIC_EnableIRQ(USB_IRQn);
simon 1:eb68149218fd 141
simon 1:eb68149218fd 142 /* Enable device interrupts */
simon 1:eb68149218fd 143 enableEvents();
simon 1:eb68149218fd 144 }
simon 1:eb68149218fd 145
simon 1:eb68149218fd 146 void usbdc::connect(void)
simon 1:eb68149218fd 147 {
simon 1:eb68149218fd 148 /* Connect USB device */
simon 1:eb68149218fd 149 unsigned char status;
simon 1:eb68149218fd 150
simon 1:eb68149218fd 151 status = getDeviceStatus();
simon 1:eb68149218fd 152 setDeviceStatus(status | SIE_DS_CON);
simon 1:eb68149218fd 153 }
simon 1:eb68149218fd 154
simon 1:eb68149218fd 155 void usbdc::disconnect(void)
simon 1:eb68149218fd 156 {
simon 1:eb68149218fd 157 /* Disconnect USB device */
simon 1:eb68149218fd 158 unsigned char status;
simon 1:eb68149218fd 159
simon 1:eb68149218fd 160 status = getDeviceStatus();
simon 1:eb68149218fd 161 setDeviceStatus(status & ~SIE_DS_CON);
simon 1:eb68149218fd 162 }
simon 1:eb68149218fd 163
simon 1:eb68149218fd 164 void usbdc::SIECommand(unsigned long command)
simon 1:eb68149218fd 165 {
simon 1:eb68149218fd 166 /* The command phase of a SIE transaction */
simon 1:eb68149218fd 167 LPC_USB->USBDevIntClr = CCEMPTY;
simon 1:eb68149218fd 168 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
simon 1:eb68149218fd 169 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
simon 1:eb68149218fd 170 }
simon 1:eb68149218fd 171
simon 1:eb68149218fd 172 void usbdc::SIEWriteData(unsigned char data)
simon 1:eb68149218fd 173 {
simon 1:eb68149218fd 174 /* The data write phase of a SIE transaction */
simon 1:eb68149218fd 175 LPC_USB->USBDevIntClr = CCEMPTY;
simon 1:eb68149218fd 176 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
simon 1:eb68149218fd 177 while (!(LPC_USB->USBDevIntSt & CCEMPTY));
simon 1:eb68149218fd 178 }
simon 1:eb68149218fd 179
simon 1:eb68149218fd 180 unsigned char usbdc::SIEReadData(unsigned long command)
simon 1:eb68149218fd 181 {
simon 1:eb68149218fd 182 /* The data read phase of a SIE transaction */
simon 1:eb68149218fd 183 LPC_USB->USBDevIntClr = CDFULL;
simon 1:eb68149218fd 184 LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
simon 1:eb68149218fd 185 while (!(LPC_USB->USBDevIntSt & CDFULL));
simon 1:eb68149218fd 186 return (unsigned char)LPC_USB->USBCmdData;
simon 1:eb68149218fd 187 }
simon 1:eb68149218fd 188
simon 1:eb68149218fd 189 void usbdc::setDeviceStatus(unsigned char status)
simon 1:eb68149218fd 190 {
simon 1:eb68149218fd 191 /* Write SIE device status register */
simon 1:eb68149218fd 192 SIECommand(SIE_CMD_SET_DEVICE_STATUS);
simon 1:eb68149218fd 193 SIEWriteData(status);
simon 1:eb68149218fd 194 }
simon 1:eb68149218fd 195
simon 1:eb68149218fd 196 unsigned char usbdc::getDeviceStatus(void)
simon 1:eb68149218fd 197 {
simon 1:eb68149218fd 198 /* Read SIE device status register */
simon 1:eb68149218fd 199 SIECommand(SIE_CMD_GET_DEVICE_STATUS);
simon 1:eb68149218fd 200 return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
simon 1:eb68149218fd 201 }
simon 1:eb68149218fd 202
simon 1:eb68149218fd 203 void usbdc::setAddress(unsigned char address)
simon 1:eb68149218fd 204 {
simon 1:eb68149218fd 205 /* Write SIE device address register */
simon 1:eb68149218fd 206 SIECommand(SIE_CMD_SET_ADDRESS);
simon 1:eb68149218fd 207 SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
simon 1:eb68149218fd 208 }
simon 1:eb68149218fd 209
simon 1:eb68149218fd 210 unsigned char usbdc::selectEndpoint(unsigned char endpoint)
simon 1:eb68149218fd 211 {
simon 1:eb68149218fd 212 /* SIE select endpoint command */
simon 1:eb68149218fd 213 SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
simon 1:eb68149218fd 214 return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
simon 1:eb68149218fd 215 }
simon 1:eb68149218fd 216
simon 1:eb68149218fd 217 #if 1
simon 1:eb68149218fd 218 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
simon 1:eb68149218fd 219 {
simon 1:eb68149218fd 220 /* SIE select endpoint and clear interrupt command */
simon 1:eb68149218fd 221 /* Using the Select Endpoint / Clear Interrupt SIE command does not seem */
simon 1:eb68149218fd 222 /* to clear the appropriate bit in EP_INT_STAT? - using EP_INT_CLR instead */
simon 1:eb68149218fd 223 LPC_USB->USBEpIntClr = EP(endpoint);
simon 1:eb68149218fd 224 while (!(LPC_USB->USBDevIntSt & CDFULL));
simon 1:eb68149218fd 225 return (unsigned char)LPC_USB->USBCmdData;
simon 1:eb68149218fd 226 }
simon 1:eb68149218fd 227 #else
simon 1:eb68149218fd 228 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
simon 1:eb68149218fd 229 {
simon 1:eb68149218fd 230 /* SIE select endpoint and clear interrupt command */
simon 1:eb68149218fd 231 SIECommand(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
simon 1:eb68149218fd 232 return SIEReadData(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
simon 1:eb68149218fd 233 }
simon 1:eb68149218fd 234 #endif
simon 1:eb68149218fd 235
simon 1:eb68149218fd 236 unsigned char usbdc::clearBuffer(void)
simon 1:eb68149218fd 237 {
simon 1:eb68149218fd 238 /* SIE clear buffer command */
simon 1:eb68149218fd 239 SIECommand(SIE_CMD_CLEAR_BUFFER);
simon 1:eb68149218fd 240 return SIEReadData(SIE_CMD_CLEAR_BUFFER);
simon 1:eb68149218fd 241 }
simon 1:eb68149218fd 242
simon 1:eb68149218fd 243 void usbdc::validateBuffer(void)
simon 1:eb68149218fd 244 {
simon 1:eb68149218fd 245 /* SIE validate buffer command */
simon 1:eb68149218fd 246 SIECommand(SIE_CMD_VALIDATE_BUFFER);
simon 1:eb68149218fd 247 }
simon 1:eb68149218fd 248
simon 1:eb68149218fd 249 void usbdc::setEndpointStatus(unsigned char endpoint, unsigned char status)
simon 1:eb68149218fd 250 {
simon 1:eb68149218fd 251 /* SIE set endpoint status command */
simon 1:eb68149218fd 252 SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
simon 1:eb68149218fd 253 SIEWriteData(status);
simon 1:eb68149218fd 254 }
simon 1:eb68149218fd 255
simon 1:eb68149218fd 256 void usbdc::realiseEndpoint(unsigned char endpoint, unsigned long maxPacket)
simon 1:eb68149218fd 257 {
simon 1:eb68149218fd 258 /* Realise an endpoint */
simon 1:eb68149218fd 259 LPC_USB->USBDevIntClr = EP_RLZED;
simon 1:eb68149218fd 260 LPC_USB->USBReEp |= EP(endpoint);
simon 1:eb68149218fd 261 LPC_USB->USBEpInd = endpoint;
simon 1:eb68149218fd 262 LPC_USB->USBMaxPSize = maxPacket;
simon 1:eb68149218fd 263
simon 1:eb68149218fd 264 while (!(LPC_USB->USBDevIntSt & EP_RLZED));
simon 1:eb68149218fd 265 LPC_USB->USBDevIntClr = EP_RLZED;
simon 1:eb68149218fd 266
simon 1:eb68149218fd 267 /* Clear stall state */
simon 1:eb68149218fd 268 endpointStallState &= ~EP(endpoint);
simon 1:eb68149218fd 269 }
simon 1:eb68149218fd 270
simon 1:eb68149218fd 271 void usbdc::enableEndpointEvent(unsigned char endpoint)
simon 1:eb68149218fd 272 {
simon 1:eb68149218fd 273 /* Enable an endpoint interrupt */
simon 1:eb68149218fd 274 LPC_USB->USBEpIntEn |= EP(endpoint);
simon 1:eb68149218fd 275 }
simon 1:eb68149218fd 276
simon 1:eb68149218fd 277 void usbdc::disableEndpointEvent(unsigned char endpoint)
simon 1:eb68149218fd 278 {
simon 1:eb68149218fd 279 /* Disable an endpoint interrupt */
simon 1:eb68149218fd 280 LPC_USB->USBEpIntEn &= ~EP(endpoint);
simon 1:eb68149218fd 281 }
simon 1:eb68149218fd 282
simon 1:eb68149218fd 283 void usbdc::stallEndpoint(unsigned char endpoint)
simon 1:eb68149218fd 284 {
simon 1:eb68149218fd 285 /* Stall an endpoint */
simon 1:eb68149218fd 286 if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
simon 1:eb68149218fd 287 {
simon 1:eb68149218fd 288 /* Conditionally stall both control endpoints */
simon 1:eb68149218fd 289 setEndpointStatus(EP0OUT, SIE_SES_CND_ST);
simon 1:eb68149218fd 290 }
simon 1:eb68149218fd 291 else
simon 1:eb68149218fd 292 {
simon 1:eb68149218fd 293 setEndpointStatus(endpoint, SIE_SES_ST);
simon 1:eb68149218fd 294
simon 1:eb68149218fd 295 /* Update stall state */
simon 1:eb68149218fd 296 endpointStallState |= EP(endpoint);
simon 1:eb68149218fd 297 }
simon 1:eb68149218fd 298 }
simon 1:eb68149218fd 299
simon 1:eb68149218fd 300 void usbdc::unstallEndpoint(unsigned char endpoint)
simon 1:eb68149218fd 301 {
simon 1:eb68149218fd 302 /* Unstall an endpoint. The endpoint will also be reinitialised */
simon 1:eb68149218fd 303 setEndpointStatus(endpoint, 0);
simon 1:eb68149218fd 304
simon 1:eb68149218fd 305 /* Update stall state */
simon 1:eb68149218fd 306 endpointStallState &= ~EP(endpoint);
simon 1:eb68149218fd 307 }
simon 1:eb68149218fd 308
simon 1:eb68149218fd 309 bool usbdc::getEndpointStallState(unsigned char endpoint)
simon 1:eb68149218fd 310 {
simon 1:eb68149218fd 311 /* Returns true if endpoint stalled */
simon 1:eb68149218fd 312 return endpointStallState & EP(endpoint);
simon 1:eb68149218fd 313 }
simon 1:eb68149218fd 314
simon 1:eb68149218fd 315 void usbdc::configureDevice(void)
simon 1:eb68149218fd 316 {
simon 1:eb68149218fd 317 /* SIE Configure device command */
simon 1:eb68149218fd 318 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
simon 1:eb68149218fd 319 SIEWriteData(SIE_CONF_DEVICE);
simon 1:eb68149218fd 320 }
simon 1:eb68149218fd 321
simon 1:eb68149218fd 322 void usbdc::unconfigureDevice(void)
simon 1:eb68149218fd 323 {
simon 1:eb68149218fd 324 /* SIE Configure device command */
simon 1:eb68149218fd 325 SIECommand(SIE_CMD_CONFIGURE_DEVICE);
simon 1:eb68149218fd 326 SIEWriteData(0);
simon 1:eb68149218fd 327 }
simon 1:eb68149218fd 328
simon 1:eb68149218fd 329 unsigned long usbdc::endpointRead(unsigned char endpoint, unsigned char *buffer)
simon 1:eb68149218fd 330 {
simon 1:eb68149218fd 331 /* Read from an OUT endpoint */
simon 1:eb68149218fd 332 unsigned long size;
simon 1:eb68149218fd 333 unsigned long i;
simon 1:eb68149218fd 334 unsigned long data;
simon 1:eb68149218fd 335 unsigned char offset;
simon 1:eb68149218fd 336
simon 1:eb68149218fd 337 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
simon 1:eb68149218fd 338 while (!(LPC_USB->USBRxPLen & PKT_RDY));
simon 1:eb68149218fd 339
simon 1:eb68149218fd 340 size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
simon 1:eb68149218fd 341
simon 1:eb68149218fd 342 offset = 0;
simon 1:eb68149218fd 343
simon 1:eb68149218fd 344 for (i=0; i<size; i++)
simon 1:eb68149218fd 345 {
simon 1:eb68149218fd 346 if (offset==0)
simon 1:eb68149218fd 347 {
simon 1:eb68149218fd 348 /* Fetch up to four bytes of data as a word */
simon 1:eb68149218fd 349 data = LPC_USB->USBRxData;
simon 1:eb68149218fd 350 }
simon 1:eb68149218fd 351
simon 1:eb68149218fd 352 /* extract a byte */
simon 1:eb68149218fd 353 *buffer++ = data>>offset;
simon 1:eb68149218fd 354
simon 1:eb68149218fd 355 /* move on to the next byte */
simon 1:eb68149218fd 356 offset = (offset + 8) % 32;
simon 1:eb68149218fd 357 }
simon 1:eb68149218fd 358
simon 1:eb68149218fd 359 /* Clear RD_EN to cover zero length packet case */
simon 1:eb68149218fd 360 LPC_USB->USBCtrl=0;
simon 1:eb68149218fd 361
simon 1:eb68149218fd 362 selectEndpoint(endpoint);
simon 1:eb68149218fd 363 clearBuffer();
simon 1:eb68149218fd 364
simon 1:eb68149218fd 365 return size;
simon 1:eb68149218fd 366 }
simon 1:eb68149218fd 367
simon 1:eb68149218fd 368 void usbdc::endpointWrite(unsigned char endpoint, unsigned char *buffer, unsigned long size)
simon 1:eb68149218fd 369 {
simon 1:eb68149218fd 370 /* Write to an IN endpoint */
simon 1:eb68149218fd 371 unsigned long temp, data;
simon 1:eb68149218fd 372 unsigned char offset;
simon 1:eb68149218fd 373
simon 1:eb68149218fd 374 LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
simon 1:eb68149218fd 375
simon 1:eb68149218fd 376 LPC_USB->USBTxPLen = size;
simon 1:eb68149218fd 377 offset = 0;
simon 1:eb68149218fd 378 data = 0;
simon 1:eb68149218fd 379
simon 1:eb68149218fd 380 if (size>0)
simon 1:eb68149218fd 381 {
simon 1:eb68149218fd 382 do {
simon 1:eb68149218fd 383 /* Fetch next data byte into a word-sized temporary variable */
simon 1:eb68149218fd 384 temp = *buffer++;
simon 1:eb68149218fd 385
simon 1:eb68149218fd 386 /* Add to current data word */
simon 1:eb68149218fd 387 temp = temp << offset;
simon 1:eb68149218fd 388 data = data | temp;
simon 1:eb68149218fd 389
simon 1:eb68149218fd 390 /* move on to the next byte */
simon 1:eb68149218fd 391 offset = (offset + 8) % 32;
simon 1:eb68149218fd 392 size--;
simon 1:eb68149218fd 393
simon 1:eb68149218fd 394 if ((offset==0) || (size==0))
simon 1:eb68149218fd 395 {
simon 1:eb68149218fd 396 /* Write the word to the endpoint */
simon 1:eb68149218fd 397 LPC_USB->USBTxData = data;
simon 1:eb68149218fd 398 data = 0;
simon 1:eb68149218fd 399 }
simon 1:eb68149218fd 400 } while (size>0);
simon 1:eb68149218fd 401 }
simon 1:eb68149218fd 402
simon 1:eb68149218fd 403 /* Clear WR_EN to cover zero length packet case */
simon 1:eb68149218fd 404 LPC_USB->USBCtrl=0;
simon 1:eb68149218fd 405
simon 1:eb68149218fd 406 selectEndpoint(endpoint);
simon 1:eb68149218fd 407 validateBuffer();
simon 1:eb68149218fd 408 }
simon 1:eb68149218fd 409
simon 1:eb68149218fd 410 void usbdc::enableEvents(void)
simon 1:eb68149218fd 411 {
simon 1:eb68149218fd 412 /* Enable interrupt sources */
simon 1:eb68149218fd 413 LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
simon 1:eb68149218fd 414 }
simon 1:eb68149218fd 415
simon 1:eb68149218fd 416 void usbdc::disableEvents(void)
simon 1:eb68149218fd 417 {
simon 1:eb68149218fd 418 /* Disable interrupt sources */
simon 1:eb68149218fd 419 LPC_USB->USBDevIntClr = EP_SLOW | DEV_STAT;
simon 1:eb68149218fd 420 }
simon 1:eb68149218fd 421
simon 1:eb68149218fd 422 void usbdc::usbisr(void)
simon 1:eb68149218fd 423 {
simon 1:eb68149218fd 424 unsigned char devStat;
simon 1:eb68149218fd 425
simon 1:eb68149218fd 426 if (LPC_USB->USBDevIntSt & FRAME)
simon 1:eb68149218fd 427 {
simon 1:eb68149218fd 428 /* Frame event */
simon 1:eb68149218fd 429 deviceEventFrame();
simon 1:eb68149218fd 430 /* Clear interrupt status flag */
simon 1:eb68149218fd 431 LPC_USB->USBDevIntClr = FRAME;
simon 1:eb68149218fd 432 }
simon 1:eb68149218fd 433
simon 1:eb68149218fd 434 if (LPC_USB->USBDevIntSt & DEV_STAT)
simon 1:eb68149218fd 435 {
simon 1:eb68149218fd 436 /* Device Status interrupt */
simon 1:eb68149218fd 437 /* Must clear the interrupt status flag before reading the device status from the SIE */
simon 1:eb68149218fd 438 LPC_USB->USBDevIntClr = DEV_STAT;
simon 1:eb68149218fd 439
simon 1:eb68149218fd 440 /* Read device status from SIE */
simon 1:eb68149218fd 441 devStat = getDeviceStatus();
simon 1:eb68149218fd 442
simon 1:eb68149218fd 443 if (devStat & SIE_DS_RST)
simon 1:eb68149218fd 444 {
simon 1:eb68149218fd 445 /* Bus reset */
simon 1:eb68149218fd 446 deviceEventReset();
simon 1:eb68149218fd 447 }
simon 1:eb68149218fd 448 }
simon 1:eb68149218fd 449
simon 1:eb68149218fd 450 if (LPC_USB->USBDevIntSt & EP_SLOW)
simon 1:eb68149218fd 451 {
simon 1:eb68149218fd 452 /* (Slow) Endpoint Interrupt */
simon 1:eb68149218fd 453
simon 1:eb68149218fd 454 /* Process each endpoint interrupt */
simon 1:eb68149218fd 455 if (LPC_USB->USBEpIntSt & EP(EP0OUT))
simon 1:eb68149218fd 456 {
simon 1:eb68149218fd 457 if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
simon 1:eb68149218fd 458 {
simon 1:eb68149218fd 459 /* this is a setup packet */
simon 1:eb68149218fd 460 endpointEventEP0Setup();
simon 1:eb68149218fd 461 }
simon 1:eb68149218fd 462 else
simon 1:eb68149218fd 463 {
simon 1:eb68149218fd 464 endpointEventEP0Out();
simon 1:eb68149218fd 465 }
simon 1:eb68149218fd 466 }
simon 1:eb68149218fd 467
simon 1:eb68149218fd 468 if (LPC_USB->USBEpIntSt & EP(EP0IN))
simon 1:eb68149218fd 469 {
simon 1:eb68149218fd 470 selectEndpointClearInterrupt(EP0IN);
simon 1:eb68149218fd 471 endpointEventEP0In();
simon 1:eb68149218fd 472 }
simon 1:eb68149218fd 473
simon 1:eb68149218fd 474 if (LPC_USB->USBEpIntSt & EP(EP1OUT))
simon 1:eb68149218fd 475 {
simon 1:eb68149218fd 476 selectEndpointClearInterrupt(EP1OUT);
simon 1:eb68149218fd 477 endpointEventEP1Out();
simon 1:eb68149218fd 478 }
simon 1:eb68149218fd 479
simon 1:eb68149218fd 480 if (LPC_USB->USBEpIntSt & EP(EP1IN))
simon 1:eb68149218fd 481 {
simon 1:eb68149218fd 482 selectEndpointClearInterrupt(EP1IN);
simon 1:eb68149218fd 483 endpointEventEP1In();
simon 1:eb68149218fd 484 }
simon 1:eb68149218fd 485
simon 1:eb68149218fd 486 if (LPC_USB->USBEpIntSt & EP(EP2OUT))
simon 1:eb68149218fd 487 {
simon 1:eb68149218fd 488 selectEndpointClearInterrupt(EP2OUT);
simon 1:eb68149218fd 489 endpointEventEP2Out();
simon 1:eb68149218fd 490 }
simon 1:eb68149218fd 491
simon 1:eb68149218fd 492 if (LPC_USB->USBEpIntSt & EP(EP2IN))
simon 1:eb68149218fd 493 {
simon 1:eb68149218fd 494 selectEndpointClearInterrupt(EP2IN);
simon 1:eb68149218fd 495 endpointEventEP2In();
simon 1:eb68149218fd 496 }
simon 1:eb68149218fd 497
simon 1:eb68149218fd 498 /* Clear interrupt status flag */
simon 1:eb68149218fd 499 /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
simon 1:eb68149218fd 500 LPC_USB->USBDevIntClr = EP_SLOW;
simon 1:eb68149218fd 501 }
simon 1:eb68149218fd 502 }
simon 1:eb68149218fd 503
simon 1:eb68149218fd 504
simon 1:eb68149218fd 505 void usbdc::_usbisr(void)
simon 1:eb68149218fd 506 {
simon 1:eb68149218fd 507 instance->usbisr();
simon 1:eb68149218fd 508 }
simon 1:eb68149218fd 509
simon 1:eb68149218fd 510 void usbdc::deviceEventReset(void)
simon 1:eb68149218fd 511 {
simon 1:eb68149218fd 512 }
simon 1:eb68149218fd 513
simon 1:eb68149218fd 514 void usbdc::deviceEventFrame(void)
simon 1:eb68149218fd 515 {
simon 1:eb68149218fd 516 }
simon 1:eb68149218fd 517
simon 1:eb68149218fd 518 void usbdc::endpointEventEP0Setup(void)
simon 1:eb68149218fd 519 {
simon 1:eb68149218fd 520 }
simon 1:eb68149218fd 521
simon 1:eb68149218fd 522 void usbdc::endpointEventEP0In(void)
simon 1:eb68149218fd 523 {
simon 1:eb68149218fd 524 }
simon 1:eb68149218fd 525
simon 1:eb68149218fd 526 void usbdc::endpointEventEP0Out(void)
simon 1:eb68149218fd 527 {
simon 1:eb68149218fd 528 }
simon 1:eb68149218fd 529
simon 1:eb68149218fd 530 void usbdc::endpointEventEP1In(void)
simon 1:eb68149218fd 531 {
simon 1:eb68149218fd 532 }
simon 1:eb68149218fd 533
simon 1:eb68149218fd 534 void usbdc::endpointEventEP1Out(void)
simon 1:eb68149218fd 535 {
simon 1:eb68149218fd 536 }
simon 1:eb68149218fd 537
simon 1:eb68149218fd 538 void usbdc::endpointEventEP2In(void)
simon 1:eb68149218fd 539 {
simon 1:eb68149218fd 540 }
simon 1:eb68149218fd 541
simon 1:eb68149218fd 542 void usbdc::endpointEventEP2Out(void)
simon 1:eb68149218fd 543 {
simon 1:eb68149218fd 544 }