RC_Simulator.....By Jafar Qutteineh with mods to connect my Futaba 9C to \'RC Helicopter\' by http://www.alphamacsoftware.com/

Dependencies:   mbed

Committer:
cbayley
Date:
Thu Dec 15 03:24:33 2011 +0000
Revision:
0:65b9d8f621d2
Initial

Who changed what in which revision?

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