USB HID Joystick Example (modified USBMouse)

Dependencies:   mbed

Committer:
bricklife
Date:
Wed Jan 19 11:27:13 2011 +0000
Revision:
1:ec6deffecbd3
Parent:
0:d450e82033a1

        

Who changed what in which revision?

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