Joystick enabled version of USBHID -library. Has full Playstation 3 functionality including button pressures and a working home-button implementation, while maintaining full PC/MAC/linux -compatibility. basic operation of the lib: #include "mbed.h" #include "usbhid.h" USBJoystick joystick; int main() { while(1) { char dpad = 0xf; /*only the rightmost 4 bits matter*/ short button = 0xff; /*only the rightmost 13 bits matter*/ /*buttons are square, cross, circle, triangle, l1, r1, l2, r2, l3, r3, home.*/ char stick1x = 0; char stick1y = 0; char stick2x = 0; char stick2y = 0; joystick.joystick(dpad, buttons, stick1x, stick1y, stick2x, stick2y); wait_ms(5); } }

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbdc.cpp Source File

usbdc.cpp

00001 /* usbdc.cpp */
00002 /* USB device controller */
00003 /* Copyright (c) Phil Wright 2008 */
00004 
00005 #include "mbed.h"  
00006 #include "usbdc.h"
00007 #include "cmsis.h"
00008 
00009 #ifdef  TARGET_LPC2368
00010 #undef  LPC_USB_BASE
00011 #define LPC_USB_BASE (0xFFE0C000) /* TODO */
00012 #endif         
00013 
00014 /* Power Control for Peripherals register */
00015 #define PCUSB      ((unsigned long)1<<31)
00016 
00017 /* USB Clock Control register */
00018 #define DEV_CLK_EN ((unsigned long)1<<1)
00019 #define AHB_CLK_EN ((unsigned long)1<<4)
00020 
00021 /* USB Clock Status register */
00022 #define DEV_CLK_ON ((unsigned long)1<<1)
00023 #define AHB_CLK_ON ((unsigned long)1<<4)
00024 
00025 /* USB Device Interupt registers */
00026 #define FRAME      ((unsigned long)1<<0)
00027 #define EP_FAST    ((unsigned long)1<<1)
00028 #define EP_SLOW    ((unsigned long)1<<2)
00029 #define DEV_STAT   ((unsigned long)1<<3)
00030 #define CCEMPTY    ((unsigned long)1<<4)
00031 #define CDFULL     ((unsigned long)1<<5)
00032 #define RxENDPKT   ((unsigned long)1<<6)
00033 #define TxENDPKT   ((unsigned long)1<<7)
00034 #define EP_RLZED   ((unsigned long)1<<8)
00035 #define ERR_INT    ((unsigned long)1<<9)
00036 
00037 /* Endpoint Interrupt Registers */
00038 #define EP(endpoint) (1<<endpoint)
00039 
00040 /* USB Control register */
00041 #define RD_EN (1<<0)
00042 #define WR_EN (1<<1)
00043 #define LOG_ENDPOINT(endpoint) ((endpoint>>1)<<2)
00044 
00045 /* USB Receive Packet Length register */
00046 #define DV      ((unsigned long)1<<10)
00047 #define PKT_RDY ((unsigned long)1<<11)
00048 #define PKT_LNGTH_MASK (0x3ff)
00049 
00050 /* Serial Interface Engine (SIE) */
00051 #define SIE_WRITE   (0x01)
00052 #define SIE_READ    (0x02)
00053 #define SIE_COMMAND (0x05)
00054 #define SIE_CMD_CODE(phase, data) ((phase<<8)|(data<<16))
00055 
00056 /* SIE Command codes */
00057 #define SIE_CMD_SET_ADDRESS        (0xD0)
00058 #define SIE_CMD_CONFIGURE_DEVICE   (0xD8)
00059 #define SIE_CMD_SET_MODE           (0xF3)
00060 #define SIE_CMD_READ_FRAME_NUMBER  (0xF5)
00061 #define SIE_CMD_READ_TEST_REGISTER (0xFD)
00062 #define SIE_CMD_SET_DEVICE_STATUS  (0xFE)
00063 #define SIE_CMD_GET_DEVICE_STATUS  (0xFE)
00064 #define SIE_CMD_GET_ERROR_CODE     (0xFF)
00065 #define SIE_CMD_READ_ERROR_STATUS  (0xFB)
00066 
00067 #define SIE_CMD_SELECT_ENDPOINT(endpoint)                 (0x00+endpoint)
00068 #define SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint) (0x40+endpoint)
00069 #define SIE_CMD_SET_ENDPOINT_STATUS(endpoint)             (0x40+endpoint)
00070 
00071 #define SIE_CMD_CLEAR_BUFFER    (0xF2)
00072 #define SIE_CMD_VALIDATE_BUFFER (0xFA)
00073 
00074 /* SIE Device Status register */
00075 #define SIE_DS_CON    (1<<0)
00076 #define SIE_DS_CON_CH (1<<1)
00077 #define SIE_DS_SUS    (1<<2)
00078 #define SIE_DS_SUS_CH (1<<3)
00079 #define SIE_DS_RST    (1<<4)
00080 
00081 /* SIE Device Set Address register */
00082 #define SIE_DSA_DEV_EN  (1<<7)
00083 
00084 /* SIE Configue Device register */
00085 #define SIE_CONF_DEVICE (1<<0)
00086 
00087 /* Select Endpoint register */
00088 #define SIE_SE_FE       (1<<0)
00089 #define SIE_SE_ST       (1<<1)
00090 #define SIE_SE_STP      (1<<2)
00091 #define SIE_SE_PO       (1<<3)
00092 #define SIE_SE_EPN      (1<<4)
00093 #define SIE_SE_B_1_FULL (1<<5)
00094 #define SIE_SE_B_2_FULL (1<<6)
00095 
00096 /* Set Endpoint Status command */
00097 #define SIE_SES_ST      (1<<0)
00098 #define SIE_SES_DA      (1<<5)
00099 #define SIE_SES_RF_MO   (1<<6)
00100 #define SIE_SES_CND_ST  (1<<7)
00101 
00102 usbdc *usbdc::instance;
00103 
00104 usbdc::usbdc()
00105 {
00106 #ifdef TARGET_LPC1768
00107     LPC_SC->USBCLKCFG=5; /* TODO */
00108 #endif
00109 
00110     /* Enable power to USB device controller */
00111     LPC_SC->PCONP |= PCUSB;
00112 
00113     /* Enable USB clocks */
00114     LPC_USB->USBClkCtrl |= DEV_CLK_EN | AHB_CLK_EN;
00115     while (LPC_USB->USBClkSt != (DEV_CLK_ON | AHB_CLK_ON));
00116 
00117     /* Configure pins P0.29 and P0.30 to be USB D+ and USB D- */
00118     LPC_PINCON->PINSEL1 &= 0xc3ffffff;
00119     LPC_PINCON->PINSEL1 |= 0x14000000;
00120 
00121 #ifdef ENABLE_VBUS    
00122     /* Configure pin P1.30 to be VBUS */
00123     LPC_PINCON->PINSEL3 &= 0xcfffffff;
00124     LPC_PINCON->PINSEL3 |= 0x20000000;
00125     
00126     /* Configure pin P1.30 to have pull-down */
00127     LPC_PINCON->PINMODE3 |= 0x30000000;
00128 #endif
00129         
00130     /* Configure pin P2.9 to be Connect */
00131     LPC_PINCON->PINSEL4 &= 0xfffcffff;
00132     LPC_PINCON->PINSEL4 |= 0x00040000;
00133     
00134     /* Connect must be low for at least 2.5uS */
00135     wait_ms(1);
00136     
00137     /* Attach IRQ */
00138     instance = this;
00139     NVIC_SetVector(USB_IRQn, (uint32_t)&_usbisr);
00140     NVIC_EnableIRQ(USB_IRQn); 
00141 
00142     /* Enable device interrupts */
00143     enableEvents();
00144 }
00145 
00146 void usbdc::connect(void)
00147 {
00148     /* Connect USB device */
00149     unsigned char status;
00150     
00151     status = getDeviceStatus();
00152     setDeviceStatus(status | SIE_DS_CON);
00153 }
00154 
00155 void usbdc::disconnect(void)
00156 {
00157     /* Disconnect USB device */
00158     unsigned char status;
00159     
00160     status = getDeviceStatus();
00161     setDeviceStatus(status & ~SIE_DS_CON);
00162 }
00163 
00164 void usbdc::SIECommand(unsigned long command)
00165 {
00166     /* The command phase of a SIE transaction */
00167     LPC_USB->USBDevIntClr = CCEMPTY;
00168     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_COMMAND, command);
00169     while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 
00170 }
00171 
00172 void usbdc::SIEWriteData(unsigned char data)
00173 {
00174     /* The data write phase of a SIE transaction */
00175     LPC_USB->USBDevIntClr = CCEMPTY;
00176     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_WRITE, data);
00177     while (!(LPC_USB->USBDevIntSt & CCEMPTY)); 
00178 }
00179 
00180 unsigned char usbdc::SIEReadData(unsigned long command)
00181 {
00182     /* The data read phase of a SIE transaction */
00183     LPC_USB->USBDevIntClr = CDFULL;
00184     LPC_USB->USBCmdCode = SIE_CMD_CODE(SIE_READ, command);
00185     while (!(LPC_USB->USBDevIntSt & CDFULL));
00186     return (unsigned char)LPC_USB->USBCmdData;
00187 }
00188 
00189 void usbdc::setDeviceStatus(unsigned char status)
00190 {
00191     /* Write SIE device status register */
00192     SIECommand(SIE_CMD_SET_DEVICE_STATUS);
00193     SIEWriteData(status);
00194 }
00195 
00196 unsigned char usbdc::getDeviceStatus(void)
00197 {
00198     /* Read SIE device status register */
00199     SIECommand(SIE_CMD_GET_DEVICE_STATUS);
00200     return SIEReadData(SIE_CMD_GET_DEVICE_STATUS);
00201 }
00202 
00203 void usbdc::setAddress(unsigned char address)
00204 {
00205     /* Write SIE device address register */
00206     SIECommand(SIE_CMD_SET_ADDRESS);
00207     SIEWriteData((address & 0x7f) | SIE_DSA_DEV_EN);
00208 }
00209 
00210 unsigned char usbdc::selectEndpoint(unsigned char endpoint)
00211 {
00212     /* SIE select endpoint command */
00213     SIECommand(SIE_CMD_SELECT_ENDPOINT(endpoint));
00214     return SIEReadData(SIE_CMD_SELECT_ENDPOINT(endpoint));
00215 }
00216 
00217 #if 1
00218 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
00219 {
00220     /* SIE select endpoint and clear interrupt command */
00221     /* Using the Select Endpoint / Clear Interrupt SIE command does not seem   */
00222     /* to clear the appropriate bit in EP_INT_STAT? - using EP_INT_CLR instead */
00223     LPC_USB->USBEpIntClr = EP(endpoint);
00224     while (!(LPC_USB->USBDevIntSt & CDFULL));
00225     return (unsigned char)LPC_USB->USBCmdData;
00226 }
00227 #else
00228 unsigned char usbdc::selectEndpointClearInterrupt(unsigned char endpoint)
00229 {
00230     /* SIE select endpoint and clear interrupt command */
00231     SIECommand(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
00232     return SIEReadData(SIE_CMD_SELECT_ENDPOINT_CLEAR_INTERRUPT(endpoint));
00233 }
00234 #endif
00235 
00236 unsigned char usbdc::clearBuffer(void)
00237 {
00238     /* SIE clear buffer command */
00239     SIECommand(SIE_CMD_CLEAR_BUFFER);
00240     return SIEReadData(SIE_CMD_CLEAR_BUFFER);
00241 }
00242 
00243 void usbdc::validateBuffer(void)
00244 {
00245     /* SIE validate buffer command */
00246     SIECommand(SIE_CMD_VALIDATE_BUFFER);
00247 }
00248 
00249 void usbdc::setEndpointStatus(unsigned char endpoint, unsigned char status)
00250 {
00251     /* SIE set endpoint status command */
00252     SIECommand(SIE_CMD_SET_ENDPOINT_STATUS(endpoint));
00253     SIEWriteData(status);
00254 }
00255 
00256 void usbdc::realiseEndpoint(unsigned char endpoint, unsigned long maxPacket)
00257 {
00258     /* Realise an endpoint */
00259     LPC_USB->USBDevIntClr = EP_RLZED;
00260     LPC_USB->USBReEp |= EP(endpoint);
00261     LPC_USB->USBEpInd = endpoint;
00262     LPC_USB->USBMaxPSize = maxPacket;
00263     
00264     while (!(LPC_USB->USBDevIntSt & EP_RLZED));
00265     LPC_USB->USBDevIntClr = EP_RLZED;
00266     
00267     /* Clear stall state */
00268     endpointStallState &= ~EP(endpoint);
00269 }
00270 
00271 void usbdc::enableEndpointEvent(unsigned char endpoint)
00272 {
00273     /* Enable an endpoint interrupt */
00274     LPC_USB->USBEpIntEn |= EP(endpoint);
00275 }
00276 
00277 void usbdc::disableEndpointEvent(unsigned char endpoint)
00278 {
00279     /* Disable an endpoint interrupt */
00280     LPC_USB->USBEpIntEn &= ~EP(endpoint);
00281 }
00282 
00283 void usbdc::stallEndpoint(unsigned char endpoint)
00284 {
00285     /* Stall an endpoint */
00286     if ( (endpoint==EP0IN) || (endpoint==EP0OUT) )
00287     {
00288         /* Conditionally stall both control endpoints */
00289         setEndpointStatus(EP0OUT, SIE_SES_CND_ST);
00290     }
00291     else
00292     {
00293         setEndpointStatus(endpoint, SIE_SES_ST);
00294         
00295         /* Update stall state */
00296         endpointStallState |= EP(endpoint);
00297     }
00298 }
00299 
00300 void usbdc::unstallEndpoint(unsigned char endpoint)
00301 {
00302     /* Unstall an endpoint. The endpoint will also be reinitialised */
00303     setEndpointStatus(endpoint, 0);
00304     
00305     /* Update stall state */
00306     endpointStallState &= ~EP(endpoint);
00307 }
00308 
00309 bool usbdc::getEndpointStallState(unsigned char endpoint)
00310 { 
00311     /* Returns true if endpoint stalled */
00312     return endpointStallState & EP(endpoint);
00313 }
00314 
00315 void usbdc::configureDevice(void)
00316 {
00317     /* SIE Configure device command */
00318     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00319     SIEWriteData(SIE_CONF_DEVICE);
00320 }
00321 
00322 void usbdc::unconfigureDevice(void)
00323 {
00324     /* SIE Configure device command */
00325     SIECommand(SIE_CMD_CONFIGURE_DEVICE);
00326     SIEWriteData(0);
00327 }    
00328 
00329 unsigned long usbdc::endpointRead(unsigned char endpoint, unsigned char *buffer)
00330 {
00331     /* Read from an OUT endpoint */
00332     unsigned long size;
00333     unsigned long i;
00334     unsigned long data;
00335     unsigned char offset;
00336     
00337     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | RD_EN;
00338     while (!(LPC_USB->USBRxPLen & PKT_RDY));
00339         
00340     size = LPC_USB->USBRxPLen & PKT_LNGTH_MASK;
00341         
00342     offset = 0;
00343     
00344     for (i=0; i<size; i++)
00345     {    
00346         if (offset==0)
00347         {    
00348             /* Fetch up to four bytes of data as a word */
00349             data = LPC_USB->USBRxData;
00350         }
00351     
00352         /* extract a byte */
00353         *buffer++ = data>>offset;
00354     
00355         /* move on to the next byte */
00356         offset = (offset + 8) % 32;
00357     }    
00358     
00359     /* Clear RD_EN to cover zero length packet case */
00360     LPC_USB->USBCtrl=0;
00361     
00362     selectEndpoint(endpoint);
00363     clearBuffer();
00364     
00365     return size;
00366 }
00367 
00368 void usbdc::endpointWrite(unsigned char endpoint, unsigned char *buffer, unsigned long size)
00369 {
00370     /* Write to an IN endpoint */
00371     unsigned long temp, data;
00372     unsigned char offset;
00373     
00374     LPC_USB->USBCtrl = LOG_ENDPOINT(endpoint) | WR_EN;
00375     
00376     LPC_USB->USBTxPLen = size;    
00377     offset = 0;
00378     data = 0;
00379     
00380     if (size>0)
00381     {
00382         do {
00383             /* Fetch next data byte into a word-sized temporary variable */
00384             temp = *buffer++;
00385         
00386             /* Add to current data word */
00387             temp = temp << offset;
00388             data = data | temp;
00389         
00390             /* move on to the next byte */
00391             offset = (offset + 8) % 32;
00392             size--;
00393         
00394             if ((offset==0) || (size==0))
00395             {
00396                 /* Write the word to the endpoint */
00397                 LPC_USB->USBTxData = data;
00398                 data = 0;
00399             }    
00400         } while (size>0);
00401     }
00402 
00403     /* Clear WR_EN to cover zero length packet case */
00404     LPC_USB->USBCtrl=0;
00405     
00406     selectEndpoint(endpoint);
00407     validateBuffer();
00408 }
00409 
00410 void usbdc::enableEvents(void)
00411 {
00412     /* Enable interrupt sources */
00413     LPC_USB->USBDevIntEn = EP_SLOW | DEV_STAT;
00414 }
00415 
00416 void usbdc::disableEvents(void)
00417 {
00418     /* Disable interrupt sources */
00419     LPC_USB->USBDevIntClr = EP_SLOW | DEV_STAT;
00420 }
00421 
00422 void usbdc::usbisr(void)
00423 { 
00424     unsigned char devStat;
00425     
00426     if (LPC_USB->USBDevIntSt & FRAME)
00427     {
00428         /* Frame event */
00429         deviceEventFrame();
00430         /* Clear interrupt status flag */
00431         LPC_USB->USBDevIntClr = FRAME;
00432     }
00433     
00434     if (LPC_USB->USBDevIntSt & DEV_STAT)
00435     {
00436         /* Device Status interrupt */        
00437         /* Must clear the interrupt status flag before reading the device status from the SIE */
00438         LPC_USB->USBDevIntClr = DEV_STAT;    
00439             
00440         /* Read device status from SIE */
00441         devStat = getDeviceStatus();
00442         
00443         if (devStat & SIE_DS_RST)
00444         {
00445             /* Bus reset */
00446             deviceEventReset();
00447         }
00448     }
00449     
00450     if (LPC_USB->USBDevIntSt & EP_SLOW)
00451     {
00452         /* (Slow) Endpoint Interrupt */
00453         
00454         /* Process each endpoint interrupt */
00455         if (LPC_USB->USBEpIntSt & EP(EP0OUT))
00456         {
00457             if (selectEndpointClearInterrupt(EP0OUT) & SIE_SE_STP)
00458             {
00459                 /* this is a setup packet */
00460                 endpointEventEP0Setup();
00461             }
00462             else
00463             {
00464                 endpointEventEP0Out();
00465             }
00466         }
00467 
00468         if (LPC_USB->USBEpIntSt & EP(EP0IN))
00469         {
00470             selectEndpointClearInterrupt(EP0IN);
00471             endpointEventEP0In();
00472         }
00473         
00474         if (LPC_USB->USBEpIntSt & EP(EP1OUT))
00475         {
00476             selectEndpointClearInterrupt(EP1OUT);
00477             endpointEventEP1Out();
00478         }    
00479         
00480         if (LPC_USB->USBEpIntSt & EP(EP1IN))
00481         {
00482             selectEndpointClearInterrupt(EP1IN);
00483             endpointEventEP1In();
00484         }    
00485         
00486         if (LPC_USB->USBEpIntSt & EP(EP2OUT))
00487         {
00488             selectEndpointClearInterrupt(EP2OUT);
00489             endpointEventEP2Out();
00490         }    
00491         
00492         if (LPC_USB->USBEpIntSt & EP(EP2IN))
00493         {
00494             selectEndpointClearInterrupt(EP2IN);
00495             endpointEventEP2In();
00496         }    
00497         
00498         /* Clear interrupt status flag */
00499         /* EP_SLOW and EP_FAST interrupt bits should be cleared after the corresponding endpoint interrupts are cleared. */
00500         LPC_USB->USBDevIntClr = EP_SLOW;
00501     }
00502 }
00503 
00504 
00505 void usbdc::_usbisr(void)
00506 {
00507     instance->usbisr();
00508 }
00509 
00510 void usbdc::deviceEventReset(void)
00511 {
00512 }
00513 
00514 void usbdc::deviceEventFrame(void)
00515 {
00516 }
00517 
00518 void usbdc::endpointEventEP0Setup(void)
00519 {
00520 }
00521 
00522 void usbdc::endpointEventEP0In(void)
00523 {
00524 }
00525 
00526 void usbdc::endpointEventEP0Out(void)
00527 {
00528 }
00529 
00530 void usbdc::endpointEventEP1In(void)
00531 {
00532 }
00533 
00534 void usbdc::endpointEventEP1Out(void)
00535 {
00536 }
00537 
00538 void usbdc::endpointEventEP2In(void)
00539 {
00540 }
00541 
00542 void usbdc::endpointEventEP2Out(void)
00543 {
00544 }