A library to send and receive MIDI messages over USB using the default USB-MIDI drivers on Win/Mac
Dependents: USBMIDI_HelloWorld USBMIDI_DrumExample USBMIDI_MonoSynth MIDI_Interface_ver_1 ... more
usbcore.c
00001 /* @license The MIT License 00002 * Copyright (c) 2011 mux, simon 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00023 #include "usbcore.h" 00024 00025 #include "mbed.h" 00026 00027 // Serial Interface Engine 00028 #define SIE_SET_ADDR (0xD0) 00029 #define SIE_SET_STATUS (0xFE) 00030 #define SIE_GET_STATUS (0xFE) 00031 #define SIE_SET_MODE (0xF3) 00032 #define SIE_CLR_BUFFER (0xF2) 00033 #define SIE_VAL_BUFFER (0xFA) 00034 #define SIE_SEL_EP (0x00) 00035 #define SIE_SEL_CLR_EP (0x28) 00036 #define SIE_SET_EP_STAT (0x40) 00037 #define SIE_READ_ERROR (0xFB) 00038 #define SIE_CONFIG_DEVICE (0xD8) 00039 00040 // EP status 00041 #define EP_FE (1<<0) // Full/Empty 00042 #define EP_ST (1<<1) // Stalled endpoint 00043 #define EP_STP (1<<2) // Setup packet 00044 #define EP_PO (1<<3) // packet overwritten 00045 #define EP_EPN (1<<4) // EP NAKed 00046 #define B_1_FULL (1<<5) // buffer 1 status 00047 #define B_2_FULL (1<<6) // buffer 2 status 00048 00049 // USB device interrupts 00050 #define DEV_FRAME (1<<0) 00051 #define EP_FAST (1<<1) 00052 #define EP_SLOW (1<<2) 00053 #define DEV_STAT (1<<3) 00054 #define RxENDPKT (1<<6) 00055 #define TxENDPKT (1<<7) 00056 #define EP_RLZED (1<<8) 00057 #define CCEMPTY (0x10) 00058 #define CDFULL (0x20) 00059 00060 // USB device status bits 00061 #define STAT_CON (1<<0) 00062 #define STAT_CON_CH (1<<1) 00063 #define STAT_SUS (1<<2) 00064 #define STAT_SUS_CH (1<<3) 00065 #define STAT_RST (1<<4) 00066 00067 // end points interrupts 00068 #define EP0RX_INT (1<<0) 00069 #define EP0TX_INT (1<<1) 00070 #define EP1RX_INT (1<<2) 00071 #define EP1TX_INT (1<<3) 00072 #define EP2RX_INT (1<<4) 00073 #define EP2TX_INT (1<<5) 00074 00075 // USB control register 00076 #define RD_EN (1<<0) 00077 #define WR_EN (1<<1) 00078 #define PKT_RDY (1<<11) 00079 #define LOG_ENDPOINT(ep) ((ep>>1)<<2) 00080 00081 // configure state 00082 static int configured = 0; 00083 00084 // USB interrupt handler 00085 void USB_IRQHandler(void); 00086 00087 // Serial Interface Engine functions 00088 void sie_command(uint32_t code) { 00089 LPC_USB->USBDevIntClr = CCEMPTY; // clear CCEMPTY 00090 LPC_USB->USBCmdCode = ((code<<16)|(0x05<<8)); // CMD_PHASE=Command 00091 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); // wait for CCEMPTY 00092 } 00093 00094 void sie_write(uint32_t data) { 00095 LPC_USB->USBDevIntClr = CCEMPTY; // clear CCEMPTY 00096 LPC_USB->USBCmdCode = ((data<<16)|(0x01<<8)); // CMD_PHASE=Write 00097 while (!(LPC_USB->USBDevIntSt & CCEMPTY)); // wait for CCEMPTY 00098 } 00099 00100 uint8_t sie_read(uint32_t code) { 00101 LPC_USB->USBDevIntClr = CDFULL; // clear CCEMPTY 00102 LPC_USB->USBCmdCode = ((code<<16)|(0x02<<8)); // CMD_PHASE=Read 00103 while (!(LPC_USB->USBDevIntSt & CDFULL)); // wait for CDFULL 00104 return (uint8_t) LPC_USB->USBCmdData; 00105 00106 } 00107 00108 // end point functions 00109 void ep_realize(uint8_t ep, uint32_t size) { 00110 LPC_USB->USBDevIntClr = EP_RLZED; // clear EP_RLZED 00111 LPC_USB->USBReEp |= (1<<ep); 00112 LPC_USB->USBEpInd = ep; // set USBEpIn 00113 LPC_USB->USBMaxPSize = size; // writing to EPn pointed to by USBEpInd 00114 while (!(LPC_USB->USBDevIntSt & EP_RLZED)); // wait for EP_RLZED 00115 LPC_USB->USBDevIntClr = EP_RLZED; // clear EP_RLZED 00116 } 00117 00118 void ep_stall(uint8_t ep) { 00119 sie_command(SIE_SET_EP_STAT+ep); 00120 sie_write(1); 00121 } 00122 00123 void ep_unstall(uint8_t ep) { 00124 sie_command(SIE_SET_EP_STAT+ep); 00125 sie_write(0); 00126 } 00127 00128 // initializes a pointer to the endpoint buffer 00129 uint8_t ep_select(uint8_t ep) { 00130 sie_command(SIE_SEL_EP+ep); 00131 return sie_read(SIE_SEL_EP+ep); 00132 } 00133 00134 uint8_t ep_select_clear(uint8_t ep) { 00135 LPC_USB->USBEpIntClr |= ep; // clear ep interrupt 00136 while (!(LPC_USB->USBDevIntSt & CDFULL)); // wait for cmd finish 00137 return LPC_USB->USBCmdData; 00138 } 00139 00140 int ep_readable(uint8_t ep) { 00141 uint8_t st = ep_select(ep); 00142 return (st & EP_FE); 00143 } 00144 00145 int ep_writable(uint8_t ep) { 00146 uint8_t st = ep_select(ep); 00147 return !(st & EP_FE); 00148 } 00149 00150 int ep_read(uint8_t ep, uint8_t *tbuf) { 00151 uint32_t *buf = (uint32_t*) tbuf; 00152 LPC_USB->USBCtrl = LOG_ENDPOINT(ep)|RD_EN; // RD_EN bit and LOG_ENDPOINT 00153 while (!(LPC_USB->USBRxPLen & PKT_RDY)); // wait for packet to be fetched 00154 int len = LPC_USB->USBRxPLen & 0x3FF; // read and mask packet length 00155 while (!(LPC_USB->USBDevIntSt & RxENDPKT)) { 00156 *buf++ = LPC_USB->USBRxData; 00157 } 00158 LPC_USB->USBCtrl = 0; 00159 LPC_USB->USBDevIntClr |= RxENDPKT; 00160 sie_command(SIE_SEL_EP+ep); // select endpoint 00161 sie_command(SIE_CLR_BUFFER); // clear RX buffer 00162 return len; 00163 } 00164 00165 void ep_write(uint8_t ep, uint8_t *tbuf, uint32_t len) { 00166 uint32_t *buf = (uint32_t*) tbuf; 00167 LPC_USB->USBCtrl = LOG_ENDPOINT(ep)|WR_EN; // RD_EN bit and LOG_ENDPOINT 00168 LPC_USB->USBTxPLen |= (len & 0x3FF); // write and mask packet length 00169 while (!(LPC_USB->USBDevIntSt & TxENDPKT)) { 00170 LPC_USB->USBTxData = *buf++; 00171 } 00172 LPC_USB->USBCtrl = 0; 00173 LPC_USB->USBDevIntClr |= TxENDPKT; 00174 sie_command(SIE_SEL_EP+ep); // select endpoint 00175 sie_command(SIE_VAL_BUFFER); // validate TX buffer 00176 } 00177 00178 // USB device controller initialization 00179 void usb_init() { 00180 // USB D+/D- pinsel functions 00181 LPC_PINCON->PINSEL1 &= 0xC3FFFFFF; 00182 LPC_PINCON->PINSEL1 |= 0x14000000; 00183 00184 #if USB_UP_DEBUG 00185 // USB_UP_LED pinsel function 00186 LPC_PINCON->PINSEL3 &= 0xFFFFFFCF; 00187 LPC_PINCON->PINSEL3 |= 0x00000010; 00188 #endif 00189 00190 // USB connect pinsel function 00191 LPC_PINCON->PINSEL4 &= 0xFFFCFFFF; 00192 LPC_PINCON->PINSEL4 |= 0x00040000; 00193 LPC_SC->PCONP |= (1UL<<31); // enable the USB controller 00194 LPC_USB->USBClkCtrl |= ((1<<1)|(1<<4)); // enable the AHB and DEV clocks 00195 while ((LPC_USB->USBClkSt & 0x12) != 0x12); // wait for the clocks to init 00196 00197 NVIC_SetVector(USB_IRQn, (uint32_t)&USB_IRQHandler); 00198 NVIC_EnableIRQ(USB_IRQn); // enable USB interrupts 00199 00200 usb_reset(); 00201 usb_set_address(0); // default address 00202 } 00203 00204 void usb_reset() { 00205 ep_realize(EP0, MAX_EP0_PSIZE); 00206 ep_realize(EP1, MAX_EP0_PSIZE); 00207 LPC_USB->USBEpIntClr = 0xFFFFFFFF; // clear end points interrupts 00208 LPC_USB->USBEpIntEn = 0xFFFFFFFF; // enable end points interrupts 00209 LPC_USB->USBEpIntPri = 0x0; // route to EP_SLOW 00210 LPC_USB->USBDevIntClr = 0xFFFFFFFF; // clear USB device interrupts 00211 LPC_USB->USBDevIntEn = (EP_SLOW|DEV_STAT); // enable USB device interrupts 00212 } 00213 00214 void usb_configure(uint8_t conf) { 00215 sie_command(SIE_CONFIG_DEVICE); 00216 sie_write(conf); 00217 configured = 1; 00218 } 00219 00220 int usb_configured() { 00221 return configured; 00222 } 00223 00224 void usb_set_address(uint8_t addr) { 00225 sie_command(SIE_SET_ADDR); 00226 sie_write(addr|0x80); // DEV_EN = 1 00227 } 00228 00229 uint8_t usb_get_status() { 00230 sie_command(SIE_GET_STATUS); 00231 return sie_read(SIE_GET_STATUS); 00232 } 00233 00234 void usb_connect() { 00235 sie_command(SIE_GET_STATUS); // read current status 00236 uint8_t st = sie_read(SIE_GET_STATUS); 00237 00238 sie_command(SIE_SET_STATUS); // set STAT_CON bit 00239 sie_write(st|STAT_CON); 00240 } 00241 00242 void USB_IRQHandler(void) { 00243 if (LPC_USB->USBDevIntSt & DEV_STAT) { // DEV_STAT interrupt 00244 LPC_USB->USBDevIntClr |= DEV_STAT; 00245 if (usb_get_status() & STAT_RST) { // bus reset 00246 usb_reset(); 00247 } 00248 return; 00249 } 00250 00251 if (LPC_USB->USBDevIntSt & EP_SLOW) { // EP_SLOW interrupt 00252 if (LPC_USB->USBEpIntSt & EP0RX_INT) { 00253 if (ep_select_clear(EP0RX_INT) & EP_STP) { // setup transfer 00254 ep0_setup(); 00255 } else { 00256 ep0_out(); 00257 } 00258 } 00259 00260 if (LPC_USB->USBEpIntSt & EP0TX_INT) { 00261 ep_select_clear(EP0TX_INT); 00262 ep0_in(); 00263 } 00264 00265 if (LPC_USB->USBEpIntSt & EP2RX_INT) { 00266 ep_select_clear(EP2TX_INT); 00267 ep2_out(); 00268 } 00269 00270 if (LPC_USB->USBEpIntSt & EP2TX_INT) { 00271 ep_select_clear(EP2TX_INT); 00272 ep2_in(); 00273 } 00274 00275 // EP_SLOW should be cleared after clearing EPs interrupts 00276 LPC_USB->USBDevIntClr |= EP_SLOW; 00277 } 00278 }
Generated on Tue Jul 12 2022 16:19:58 by 1.7.2