MIDI Stop Controller V1.0 suitable for driving Hauptwerk digital organ software. Written for the KL25Z uses BusInOut and will drive up to 16 illuminated push buttons each switch uses a single I/O pin to both drive the LED and act as a switch input. Pressing a button will alternately send MIDI note on / off messages and turn the LED on or off. If corresponding MIDI note on/off messages are received these will be used to drive the LEDs in preference to the locally generated LED signals. The MIDI channel used to send can be selected by jumpers on 4 pins of the J2 header.

Dependencies:   mbed

Committer:
djbottrill
Date:
Sat Sep 14 21:32:06 2013 +0000
Revision:
0:aac55e1fc12f
V1.0 MIDI Stop Controller

Who changed what in which revision?

UserRevisionLine numberNew contents of line
djbottrill 0:aac55e1fc12f 1 /* Copyright (c) 2010-2011 mbed.org, MIT License
djbottrill 0:aac55e1fc12f 2 *
djbottrill 0:aac55e1fc12f 3 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
djbottrill 0:aac55e1fc12f 4 * and associated documentation files (the "Software"), to deal in the Software without
djbottrill 0:aac55e1fc12f 5 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
djbottrill 0:aac55e1fc12f 6 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
djbottrill 0:aac55e1fc12f 7 * Software is furnished to do so, subject to the following conditions:
djbottrill 0:aac55e1fc12f 8 *
djbottrill 0:aac55e1fc12f 9 * The above copyright notice and this permission notice shall be included in all copies or
djbottrill 0:aac55e1fc12f 10 * substantial portions of the Software.
djbottrill 0:aac55e1fc12f 11 *
djbottrill 0:aac55e1fc12f 12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
djbottrill 0:aac55e1fc12f 13 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
djbottrill 0:aac55e1fc12f 14 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
djbottrill 0:aac55e1fc12f 15 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
djbottrill 0:aac55e1fc12f 16 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
djbottrill 0:aac55e1fc12f 17 */
djbottrill 0:aac55e1fc12f 18
djbottrill 0:aac55e1fc12f 19 #if defined(TARGET_KL25Z)
djbottrill 0:aac55e1fc12f 20
djbottrill 0:aac55e1fc12f 21 #include "USBHAL.h"
djbottrill 0:aac55e1fc12f 22
djbottrill 0:aac55e1fc12f 23 USBHAL * USBHAL::instance;
djbottrill 0:aac55e1fc12f 24
djbottrill 0:aac55e1fc12f 25 static volatile int epComplete = 0;
djbottrill 0:aac55e1fc12f 26
djbottrill 0:aac55e1fc12f 27 // Convert physical endpoint number to register bit
djbottrill 0:aac55e1fc12f 28 #define EP(endpoint) (1<<(endpoint))
djbottrill 0:aac55e1fc12f 29
djbottrill 0:aac55e1fc12f 30 // Convert physical to logical
djbottrill 0:aac55e1fc12f 31 #define PHY_TO_LOG(endpoint) ((endpoint)>>1)
djbottrill 0:aac55e1fc12f 32
djbottrill 0:aac55e1fc12f 33 // Get endpoint direction
djbottrill 0:aac55e1fc12f 34 #define IN_EP(endpoint) ((endpoint) & 1U ? true : false)
djbottrill 0:aac55e1fc12f 35 #define OUT_EP(endpoint) ((endpoint) & 1U ? false : true)
djbottrill 0:aac55e1fc12f 36
djbottrill 0:aac55e1fc12f 37 #define BD_OWN_MASK (1<<7)
djbottrill 0:aac55e1fc12f 38 #define BD_DATA01_MASK (1<<6)
djbottrill 0:aac55e1fc12f 39 #define BD_KEEP_MASK (1<<5)
djbottrill 0:aac55e1fc12f 40 #define BD_NINC_MASK (1<<4)
djbottrill 0:aac55e1fc12f 41 #define BD_DTS_MASK (1<<3)
djbottrill 0:aac55e1fc12f 42 #define BD_STALL_MASK (1<<2)
djbottrill 0:aac55e1fc12f 43
djbottrill 0:aac55e1fc12f 44 #define TX 1
djbottrill 0:aac55e1fc12f 45 #define RX 0
djbottrill 0:aac55e1fc12f 46 #define ODD 0
djbottrill 0:aac55e1fc12f 47 #define EVEN 1
djbottrill 0:aac55e1fc12f 48 // this macro waits a physical endpoint number
djbottrill 0:aac55e1fc12f 49 #define EP_BDT_IDX(ep, dir, odd) (((ep * 4) + (2 * dir) + (1 * odd)))
djbottrill 0:aac55e1fc12f 50
djbottrill 0:aac55e1fc12f 51 #define SETUP_TOKEN 0x0D
djbottrill 0:aac55e1fc12f 52 #define IN_TOKEN 0x09
djbottrill 0:aac55e1fc12f 53 #define OUT_TOKEN 0x01
djbottrill 0:aac55e1fc12f 54 #define TOK_PID(idx) ((bdt[idx].info >> 2) & 0x0F)
djbottrill 0:aac55e1fc12f 55
djbottrill 0:aac55e1fc12f 56 // for each endpt: 8 bytes
djbottrill 0:aac55e1fc12f 57 typedef struct BDT {
djbottrill 0:aac55e1fc12f 58 uint8_t info; // BD[0:7]
djbottrill 0:aac55e1fc12f 59 uint8_t dummy; // RSVD: BD[8:15]
djbottrill 0:aac55e1fc12f 60 uint16_t byte_count; // BD[16:32]
djbottrill 0:aac55e1fc12f 61 uint32_t address; // Addr
djbottrill 0:aac55e1fc12f 62 } BDT;
djbottrill 0:aac55e1fc12f 63
djbottrill 0:aac55e1fc12f 64
djbottrill 0:aac55e1fc12f 65 // there are:
djbottrill 0:aac55e1fc12f 66 // * 16 bidirectionnal endpt -> 32 physical endpt
djbottrill 0:aac55e1fc12f 67 // * as there are ODD and EVEN buffer -> 32*2 bdt
djbottrill 0:aac55e1fc12f 68 __attribute__((__aligned__(512))) BDT bdt[NUMBER_OF_PHYSICAL_ENDPOINTS * 2];
djbottrill 0:aac55e1fc12f 69 uint8_t * endpoint_buffer[(NUMBER_OF_PHYSICAL_ENDPOINTS - 2) * 2];
djbottrill 0:aac55e1fc12f 70 uint8_t * endpoint_buffer_iso[2*2];
djbottrill 0:aac55e1fc12f 71
djbottrill 0:aac55e1fc12f 72 static uint8_t set_addr = 0;
djbottrill 0:aac55e1fc12f 73 static uint8_t addr = 0;
djbottrill 0:aac55e1fc12f 74
djbottrill 0:aac55e1fc12f 75 static uint32_t Data1 = 0x55555555;
djbottrill 0:aac55e1fc12f 76
djbottrill 0:aac55e1fc12f 77 static uint32_t frameNumber() {
djbottrill 0:aac55e1fc12f 78 return((USB0->FRMNUML | (USB0->FRMNUMH << 8) & 0x07FF));
djbottrill 0:aac55e1fc12f 79 }
djbottrill 0:aac55e1fc12f 80
djbottrill 0:aac55e1fc12f 81 uint32_t USBHAL::endpointReadcore(uint8_t endpoint, uint8_t *buffer) {
djbottrill 0:aac55e1fc12f 82 return 0;
djbottrill 0:aac55e1fc12f 83 }
djbottrill 0:aac55e1fc12f 84
djbottrill 0:aac55e1fc12f 85 USBHAL::USBHAL(void) {
djbottrill 0:aac55e1fc12f 86 // Disable IRQ
djbottrill 0:aac55e1fc12f 87 NVIC_DisableIRQ(USB0_IRQn);
djbottrill 0:aac55e1fc12f 88
djbottrill 0:aac55e1fc12f 89 // fill in callback array
djbottrill 0:aac55e1fc12f 90 epCallback[0] = &USBHAL::EP1_OUT_callback;
djbottrill 0:aac55e1fc12f 91 epCallback[1] = &USBHAL::EP1_IN_callback;
djbottrill 0:aac55e1fc12f 92 epCallback[2] = &USBHAL::EP2_OUT_callback;
djbottrill 0:aac55e1fc12f 93 epCallback[3] = &USBHAL::EP2_IN_callback;
djbottrill 0:aac55e1fc12f 94 epCallback[4] = &USBHAL::EP3_OUT_callback;
djbottrill 0:aac55e1fc12f 95 epCallback[5] = &USBHAL::EP3_IN_callback;
djbottrill 0:aac55e1fc12f 96 epCallback[6] = &USBHAL::EP4_OUT_callback;
djbottrill 0:aac55e1fc12f 97 epCallback[7] = &USBHAL::EP4_IN_callback;
djbottrill 0:aac55e1fc12f 98 epCallback[8] = &USBHAL::EP5_OUT_callback;
djbottrill 0:aac55e1fc12f 99 epCallback[9] = &USBHAL::EP5_IN_callback;
djbottrill 0:aac55e1fc12f 100 epCallback[10] = &USBHAL::EP6_OUT_callback;
djbottrill 0:aac55e1fc12f 101 epCallback[11] = &USBHAL::EP6_IN_callback;
djbottrill 0:aac55e1fc12f 102 epCallback[12] = &USBHAL::EP7_OUT_callback;
djbottrill 0:aac55e1fc12f 103 epCallback[13] = &USBHAL::EP7_IN_callback;
djbottrill 0:aac55e1fc12f 104 epCallback[14] = &USBHAL::EP8_OUT_callback;
djbottrill 0:aac55e1fc12f 105 epCallback[15] = &USBHAL::EP8_IN_callback;
djbottrill 0:aac55e1fc12f 106 epCallback[16] = &USBHAL::EP9_OUT_callback;
djbottrill 0:aac55e1fc12f 107 epCallback[17] = &USBHAL::EP9_IN_callback;
djbottrill 0:aac55e1fc12f 108 epCallback[18] = &USBHAL::EP10_OUT_callback;
djbottrill 0:aac55e1fc12f 109 epCallback[19] = &USBHAL::EP10_IN_callback;
djbottrill 0:aac55e1fc12f 110 epCallback[20] = &USBHAL::EP11_OUT_callback;
djbottrill 0:aac55e1fc12f 111 epCallback[21] = &USBHAL::EP11_IN_callback;
djbottrill 0:aac55e1fc12f 112 epCallback[22] = &USBHAL::EP12_OUT_callback;
djbottrill 0:aac55e1fc12f 113 epCallback[23] = &USBHAL::EP12_IN_callback;
djbottrill 0:aac55e1fc12f 114 epCallback[24] = &USBHAL::EP13_OUT_callback;
djbottrill 0:aac55e1fc12f 115 epCallback[25] = &USBHAL::EP13_IN_callback;
djbottrill 0:aac55e1fc12f 116 epCallback[26] = &USBHAL::EP14_OUT_callback;
djbottrill 0:aac55e1fc12f 117 epCallback[27] = &USBHAL::EP14_IN_callback;
djbottrill 0:aac55e1fc12f 118 epCallback[28] = &USBHAL::EP15_OUT_callback;
djbottrill 0:aac55e1fc12f 119 epCallback[29] = &USBHAL::EP15_IN_callback;
djbottrill 0:aac55e1fc12f 120
djbottrill 0:aac55e1fc12f 121
djbottrill 0:aac55e1fc12f 122 // choose usb src as PLL
djbottrill 0:aac55e1fc12f 123 SIM->SOPT2 |= (SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL_MASK);
djbottrill 0:aac55e1fc12f 124
djbottrill 0:aac55e1fc12f 125 // enable OTG clock
djbottrill 0:aac55e1fc12f 126 SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;
djbottrill 0:aac55e1fc12f 127
djbottrill 0:aac55e1fc12f 128 // Attach IRQ
djbottrill 0:aac55e1fc12f 129 instance = this;
djbottrill 0:aac55e1fc12f 130 NVIC_SetVector(USB0_IRQn, (uint32_t)&_usbisr);
djbottrill 0:aac55e1fc12f 131 NVIC_EnableIRQ(USB0_IRQn);
djbottrill 0:aac55e1fc12f 132
djbottrill 0:aac55e1fc12f 133 // USB Module Configuration
djbottrill 0:aac55e1fc12f 134 // Reset USB Module
djbottrill 0:aac55e1fc12f 135 USB0->USBTRC0 |= USB_USBTRC0_USBRESET_MASK;
djbottrill 0:aac55e1fc12f 136 while(USB0->USBTRC0 & USB_USBTRC0_USBRESET_MASK);
djbottrill 0:aac55e1fc12f 137
djbottrill 0:aac55e1fc12f 138 // Set BDT Base Register
djbottrill 0:aac55e1fc12f 139 USB0->BDTPAGE1=(uint8_t)((uint32_t)bdt>>8);
djbottrill 0:aac55e1fc12f 140 USB0->BDTPAGE2=(uint8_t)((uint32_t)bdt>>16);
djbottrill 0:aac55e1fc12f 141 USB0->BDTPAGE3=(uint8_t)((uint32_t)bdt>>24);
djbottrill 0:aac55e1fc12f 142
djbottrill 0:aac55e1fc12f 143 // Clear interrupt flag
djbottrill 0:aac55e1fc12f 144 USB0->ISTAT = 0xff;
djbottrill 0:aac55e1fc12f 145
djbottrill 0:aac55e1fc12f 146 // USB Interrupt Enablers
djbottrill 0:aac55e1fc12f 147 USB0->INTEN |= USB_INTEN_TOKDNEEN_MASK |
djbottrill 0:aac55e1fc12f 148 USB_INTEN_SOFTOKEN_MASK |
djbottrill 0:aac55e1fc12f 149 USB_INTEN_ERROREN_MASK |
djbottrill 0:aac55e1fc12f 150 USB_INTEN_USBRSTEN_MASK;
djbottrill 0:aac55e1fc12f 151
djbottrill 0:aac55e1fc12f 152 // Disable weak pull downs
djbottrill 0:aac55e1fc12f 153 USB0->USBCTRL &= ~(USB_USBCTRL_PDE_MASK | USB_USBCTRL_SUSP_MASK);
djbottrill 0:aac55e1fc12f 154
djbottrill 0:aac55e1fc12f 155 USB0->USBTRC0 |= 0x40;
djbottrill 0:aac55e1fc12f 156 }
djbottrill 0:aac55e1fc12f 157
djbottrill 0:aac55e1fc12f 158 USBHAL::~USBHAL(void) { }
djbottrill 0:aac55e1fc12f 159
djbottrill 0:aac55e1fc12f 160 void USBHAL::connect(void) {
djbottrill 0:aac55e1fc12f 161 // enable USB
djbottrill 0:aac55e1fc12f 162 USB0->CTL |= USB_CTL_USBENSOFEN_MASK;
djbottrill 0:aac55e1fc12f 163 // Pull up enable
djbottrill 0:aac55e1fc12f 164 USB0->CONTROL |= USB_CONTROL_DPPULLUPNONOTG_MASK;
djbottrill 0:aac55e1fc12f 165 }
djbottrill 0:aac55e1fc12f 166
djbottrill 0:aac55e1fc12f 167 void USBHAL::disconnect(void) {
djbottrill 0:aac55e1fc12f 168 // disable USB
djbottrill 0:aac55e1fc12f 169 USB0->CTL &= ~USB_CTL_USBENSOFEN_MASK;
djbottrill 0:aac55e1fc12f 170 // Pull up disable
djbottrill 0:aac55e1fc12f 171 USB0->CONTROL &= ~USB_CONTROL_DPPULLUPNONOTG_MASK;
djbottrill 0:aac55e1fc12f 172 }
djbottrill 0:aac55e1fc12f 173
djbottrill 0:aac55e1fc12f 174 void USBHAL::configureDevice(void) {
djbottrill 0:aac55e1fc12f 175 // not needed
djbottrill 0:aac55e1fc12f 176 }
djbottrill 0:aac55e1fc12f 177
djbottrill 0:aac55e1fc12f 178 void USBHAL::unconfigureDevice(void) {
djbottrill 0:aac55e1fc12f 179 // not needed
djbottrill 0:aac55e1fc12f 180 }
djbottrill 0:aac55e1fc12f 181
djbottrill 0:aac55e1fc12f 182 void USBHAL::setAddress(uint8_t address) {
djbottrill 0:aac55e1fc12f 183 // we don't set the address now otherwise the usb controller does not ack
djbottrill 0:aac55e1fc12f 184 // we set a flag instead
djbottrill 0:aac55e1fc12f 185 // see usbisr when an IN token is received
djbottrill 0:aac55e1fc12f 186 set_addr = 1;
djbottrill 0:aac55e1fc12f 187 addr = address;
djbottrill 0:aac55e1fc12f 188 }
djbottrill 0:aac55e1fc12f 189
djbottrill 0:aac55e1fc12f 190 bool USBHAL::realiseEndpoint(uint8_t endpoint, uint32_t maxPacket, uint32_t flags) {
djbottrill 0:aac55e1fc12f 191 uint32_t handshake_flag = 0;
djbottrill 0:aac55e1fc12f 192 uint8_t * buf;
djbottrill 0:aac55e1fc12f 193
djbottrill 0:aac55e1fc12f 194 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
djbottrill 0:aac55e1fc12f 195 return false;
djbottrill 0:aac55e1fc12f 196 }
djbottrill 0:aac55e1fc12f 197
djbottrill 0:aac55e1fc12f 198 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
djbottrill 0:aac55e1fc12f 199
djbottrill 0:aac55e1fc12f 200 if ((flags & ISOCHRONOUS) == 0) {
djbottrill 0:aac55e1fc12f 201 handshake_flag = USB_ENDPT_EPHSHK_MASK;
djbottrill 0:aac55e1fc12f 202 if (IN_EP(endpoint)) {
djbottrill 0:aac55e1fc12f 203 endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )] = (uint8_t *) malloc (64*2);
djbottrill 0:aac55e1fc12f 204 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, TX, ODD )][0];
djbottrill 0:aac55e1fc12f 205 } else {
djbottrill 0:aac55e1fc12f 206 endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )] = (uint8_t *) malloc (64*2);
djbottrill 0:aac55e1fc12f 207 buf = &endpoint_buffer[EP_BDT_IDX(log_endpoint, RX, ODD )][0];
djbottrill 0:aac55e1fc12f 208 }
djbottrill 0:aac55e1fc12f 209 } else {
djbottrill 0:aac55e1fc12f 210 if (IN_EP(endpoint)) {
djbottrill 0:aac55e1fc12f 211 endpoint_buffer_iso[2] = (uint8_t *) malloc (1023*2);
djbottrill 0:aac55e1fc12f 212 buf = &endpoint_buffer_iso[2][0];
djbottrill 0:aac55e1fc12f 213 } else {
djbottrill 0:aac55e1fc12f 214 endpoint_buffer_iso[0] = (uint8_t *) malloc (1023*2);
djbottrill 0:aac55e1fc12f 215 buf = &endpoint_buffer_iso[0][0];
djbottrill 0:aac55e1fc12f 216 }
djbottrill 0:aac55e1fc12f 217 }
djbottrill 0:aac55e1fc12f 218
djbottrill 0:aac55e1fc12f 219 // IN endpt -> device to host (TX)
djbottrill 0:aac55e1fc12f 220 if (IN_EP(endpoint)) {
djbottrill 0:aac55e1fc12f 221 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
djbottrill 0:aac55e1fc12f 222 USB_ENDPT_EPTXEN_MASK; // en TX (IN) tran
djbottrill 0:aac55e1fc12f 223 bdt[EP_BDT_IDX(log_endpoint, TX, ODD )].address = (uint32_t) buf;
djbottrill 0:aac55e1fc12f 224 bdt[EP_BDT_IDX(log_endpoint, TX, EVEN)].address = 0;
djbottrill 0:aac55e1fc12f 225 }
djbottrill 0:aac55e1fc12f 226 // OUT endpt -> host to device (RX)
djbottrill 0:aac55e1fc12f 227 else {
djbottrill 0:aac55e1fc12f 228 USB0->ENDPOINT[log_endpoint].ENDPT |= handshake_flag | // ep handshaking (not if iso endpoint)
djbottrill 0:aac55e1fc12f 229 USB_ENDPT_EPRXEN_MASK; // en RX (OUT) tran.
djbottrill 0:aac55e1fc12f 230 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].byte_count = maxPacket;
djbottrill 0:aac55e1fc12f 231 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].address = (uint32_t) buf;
djbottrill 0:aac55e1fc12f 232 bdt[EP_BDT_IDX(log_endpoint, RX, ODD )].info = BD_OWN_MASK | BD_DTS_MASK;
djbottrill 0:aac55e1fc12f 233 bdt[EP_BDT_IDX(log_endpoint, RX, EVEN)].info = 0;
djbottrill 0:aac55e1fc12f 234 }
djbottrill 0:aac55e1fc12f 235
djbottrill 0:aac55e1fc12f 236 Data1 |= (1 << endpoint);
djbottrill 0:aac55e1fc12f 237
djbottrill 0:aac55e1fc12f 238 return true;
djbottrill 0:aac55e1fc12f 239 }
djbottrill 0:aac55e1fc12f 240
djbottrill 0:aac55e1fc12f 241 // read setup packet
djbottrill 0:aac55e1fc12f 242 void USBHAL::EP0setup(uint8_t *buffer) {
djbottrill 0:aac55e1fc12f 243 uint32_t sz;
djbottrill 0:aac55e1fc12f 244 endpointReadResult(EP0OUT, buffer, &sz);
djbottrill 0:aac55e1fc12f 245 }
djbottrill 0:aac55e1fc12f 246
djbottrill 0:aac55e1fc12f 247 void USBHAL::EP0readStage(void) {
djbottrill 0:aac55e1fc12f 248 Data1 &= ~1UL; // set DATA0
djbottrill 0:aac55e1fc12f 249 bdt[0].info = (BD_DTS_MASK | BD_OWN_MASK);
djbottrill 0:aac55e1fc12f 250 }
djbottrill 0:aac55e1fc12f 251
djbottrill 0:aac55e1fc12f 252 void USBHAL::EP0read(void) {
djbottrill 0:aac55e1fc12f 253 uint32_t idx = EP_BDT_IDX(PHY_TO_LOG(EP0OUT), RX, 0);
djbottrill 0:aac55e1fc12f 254 bdt[idx].byte_count = MAX_PACKET_SIZE_EP0;
djbottrill 0:aac55e1fc12f 255 }
djbottrill 0:aac55e1fc12f 256
djbottrill 0:aac55e1fc12f 257 uint32_t USBHAL::EP0getReadResult(uint8_t *buffer) {
djbottrill 0:aac55e1fc12f 258 uint32_t sz;
djbottrill 0:aac55e1fc12f 259 endpointReadResult(EP0OUT, buffer, &sz);
djbottrill 0:aac55e1fc12f 260 return sz;
djbottrill 0:aac55e1fc12f 261 }
djbottrill 0:aac55e1fc12f 262
djbottrill 0:aac55e1fc12f 263 void USBHAL::EP0write(uint8_t *buffer, uint32_t size) {
djbottrill 0:aac55e1fc12f 264 endpointWrite(EP0IN, buffer, size);
djbottrill 0:aac55e1fc12f 265 }
djbottrill 0:aac55e1fc12f 266
djbottrill 0:aac55e1fc12f 267 void USBHAL::EP0getWriteResult(void) {
djbottrill 0:aac55e1fc12f 268 }
djbottrill 0:aac55e1fc12f 269
djbottrill 0:aac55e1fc12f 270 void USBHAL::EP0stall(void) {
djbottrill 0:aac55e1fc12f 271 stallEndpoint(EP0OUT);
djbottrill 0:aac55e1fc12f 272 }
djbottrill 0:aac55e1fc12f 273
djbottrill 0:aac55e1fc12f 274 EP_STATUS USBHAL::endpointRead(uint8_t endpoint, uint32_t maximumSize) {
djbottrill 0:aac55e1fc12f 275 endpoint = PHY_TO_LOG(endpoint);
djbottrill 0:aac55e1fc12f 276 uint32_t idx = EP_BDT_IDX(endpoint, RX, 0);
djbottrill 0:aac55e1fc12f 277 bdt[idx].byte_count = maximumSize;
djbottrill 0:aac55e1fc12f 278 return EP_PENDING;
djbottrill 0:aac55e1fc12f 279 }
djbottrill 0:aac55e1fc12f 280
djbottrill 0:aac55e1fc12f 281 EP_STATUS USBHAL::endpointReadResult(uint8_t endpoint, uint8_t * buffer, uint32_t *bytesRead) {
djbottrill 0:aac55e1fc12f 282 uint32_t n, sz, idx, setup = 0;
djbottrill 0:aac55e1fc12f 283 uint8_t not_iso;
djbottrill 0:aac55e1fc12f 284 uint8_t * ep_buf;
djbottrill 0:aac55e1fc12f 285
djbottrill 0:aac55e1fc12f 286 uint32_t log_endpoint = PHY_TO_LOG(endpoint);
djbottrill 0:aac55e1fc12f 287
djbottrill 0:aac55e1fc12f 288 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
djbottrill 0:aac55e1fc12f 289 return EP_INVALID;
djbottrill 0:aac55e1fc12f 290 }
djbottrill 0:aac55e1fc12f 291
djbottrill 0:aac55e1fc12f 292 // if read on a IN endpoint -> error
djbottrill 0:aac55e1fc12f 293 if (IN_EP(endpoint)) {
djbottrill 0:aac55e1fc12f 294 return EP_INVALID;
djbottrill 0:aac55e1fc12f 295 }
djbottrill 0:aac55e1fc12f 296
djbottrill 0:aac55e1fc12f 297 idx = EP_BDT_IDX(log_endpoint, RX, 0);
djbottrill 0:aac55e1fc12f 298 sz = bdt[idx].byte_count;
djbottrill 0:aac55e1fc12f 299 not_iso = USB0->ENDPOINT[log_endpoint].ENDPT & USB_ENDPT_EPHSHK_MASK;
djbottrill 0:aac55e1fc12f 300
djbottrill 0:aac55e1fc12f 301 //for isochronous endpoint, we don't wait an interrupt
djbottrill 0:aac55e1fc12f 302 if ((log_endpoint != 0) && not_iso && !(epComplete & EP(endpoint))) {
djbottrill 0:aac55e1fc12f 303 return EP_PENDING;
djbottrill 0:aac55e1fc12f 304 }
djbottrill 0:aac55e1fc12f 305
djbottrill 0:aac55e1fc12f 306 if ((log_endpoint == 0) && (TOK_PID(idx) == SETUP_TOKEN)) {
djbottrill 0:aac55e1fc12f 307 setup = 1;
djbottrill 0:aac55e1fc12f 308 }
djbottrill 0:aac55e1fc12f 309
djbottrill 0:aac55e1fc12f 310 // non iso endpoint
djbottrill 0:aac55e1fc12f 311 if (not_iso) {
djbottrill 0:aac55e1fc12f 312 ep_buf = endpoint_buffer[idx];
djbottrill 0:aac55e1fc12f 313 } else {
djbottrill 0:aac55e1fc12f 314 ep_buf = endpoint_buffer_iso[0];
djbottrill 0:aac55e1fc12f 315 }
djbottrill 0:aac55e1fc12f 316
djbottrill 0:aac55e1fc12f 317 for (n = 0; n < sz; n++) {
djbottrill 0:aac55e1fc12f 318 buffer[n] = ep_buf[n];
djbottrill 0:aac55e1fc12f 319 }
djbottrill 0:aac55e1fc12f 320
djbottrill 0:aac55e1fc12f 321 if (((Data1 >> endpoint) & 1) == ((bdt[idx].info >> 6) & 1)) {
djbottrill 0:aac55e1fc12f 322 if (setup && (buffer[6] == 0)) // if no setup data stage,
djbottrill 0:aac55e1fc12f 323 Data1 &= ~1UL; // set DATA0
djbottrill 0:aac55e1fc12f 324 else
djbottrill 0:aac55e1fc12f 325 Data1 ^= (1 << endpoint);
djbottrill 0:aac55e1fc12f 326 }
djbottrill 0:aac55e1fc12f 327
djbottrill 0:aac55e1fc12f 328 if (((Data1 >> endpoint) & 1)) {
djbottrill 0:aac55e1fc12f 329 bdt[idx].info = BD_DTS_MASK | BD_DATA01_MASK | BD_OWN_MASK;
djbottrill 0:aac55e1fc12f 330 }
djbottrill 0:aac55e1fc12f 331 else {
djbottrill 0:aac55e1fc12f 332 bdt[idx].info = BD_DTS_MASK | BD_OWN_MASK;
djbottrill 0:aac55e1fc12f 333 }
djbottrill 0:aac55e1fc12f 334
djbottrill 0:aac55e1fc12f 335 USB0->CTL &= ~USB_CTL_TXSUSPENDTOKENBUSY_MASK;
djbottrill 0:aac55e1fc12f 336 *bytesRead = sz;
djbottrill 0:aac55e1fc12f 337
djbottrill 0:aac55e1fc12f 338 epComplete &= ~EP(endpoint);
djbottrill 0:aac55e1fc12f 339 return EP_COMPLETED;
djbottrill 0:aac55e1fc12f 340 }
djbottrill 0:aac55e1fc12f 341
djbottrill 0:aac55e1fc12f 342 EP_STATUS USBHAL::endpointWrite(uint8_t endpoint, uint8_t *data, uint32_t size) {
djbottrill 0:aac55e1fc12f 343 uint32_t idx, n;
djbottrill 0:aac55e1fc12f 344 uint8_t * ep_buf;
djbottrill 0:aac55e1fc12f 345
djbottrill 0:aac55e1fc12f 346 if (endpoint > NUMBER_OF_PHYSICAL_ENDPOINTS - 1) {
djbottrill 0:aac55e1fc12f 347 return EP_INVALID;
djbottrill 0:aac55e1fc12f 348 }
djbottrill 0:aac55e1fc12f 349
djbottrill 0:aac55e1fc12f 350 // if write on a OUT endpoint -> error
djbottrill 0:aac55e1fc12f 351 if (OUT_EP(endpoint)) {
djbottrill 0:aac55e1fc12f 352 return EP_INVALID;
djbottrill 0:aac55e1fc12f 353 }
djbottrill 0:aac55e1fc12f 354
djbottrill 0:aac55e1fc12f 355 idx = EP_BDT_IDX(PHY_TO_LOG(endpoint), TX, 0);
djbottrill 0:aac55e1fc12f 356 bdt[idx].byte_count = size;
djbottrill 0:aac55e1fc12f 357
djbottrill 0:aac55e1fc12f 358
djbottrill 0:aac55e1fc12f 359 // non iso endpoint
djbottrill 0:aac55e1fc12f 360 if (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPHSHK_MASK) {
djbottrill 0:aac55e1fc12f 361 ep_buf = endpoint_buffer[idx];
djbottrill 0:aac55e1fc12f 362 } else {
djbottrill 0:aac55e1fc12f 363 ep_buf = endpoint_buffer_iso[2];
djbottrill 0:aac55e1fc12f 364 }
djbottrill 0:aac55e1fc12f 365
djbottrill 0:aac55e1fc12f 366 for (n = 0; n < size; n++) {
djbottrill 0:aac55e1fc12f 367 ep_buf[n] = data[n];
djbottrill 0:aac55e1fc12f 368 }
djbottrill 0:aac55e1fc12f 369
djbottrill 0:aac55e1fc12f 370 if ((Data1 >> endpoint) & 1) {
djbottrill 0:aac55e1fc12f 371 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK;
djbottrill 0:aac55e1fc12f 372 } else {
djbottrill 0:aac55e1fc12f 373 bdt[idx].info = BD_OWN_MASK | BD_DTS_MASK | BD_DATA01_MASK;
djbottrill 0:aac55e1fc12f 374 }
djbottrill 0:aac55e1fc12f 375
djbottrill 0:aac55e1fc12f 376 Data1 ^= (1 << endpoint);
djbottrill 0:aac55e1fc12f 377
djbottrill 0:aac55e1fc12f 378 return EP_PENDING;
djbottrill 0:aac55e1fc12f 379 }
djbottrill 0:aac55e1fc12f 380
djbottrill 0:aac55e1fc12f 381 EP_STATUS USBHAL::endpointWriteResult(uint8_t endpoint) {
djbottrill 0:aac55e1fc12f 382 if (epComplete & EP(endpoint)) {
djbottrill 0:aac55e1fc12f 383 epComplete &= ~EP(endpoint);
djbottrill 0:aac55e1fc12f 384 return EP_COMPLETED;
djbottrill 0:aac55e1fc12f 385 }
djbottrill 0:aac55e1fc12f 386
djbottrill 0:aac55e1fc12f 387 return EP_PENDING;
djbottrill 0:aac55e1fc12f 388 }
djbottrill 0:aac55e1fc12f 389
djbottrill 0:aac55e1fc12f 390 void USBHAL::stallEndpoint(uint8_t endpoint) {
djbottrill 0:aac55e1fc12f 391 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT |= USB_ENDPT_EPSTALL_MASK;
djbottrill 0:aac55e1fc12f 392 }
djbottrill 0:aac55e1fc12f 393
djbottrill 0:aac55e1fc12f 394 void USBHAL::unstallEndpoint(uint8_t endpoint) {
djbottrill 0:aac55e1fc12f 395 USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
djbottrill 0:aac55e1fc12f 396 }
djbottrill 0:aac55e1fc12f 397
djbottrill 0:aac55e1fc12f 398 bool USBHAL::getEndpointStallState(uint8_t endpoint) {
djbottrill 0:aac55e1fc12f 399 uint8_t stall = (USB0->ENDPOINT[PHY_TO_LOG(endpoint)].ENDPT & USB_ENDPT_EPSTALL_MASK);
djbottrill 0:aac55e1fc12f 400 return (stall) ? true : false;
djbottrill 0:aac55e1fc12f 401 }
djbottrill 0:aac55e1fc12f 402
djbottrill 0:aac55e1fc12f 403 void USBHAL::remoteWakeup(void) {
djbottrill 0:aac55e1fc12f 404 // [TODO]
djbottrill 0:aac55e1fc12f 405 }
djbottrill 0:aac55e1fc12f 406
djbottrill 0:aac55e1fc12f 407
djbottrill 0:aac55e1fc12f 408 void USBHAL::_usbisr(void) {
djbottrill 0:aac55e1fc12f 409 instance->usbisr();
djbottrill 0:aac55e1fc12f 410 }
djbottrill 0:aac55e1fc12f 411
djbottrill 0:aac55e1fc12f 412
djbottrill 0:aac55e1fc12f 413 void USBHAL::usbisr(void) {
djbottrill 0:aac55e1fc12f 414 uint8_t i;
djbottrill 0:aac55e1fc12f 415 uint8_t istat = USB0->ISTAT;
djbottrill 0:aac55e1fc12f 416
djbottrill 0:aac55e1fc12f 417 // reset interrupt
djbottrill 0:aac55e1fc12f 418 if (istat & USB_ISTAT_USBRST_MASK) {
djbottrill 0:aac55e1fc12f 419 // disable all endpt
djbottrill 0:aac55e1fc12f 420 for(i = 0; i < 16; i++) {
djbottrill 0:aac55e1fc12f 421 USB0->ENDPOINT[i].ENDPT = 0x00;
djbottrill 0:aac55e1fc12f 422 }
djbottrill 0:aac55e1fc12f 423
djbottrill 0:aac55e1fc12f 424 // enable control endpoint
djbottrill 0:aac55e1fc12f 425 realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0, 0);
djbottrill 0:aac55e1fc12f 426 realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0, 0);
djbottrill 0:aac55e1fc12f 427
djbottrill 0:aac55e1fc12f 428 Data1 = 0x55555555;
djbottrill 0:aac55e1fc12f 429 USB0->CTL |= USB_CTL_ODDRST_MASK;
djbottrill 0:aac55e1fc12f 430
djbottrill 0:aac55e1fc12f 431 USB0->ISTAT = 0xFF; // clear all interrupt status flags
djbottrill 0:aac55e1fc12f 432 USB0->ERRSTAT = 0xFF; // clear all error flags
djbottrill 0:aac55e1fc12f 433 USB0->ERREN = 0xFF; // enable error interrupt sources
djbottrill 0:aac55e1fc12f 434 USB0->ADDR = 0x00; // set default address
djbottrill 0:aac55e1fc12f 435
djbottrill 0:aac55e1fc12f 436 return;
djbottrill 0:aac55e1fc12f 437 }
djbottrill 0:aac55e1fc12f 438
djbottrill 0:aac55e1fc12f 439 // resume interrupt
djbottrill 0:aac55e1fc12f 440 if (istat & USB_ISTAT_RESUME_MASK) {
djbottrill 0:aac55e1fc12f 441 USB0->ISTAT = USB_ISTAT_RESUME_MASK;
djbottrill 0:aac55e1fc12f 442 }
djbottrill 0:aac55e1fc12f 443
djbottrill 0:aac55e1fc12f 444 // SOF interrupt
djbottrill 0:aac55e1fc12f 445 if (istat & USB_ISTAT_SOFTOK_MASK) {
djbottrill 0:aac55e1fc12f 446 USB0->ISTAT = USB_ISTAT_SOFTOK_MASK;
djbottrill 0:aac55e1fc12f 447 // SOF event, read frame number
djbottrill 0:aac55e1fc12f 448 SOF(frameNumber());
djbottrill 0:aac55e1fc12f 449 }
djbottrill 0:aac55e1fc12f 450
djbottrill 0:aac55e1fc12f 451 // stall interrupt
djbottrill 0:aac55e1fc12f 452 if (istat & 1<<7) {
djbottrill 0:aac55e1fc12f 453 if (USB0->ENDPOINT[0].ENDPT & USB_ENDPT_EPSTALL_MASK)
djbottrill 0:aac55e1fc12f 454 USB0->ENDPOINT[0].ENDPT &= ~USB_ENDPT_EPSTALL_MASK;
djbottrill 0:aac55e1fc12f 455 USB0->ISTAT |= USB_ISTAT_STALL_MASK;
djbottrill 0:aac55e1fc12f 456 }
djbottrill 0:aac55e1fc12f 457
djbottrill 0:aac55e1fc12f 458 // token interrupt
djbottrill 0:aac55e1fc12f 459 if (istat & 1<<3) {
djbottrill 0:aac55e1fc12f 460 uint32_t num = (USB0->STAT >> 4) & 0x0F;
djbottrill 0:aac55e1fc12f 461 uint32_t dir = (USB0->STAT >> 3) & 0x01;
djbottrill 0:aac55e1fc12f 462 uint32_t ev_odd = (USB0->STAT >> 2) & 0x01;
djbottrill 0:aac55e1fc12f 463
djbottrill 0:aac55e1fc12f 464 // setup packet
djbottrill 0:aac55e1fc12f 465 if ((num == 0) && (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == SETUP_TOKEN)) {
djbottrill 0:aac55e1fc12f 466 Data1 &= ~0x02;
djbottrill 0:aac55e1fc12f 467 bdt[EP_BDT_IDX(0, TX, EVEN)].info &= ~BD_OWN_MASK;
djbottrill 0:aac55e1fc12f 468 bdt[EP_BDT_IDX(0, TX, ODD)].info &= ~BD_OWN_MASK;
djbottrill 0:aac55e1fc12f 469
djbottrill 0:aac55e1fc12f 470 // EP0 SETUP event (SETUP data received)
djbottrill 0:aac55e1fc12f 471 EP0setupCallback();
djbottrill 0:aac55e1fc12f 472
djbottrill 0:aac55e1fc12f 473 } else {
djbottrill 0:aac55e1fc12f 474 // OUT packet
djbottrill 0:aac55e1fc12f 475 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == OUT_TOKEN) {
djbottrill 0:aac55e1fc12f 476 if (num == 0)
djbottrill 0:aac55e1fc12f 477 EP0out();
djbottrill 0:aac55e1fc12f 478 else {
djbottrill 0:aac55e1fc12f 479 epComplete |= (1 << EP(num));
djbottrill 0:aac55e1fc12f 480 if ((instance->*(epCallback[EP(num) - 2]))()) {
djbottrill 0:aac55e1fc12f 481 epComplete &= ~(1 << EP(num));
djbottrill 0:aac55e1fc12f 482 }
djbottrill 0:aac55e1fc12f 483 }
djbottrill 0:aac55e1fc12f 484 }
djbottrill 0:aac55e1fc12f 485
djbottrill 0:aac55e1fc12f 486 // IN packet
djbottrill 0:aac55e1fc12f 487 if (TOK_PID((EP_BDT_IDX(num, dir, ev_odd))) == IN_TOKEN) {
djbottrill 0:aac55e1fc12f 488 if (num == 0) {
djbottrill 0:aac55e1fc12f 489 EP0in();
djbottrill 0:aac55e1fc12f 490 if (set_addr == 1) {
djbottrill 0:aac55e1fc12f 491 USB0->ADDR = addr & 0x7F;
djbottrill 0:aac55e1fc12f 492 set_addr = 0;
djbottrill 0:aac55e1fc12f 493 }
djbottrill 0:aac55e1fc12f 494 }
djbottrill 0:aac55e1fc12f 495 else {
djbottrill 0:aac55e1fc12f 496 epComplete |= (1 << (EP(num) + 1));
djbottrill 0:aac55e1fc12f 497 if ((instance->*(epCallback[EP(num) + 1 - 2]))()) {
djbottrill 0:aac55e1fc12f 498 epComplete &= ~(1 << (EP(num) + 1));
djbottrill 0:aac55e1fc12f 499 }
djbottrill 0:aac55e1fc12f 500 }
djbottrill 0:aac55e1fc12f 501 }
djbottrill 0:aac55e1fc12f 502 }
djbottrill 0:aac55e1fc12f 503
djbottrill 0:aac55e1fc12f 504 USB0->ISTAT = USB_ISTAT_TOKDNE_MASK;
djbottrill 0:aac55e1fc12f 505 }
djbottrill 0:aac55e1fc12f 506
djbottrill 0:aac55e1fc12f 507 // sleep interrupt
djbottrill 0:aac55e1fc12f 508 if (istat & 1<<4) {
djbottrill 0:aac55e1fc12f 509 USB0->ISTAT |= USB_ISTAT_SLEEP_MASK;
djbottrill 0:aac55e1fc12f 510 }
djbottrill 0:aac55e1fc12f 511
djbottrill 0:aac55e1fc12f 512 // error interrupt
djbottrill 0:aac55e1fc12f 513 if (istat & USB_ISTAT_ERROR_MASK) {
djbottrill 0:aac55e1fc12f 514 USB0->ERRSTAT = 0xFF;
djbottrill 0:aac55e1fc12f 515 USB0->ISTAT |= USB_ISTAT_ERROR_MASK;
djbottrill 0:aac55e1fc12f 516 }
djbottrill 0:aac55e1fc12f 517 }
djbottrill 0:aac55e1fc12f 518
djbottrill 0:aac55e1fc12f 519
djbottrill 0:aac55e1fc12f 520 #endif