////////////////////////////////////////////////////////////////////// // // THREAD FUNCTION TO RUN MIDI INPUT // ////////////////////////////////////////////////////////////////////// void RunMIDIInput() { SMQ_MSG msg; unsigned short num_read; byte uch; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); for(;;) { vos_dev_read(hUART, &uch, 1, &num_read); if(num_read > 0) { if(uch == 0xf8) { msg.status = 0xf8; msg.param1 = 0x00; msg.param2 = 0x00; SMQWrite(&msg); } } } }
//////////////////////////////////////////////////////////////////// // Main application thread void RunPlaypad() { SMQ_MSG msg; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); arpie_init(); for(;;) { SMQRead(&msg); switch(msg.status) { case 0x80: case 0x90: if(msg.status == 0x80 || msg.param2 == 0) { arpie_event(EVENT_KEYUP, msg.param1/16, msg.param1%16); } else { arpie_event(EVENT_KEYDOWN, msg.param1/16, msg.param1%16); } break; case 0xf8: // clock tick arpie_event(EVENT_TICK, 0, 0); break; } } }
void HelloWorld(void) { BYTE Counter = 0; vos_wait_semaphore(&DevicesStarted); vos_signal_semaphore(&DevicesStarted); dprint("Hello World has started\n", 0); while (1) { vos_delay_msecs(1000); dprint("Hello World %d ", &Counter++); } }
void StartupDevices(void) { gpio_ioctl_cb_t gpio_iocb; common_ioctl_cb_t uart_iocb; BYTE Status = 0; // Open GPIO driver and configure it hDevice[LEDs] = vos_dev_open(LEDs); // Set LED3 pin to output gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK; gpio_iocb.value = LED3; Status |= vos_dev_ioctl(hDevice[LEDs], &gpio_iocb); // Open UART driver and configure it hDevice[UART] = vos_dev_open(UART); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE; uart_iocb.set.uart_baud_rate = UART_BAUD_3000000; Status = vos_dev_ioctl(hDevice[UART], &uart_iocb); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL; uart_iocb.set.param = UART_FLOW_NONE; // Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS; uart_iocb.set.param = UART_DATA_BITS_8; Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS; uart_iocb.set.param = UART_STOP_BITS_1; Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY; uart_iocb.set.param = UART_PARITY_NONE; // Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb); // Since baud rate >= 115200 enable DMA for this channel uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA; Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb); // Finally enable UART interrupts are we're ready to go! vos_enable_interrupts(VOS_UART_INT_IEN); // Open two more GPIO drivers for the Logic Analyser and configure them hDevice[LA_In] = vos_dev_open(LA_In); // Set all port bits to input gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK; gpio_iocb.value = 0; Status |= vos_dev_ioctl(hDevice[LA_In], &gpio_iocb); hDevice[LA_Out] = vos_dev_open(LA_Out); // Set all port bits to output gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK; gpio_iocb.value = 0xFF; Status |= vos_dev_ioctl(hDevice[LA_Out], &gpio_iocb); // Spin up USB Host hDevice[Host] = vos_dev_open(Host); // Let other tasks know that devices are initialized vos_signal_semaphore(&DevicesStarted); CheckStatus(Status, ErrorStartupDevices); }
void HandleChapter9Request(BYTE ThreadID, usb_deviceRequest_t* Setup) { BYTE Temp; usbslave_ioctl_cb_t iocb; dprint("\nIn HandleChapter9Request with %x", &Setup->bRequest); switch (Setup->bRequest) { case USB_REQUEST_CODE_SET_ADDRESS: dprint("\nAt SetAddress with %X", &Setup->wValue); iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SET_ADDRESS; Temp = Setup->wValue & 0xFF; iocb.set = (void*) Temp; i_vos_dev_ioctl(ThreadID, hDevice[Slave], &iocb); SendACK(ThreadID); break; case USB_REQUEST_CODE_GET_DESCRIPTOR: Temp = Setup->wValue >> 8; dprint("\nIn Get Descriptor with %x", &Temp); switch (Temp) { case USB_DESCRIPTOR_TYPE_DEVICE: dprint("\nGet Device Descriptor (%X)", &Setup->wLength); SendResponse(ThreadID, &MyDeviceDescriptor[0], Setup->wLength ,sizeof(MyDeviceDescriptor)); break; case USB_DESCRIPTOR_TYPE_CONFIGURATION: dprint("\nGet Configuration Descriptor (%X)", &Setup->wLength); SendResponse(ThreadID, &MyConfigurationDescriptor[0], Setup->wLength ,sizeof(MyConfigurationDescriptor)); break; case 0x22: // This is request for the HID Report Descriptor SendResponse(ThreadID, &KeyboardReportDescriptor[0], Setup->wLength ,sizeof(KeyboardReportDescriptor)); break; // Need to complete these - catch as an error for now case USB_DESCRIPTOR_TYPE_ENDPOINT: case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: CheckStatus(Setup->wValue & 0xF, ErrorUnknownDescriptorType); break; } break; case USB_REQUEST_CODE_SET_CONFIGURATION: dprint("\nSet Configuration = %x", &Setup->wValue); SendACK(ThreadID); vos_signal_semaphore(&EnumerationComplete); break; // Need to complete these - catch as an error for now case USB_REQUEST_CODE_GET_STATUS: case USB_REQUEST_CODE_CLEAR_FEATURE: case USB_REQUEST_CODE_SET_FEATURE: case USB_REQUEST_CODE_SET_DESCRIPTOR: case USB_REQUEST_CODE_GET_CONFIGURATION: case USB_REQUEST_CODE_GET_INTERFACE: case USB_REQUEST_CODE_SET_INTERFACE: case USB_REQUEST_CODE_SYNCH_FRAME: CheckStatus(Setup->bRequest, ErrorUnknownRequest); break; } }
void fifo_write(FIFO_TYPE *pfifo, unsigned char *data, int count) { int i; for(i=0; i<count; ++i) { vos_wait_semaphore(&pfifo->semWrite); vos_lock_mutex(&pfifo->mutex); pfifo->data[pfifo->head] = data[i]; pfifo->head = FIFO_INC(pfifo->head); vos_unlock_mutex(&pfifo->mutex); } vos_signal_semaphore(&pfifo->semRead); }
int fifo_read(FIFO_TYPE *pfifo, unsigned char *data, int size) { int count = 0; vos_wait_semaphore(&pfifo->semRead); vos_lock_mutex(&pfifo->mutex); while(count < size && pfifo->tail != pfifo->head) { data[count] = pfifo->data[pfifo->tail]; pfifo->tail = FIFO_INC(pfifo->tail); vos_signal_semaphore(&pfifo->semWrite); ++count; } vos_unlock_mutex(&pfifo->mutex); return count; }
void RunUSBSend() { unsigned char attached; uint8 msg[3]; int param = 1; int i; unsigned short bytes_written; VOS_HANDLE hUSB; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); msg[0] = 0; while(1) { int count = fifo_read(&stSPIReadFIFO, usbSendBuffer, 64); for(i=0;i<count;++i) { if(usbSendBuffer[i]&0x80) { msg[0] = usbSendBuffer[i]; param = 1; } else if(param == 1) { msg[1] = usbSendBuffer[i]; param = 2; } else if(param == 2) { msg[2] = usbSendBuffer[i]; param = 1; if(msg[0]) { VOS_ENTER_CRITICAL_SECTION; hUSB = PortA.hUSBHOSTGENERIC; VOS_EXIT_CRITICAL_SECTION; if(hUSB) { vos_dev_write(hUSB, msg, 3, &bytes_written); } } } } } }
////////////////////////////////////////////////////////////////////// // // APPLICATION SETUP THREAD FUNCTION // ////////////////////////////////////////////////////////////////////// void Setup() { common_ioctl_cb_t spis_iocb; usbhostGeneric_ioctl_t generic_iocb; gpio_ioctl_cb_t gpio_iocb; common_ioctl_cb_t uart_iocb; unsigned char uchLeds; common_ioctl_cb_t ss_iocb; hSPISlave = vos_dev_open(VOS_DEV_SPISLAVE); // Open up the base level drivers hGpioA = vos_dev_open(VOS_DEV_GPIO_A); gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK; gpio_iocb.value = 0b11000110; vos_dev_ioctl(hGpioA, &gpio_iocb); setGpioA(0b11000110,0); ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SCK_CPHA; ss_iocb.set.param = SPI_SLAVE_SCK_CPHA_0; vos_dev_ioctl(hSPISlave, &ss_iocb); ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SCK_CPOL; ss_iocb.set.param = SPI_SLAVE_SCK_CPOL_0; vos_dev_ioctl(hSPISlave, &ss_iocb); ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_DATA_ORDER; ss_iocb.set.param = SPI_SLAVE_DATA_ORDER_MSB; vos_dev_ioctl(hSPISlave, &ss_iocb); ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SET_MODE; ss_iocb.set.param = SPI_SLAVE_MODE_FULL_DUPLEX; vos_dev_ioctl(hSPISlave, &ss_iocb); ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SET_ADDRESS; ss_iocb.set.param = 0; vos_dev_ioctl(hSPISlave, &ss_iocb); ss_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA; ss_iocb.set.param = DMA_ACQUIRE_AND_RETAIN; vos_dev_ioctl(hSPISlave, &ss_iocb); // Release other application threads vos_signal_semaphore(&setupSem); }
void RunSPISend() { unsigned short bytes_written; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); while(1) { int count = fifo_read(&stSPIWriteFIFO, spiSendBuffer, 64); vos_dev_write(hSPISlave, spiSendBuffer, (unsigned short)count, &bytes_written); setGpioA(LED_SIGNAL,0); setGpioA(LED_SIGNAL,LED_SIGNAL|LED_ACTIVITY); } }
void RunSPIReceive() { unsigned short bytes_read; common_ioctl_cb_t spi_iocb; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); while(1) { spi_iocb.ioctl_code = VOS_IOCTL_COMMON_GET_RX_QUEUE_STATUS; vos_dev_ioctl(hSPISlave, &spi_iocb); if(spi_iocb.get.queue_stat) { if(0==vos_dev_read(hSPISlave, (char*)spiRxBuffer, spi_iocb.get.queue_stat, &bytes_read)) fifo_write(&stSPIReadFIFO, spiRxBuffer, (int)bytes_read); } } }
////////////////////////////////////////////////////////////////////// // // APPLICATION SETUP THREAD FUNCTION // ////////////////////////////////////////////////////////////////////// void Setup() { common_ioctl_cb_t spis_iocb; usbhostGeneric_ioctl_t generic_iocb; gpio_ioctl_cb_t gpio_iocb; common_ioctl_cb_t uart_iocb; unsigned char uchLeds; // Open up the base level drivers hGpioA = vos_dev_open(VOS_DEV_GPIO_A); PortA.hUSBHOST = vos_dev_open(VOS_DEV_USBHOST_1); //PortB.hUSBHOST = vos_dev_open(VOS_DEV_USBHOST_2); gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK; gpio_iocb.value = 0b00001110; vos_dev_ioctl(hGpioA, &gpio_iocb); uchLeds = 0b00001000; vos_dev_write(hGpioA,&uchLeds,1,NULL); hUART = vos_dev_open(VOS_DEV_UART); /* UART ioctl call to enable DMA and link to DMA driver */ uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA; vos_dev_ioctl(hUART, &uart_iocb); // Set up for MIDI uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE; uart_iocb.set.uart_baud_rate = 31250; vos_dev_ioctl(hUART, &uart_iocb); uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL; uart_iocb.set.param = UART_FLOW_NONE; vos_dev_ioctl(hUART, &uart_iocb); // Set up the metronome MetroInit(&metro, VOS_DEV_TIMER0, TIMER_0); // Release other application threads vos_signal_semaphore(&setupSem); }
///////////////////////////////////////////////////////////////////// // Thread to dispatch tick events to the playpad thread // at timed intervals void RunMetronome() { SMQ_MSG tick; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); // Prepare standard tick message tick.status = 0xf8; tick.param1 = 0x00; tick.param2 = 0x00; // Start the metronome MetroStart(&metro, VOS_DEV_TIMER0, 120); for(;;) { // run! SMQWrite(&tick); MetroDelay(&metro); } }
int incHead(int oldHe ///////////////////////////////////////////////////////////////////////////// // WRITE void SMQWrite(uint8 tag, uint8 device, int size, uint8 *data) { int newHead; vos_lock_mutex(&mAccess); newHead = head + 1; if(newHead >= SMQ_LEN) newHead = 0; if(newHead != tail) { queue[head].status = msg->status; queue[head].param1 = msg->param1; queue[head].param2 = msg->param2; head = newHead; vos_signal_semaphore(&semAvailable); } vos_unlock_mutex(&mAccess); }
////////////////////////////////////////////////////////////////////// // // THREAD FUNCTION TO RUN USB HOST PORT // ////////////////////////////////////////////////////////////////////// void RunHostPort(HOST_PORT_DATA *pHostData) { unsigned char status; unsigned char buf[64]; unsigned short num_read; unsigned int handle; usbhostGeneric_ioctl_t generic_iocb; usbhostGeneric_ioctl_cb_attach_t genericAtt; usbhost_device_handle_ex ifDev; usbhost_ioctl_cb_t hc_iocb; usbhost_ioctl_cb_vid_pid_t hc_iocb_vid_pid; gpio_ioctl_cb_t gpio_iocb; SMQ_MSG msg; msg.status = 0x90; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); // loop forever while(1) { // is the device enumerated on this port? if (usbhost_connect_state(pHostData->hUSBHOST) == PORT_STATE_ENUMERATED) { // user ioctl to find first hub device hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE; hc_iocb.handle.dif = NULL; hc_iocb.set = NULL; hc_iocb.get = &ifDev; if (vos_dev_ioctl(pHostData->hUSBHOST, &hc_iocb) == USBHOST_OK) { hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_VID_PID; hc_iocb.handle.dif = ifDev; hc_iocb.get = &hc_iocb_vid_pid; // attach the Launchpad device to the USB host device pHostData->hUSBHOSTGENERIC = vos_dev_open(pHostData->uchDeviceNumber); genericAtt.hc_handle = pHostData->hUSBHOST; genericAtt.ifDev = ifDev; generic_iocb.ioctl_code = VOS_IOCTL_USBHOSTGENERIC_ATTACH; generic_iocb.set.att = &genericAtt; if (vos_dev_ioctl(pHostData->hUSBHOSTGENERIC, &generic_iocb) == USBHOSTGENERIC_OK) { setLed(pHostData->uchActivityLed, 1); // now we loop until the launchpad is detached while(1) { int pos = 0; byte param = 1; // read data status = vos_dev_read(pHostData->hUSBHOSTGENERIC, buf, 64, &num_read); if(status != USBHOSTGENERIC_OK) break; setLed(pHostData->uchActivityLed, 0); // interpret MIDI data and pass to application thread while(pos < num_read) { if(buf[pos] & 0x80) { msg.status = buf[pos]; param = 1; } else if(param == 1) { msg.param1 = buf[pos]; param = 2; } else if(param == 2) { msg.param2 = buf[pos]; SMQWrite(&msg); param = 1; } ++pos; } setLed(pHostData->uchActivityLed, 1); } } vos_dev_close(pHostData->hUSBHOSTGENERIC); } } setLed(pHostData->uchActivityLed, 0); } }
void WaitForDevicesStarted(void) { vos_wait_semaphore(&DevicesStarted); vos_signal_semaphore(&DevicesStarted); }
////////////////////////////////////////////////////////////////////// // // RUN USB HOST PORT // ////////////////////////////////////////////////////////////////////// void RunHostPort(HOST_PORT_DATA *pHostData) { int i; int midiParam; unsigned char status; unsigned char buf[64]; unsigned short num_bytes; unsigned int handle; usbhostGeneric_ioctl_t generic_iocb; usbhostGeneric_ioctl_cb_attach_t genericAtt; usbhost_device_handle_ex ifDev; usbhost_ioctl_cb_t hc_iocb; usbhost_ioctl_cb_vid_pid_t hc_iocb_vid_pid; gpio_ioctl_cb_t gpio_iocb; VOS_HANDLE hUSB; // wait for setup to complete vos_wait_semaphore(&setupSem); vos_signal_semaphore(&setupSem); // Open the base USB Host driver pHostData->hUSBHOST = vos_dev_open(pHostData->uchDeviceNumberBase); // loop forever while(1) { vos_delay_msecs(10); // is the device enumerated on this port? if (usbhost_connect_state(pHostData->hUSBHOST) == PORT_STATE_ENUMERATED) { // user ioctl to find first hub device hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE; hc_iocb.handle.dif = NULL; hc_iocb.set = NULL; hc_iocb.get = &ifDev; if (vos_dev_ioctl(pHostData->hUSBHOST, &hc_iocb) == USBHOST_OK) { // query the device VID/PID hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_VID_PID; hc_iocb.handle.dif = ifDev; hc_iocb.get = &hc_iocb_vid_pid; // Load the function driver hUSB = vos_dev_open(pHostData->uchDeviceNumber); // Attach the function driver to the base driver genericAtt.hc_handle = pHostData->hUSBHOST; genericAtt.ifDev = ifDev; generic_iocb.ioctl_code = VOS_IOCTL_USBHOSTGENERIC_ATTACH; generic_iocb.set.att = &genericAtt; if (vos_dev_ioctl(hUSB, &generic_iocb) == USBHOSTGENERIC_OK) { // Turn on the LED for this port setGpioA(pHostData->uchActivityLed, pHostData->uchActivityLed); // flag that the port is attached VOS_ENTER_CRITICAL_SECTION; pHostData->hUSBHOSTGENERIC = hUSB; VOS_EXIT_CRITICAL_SECTION; // now we loop until the launchpad is detached while(1) { // listen for data from launchpad uint16 result = vos_dev_read(hUSB, buf, 64, &num_bytes); if(0 != result) break; // break when the launchpad is detached fifo_write(&stSPIWriteFIFO, buf, (int)num_bytes); } // flag that the port is no longer attached VOS_ENTER_CRITICAL_SECTION; pHostData->hUSBHOSTGENERIC = NULL; VOS_EXIT_CRITICAL_SECTION; // turn off the activity LED setGpioA(pHostData->uchActivityLed, 0); } // close the function driver vos_dev_close(hUSB); } } } }
void i_vos_signal_semaphore(BYTE ThreadID, vos_semaphore_t* s) { CallVOS(ThreadID); vos_signal_semaphore(s); ThreadRunning(ThreadID); }
// This function is run inside the thread created in init // It will respond to standard USB requests // some of the requests are forwarded to the flash drive when appropriate void usbslaveboms_setup(usbSlaveBoms_context *ctx) { usbslave_ioctl_cb_t iocb; // this is a structure used by underlying VOS driver usb_deviceRequest_t *devReq; // this struct is defined in usb.h and is used to store the 9 byte setup request unsigned char bmRequestType; // The request type is defined by USB standard unsigned char state = UNATTACHED; // assume unattached at the start // This will wait till the flash drive is enumed so we don't // start responding to commands right away vos_wait_semaphore(&ctx->enumed); vos_signal_semaphore(&ctx->enumed); vos_wait_semaphore(&setupDoneSemaphore); // wait for setup to complete vos_signal_semaphore(&setupDoneSemaphore); // reset semaphore for next guy while (1) { switch (state) { case UNATTACHED: if (!ctx->attached) vos_delay_msecs(100); // this delay is to avoid a tight loop else { state = ATTACHED; } break; case ATTACHED: if (!ctx->attached) // check to see if we somehow became unattached { state = UNATTACHED; break; } // we now make a blocking call requesting the 9 byte setup // packet on the control endpoint iocb.ioctl_code = VOS_IOCTL_USBSLAVE_WAIT_SETUP_RCVD; iocb.request.setup_or_bulk_transfer.buffer = ctx->setup_buffer; iocb.request.setup_or_bulk_transfer.size = 9; vos_dev_ioctl(ctx->handle, &iocb); // decode the raw data by pointing to our structure devReq = (usb_deviceRequest_t *) ctx->setup_buffer; // valid types here are standard, class, and vendor // BOMS devices do not have vendor specific calls // even if they did, we wouldn't support them. bmRequestType = devReq->bmRequestType & (USB_BMREQUESTTYPE_STANDARD | USB_BMREQUESTTYPE_CLASS); // we only need to handle standard and class requests for BOMS if (bmRequestType == USB_BMREQUESTTYPE_STANDARD) { standard_request(ctx); // standard request that all USB devices support } else if (bmRequestType == USB_BMREQUESTTYPE_CLASS) { class_request(ctx); // the request is specific to this device class (only 2 in our case) } break; default: asm {HALT}; // if we somehow got here the fecal matter has hit the turbine break; } } return; }