This program allows to transform analog signal from rotary dial phone to numeric keys.

Dependencies:   mbed

Committer:
amigainc
Date:
Sun Aug 07 09:10:18 2011 +0000
Revision:
0:2c8568cec97f

        

Who changed what in which revision?

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