A fully-Android-compatible two joysticks USB driver for LPC1768. The joysticks have 1 hat, 6 buttons, and there are 1P, 2P buttons.

Dependencies:   mbed

Fork of app-board-Joystick by Chris Styles

Committer:
Alberto_Wino
Date:
Sat Dec 17 15:10:12 2016 +0000
Revision:
3:f1a8ec4659f8
Parent:
1:76c47d2ba442
Added a two-interface configuration, which fully works on Android.

Who changed what in which revision?

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