A optical beam breaker detector that appears to aPC as a USB keyboard, typing characters when the beam is broken

Dependencies:   mbed

Committer:
chris
Date:
Thu May 12 16:44:09 2011 +0000
Revision:
0:9d0f47bc66da

        

Who changed what in which revision?

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