N64 to USB HID interface

Dependencies:   mbed

Committer:
igor_m
Date:
Wed Dec 10 14:22:30 2014 +0000
Revision:
5:eb93a4f91396
Parent:
0:547c5459faa6
Initial Release

Who changed what in which revision?

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