I have ported my old project “pNesX” game console emulator to the nucleo.

Dependencies:   SDFileSystem mbed

Intro

I have ported my old project “pNesX” to the STM32 Nucleo. The pNesX is a NES emulator for the PlayStation that I have created 16 years ago!

Emulation part was almost without change, the sound part was newly added.

Parts

STM32 Nucleo F446RE
QVGA 2.2 TFT SPI (with the SD card slot)
Audio jack(TS or TRS)
USB Connector
Register 100k, 10k, 4.7k, 100
Capacitor 0.01uF, 2.2uF
Breadboard
Wires
Computer Speakers
USB GamePad

Wiring diagram

/media/uploads/beaglescout007/nucleo_ex06_emu.png

TFT J2Nucleo
VCC3V3
GNDGND
CSPB_5(D4)
ResetPA_10(D2) Pull Up(100k)
D/CPA_8(D7)
MOSIPA_7(D11)
SCKPA_5(D13)
LEDLED-100ohm-3V3
MISOPA_6(D12)
TFT J4Nucleo
SD_CSPA_9
SD_MOSIPB_15
SD_MISOPB_14
SD_SCKPB_13
AudioNucleo
TIPPA_4(A2)
USB con.Nucleo
GNDGND
+PA_12
-PA_11
5V5V

https://youtu.be/jL24IjT6LnI

Limitations

  • Since the rest of the RAM is about 50kbyte, maximum capacity of the game ROM is about 50kbyte.
  • The length of the file name up to 32 characters.
  • The number of files in the folder is up to 100.

Used Library

Committer:
beaglescout007
Date:
Sun Apr 03 07:45:29 2016 +0000
Revision:
0:3dac1f1bc9e0
Release

Who changed what in which revision?

UserRevisionLine numberNew contents of line
beaglescout007 0:3dac1f1bc9e0 1 /* mbed USBHost Library
beaglescout007 0:3dac1f1bc9e0 2 * Copyright (c) 2006-2013 ARM Limited
beaglescout007 0:3dac1f1bc9e0 3 *
beaglescout007 0:3dac1f1bc9e0 4 * Licensed under the Apache License, Version 2.0 (the "License");
beaglescout007 0:3dac1f1bc9e0 5 * you may not use this file except in compliance with the License.
beaglescout007 0:3dac1f1bc9e0 6 * You may obtain a copy of the License at
beaglescout007 0:3dac1f1bc9e0 7 *
beaglescout007 0:3dac1f1bc9e0 8 * http://www.apache.org/licenses/LICENSE-2.0
beaglescout007 0:3dac1f1bc9e0 9 *
beaglescout007 0:3dac1f1bc9e0 10 * Unless required by applicable law or agreed to in writing, software
beaglescout007 0:3dac1f1bc9e0 11 * distributed under the License is distributed on an "AS IS" BASIS,
beaglescout007 0:3dac1f1bc9e0 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
beaglescout007 0:3dac1f1bc9e0 13 * See the License for the specific language governing permissions and
beaglescout007 0:3dac1f1bc9e0 14 * limitations under the License.
beaglescout007 0:3dac1f1bc9e0 15 */
beaglescout007 0:3dac1f1bc9e0 16
beaglescout007 0:3dac1f1bc9e0 17 #include "USBHost.h"
beaglescout007 0:3dac1f1bc9e0 18
beaglescout007 0:3dac1f1bc9e0 19 #define USB_TRACE1(A) while(0)
beaglescout007 0:3dac1f1bc9e0 20 #undef USB_TEST_ASSERT
beaglescout007 0:3dac1f1bc9e0 21 void usb_test_assert_internal(const char *expr, const char *file, int line);
beaglescout007 0:3dac1f1bc9e0 22 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
beaglescout007 0:3dac1f1bc9e0 23
beaglescout007 0:3dac1f1bc9e0 24 USBHost* USBHost::inst = NULL;
beaglescout007 0:3dac1f1bc9e0 25
beaglescout007 0:3dac1f1bc9e0 26 USBHost* USBHost::getHostInst() {
beaglescout007 0:3dac1f1bc9e0 27 if (inst == NULL) {
beaglescout007 0:3dac1f1bc9e0 28 inst = new USBHost();
beaglescout007 0:3dac1f1bc9e0 29 inst->init();
beaglescout007 0:3dac1f1bc9e0 30 }
beaglescout007 0:3dac1f1bc9e0 31 return inst;
beaglescout007 0:3dac1f1bc9e0 32 }
beaglescout007 0:3dac1f1bc9e0 33
beaglescout007 0:3dac1f1bc9e0 34 void USBHost::poll()
beaglescout007 0:3dac1f1bc9e0 35 {
beaglescout007 0:3dac1f1bc9e0 36 if (inst) {
beaglescout007 0:3dac1f1bc9e0 37 inst->task();
beaglescout007 0:3dac1f1bc9e0 38 }
beaglescout007 0:3dac1f1bc9e0 39 }
beaglescout007 0:3dac1f1bc9e0 40
beaglescout007 0:3dac1f1bc9e0 41 USBHost::USBHost() {
beaglescout007 0:3dac1f1bc9e0 42 }
beaglescout007 0:3dac1f1bc9e0 43
beaglescout007 0:3dac1f1bc9e0 44 /* virtual */ bool USBHost::addDevice(USBDeviceConnected* parent, int port, bool lowSpeed) {
beaglescout007 0:3dac1f1bc9e0 45 USBDeviceConnected* dev = new USBDeviceConnected;
beaglescout007 0:3dac1f1bc9e0 46 USBEndpoint* ep = new USBEndpoint(dev);
beaglescout007 0:3dac1f1bc9e0 47 dev->init(0, port, lowSpeed);
beaglescout007 0:3dac1f1bc9e0 48 dev->setAddress(0);
beaglescout007 0:3dac1f1bc9e0 49 dev->setEpCtl(ep);
beaglescout007 0:3dac1f1bc9e0 50 uint8_t desc[18];
beaglescout007 0:3dac1f1bc9e0 51 wait_ms(100);
beaglescout007 0:3dac1f1bc9e0 52
beaglescout007 0:3dac1f1bc9e0 53 int rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, 8);
beaglescout007 0:3dac1f1bc9e0 54 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 55 if (rc != USB_TYPE_OK) {
beaglescout007 0:3dac1f1bc9e0 56 USB_ERR("ADD DEVICE FAILD");
beaglescout007 0:3dac1f1bc9e0 57 }
beaglescout007 0:3dac1f1bc9e0 58 USB_DBG_HEX(desc, 8);
beaglescout007 0:3dac1f1bc9e0 59 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
beaglescout007 0:3dac1f1bc9e0 60 ep->setSize(dev_desc->bMaxPacketSize);
beaglescout007 0:3dac1f1bc9e0 61
beaglescout007 0:3dac1f1bc9e0 62 int new_addr = USBDeviceConnected::getNewAddress();
beaglescout007 0:3dac1f1bc9e0 63 rc = controlWrite(dev, 0x00, SET_ADDRESS, new_addr, 0, NULL, 0);
beaglescout007 0:3dac1f1bc9e0 64 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 65 dev->setAddress(new_addr);
beaglescout007 0:3dac1f1bc9e0 66 wait_ms(100);
beaglescout007 0:3dac1f1bc9e0 67
beaglescout007 0:3dac1f1bc9e0 68 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
beaglescout007 0:3dac1f1bc9e0 69 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 70 USB_DBG_HEX(desc, sizeof(desc));
beaglescout007 0:3dac1f1bc9e0 71
beaglescout007 0:3dac1f1bc9e0 72 dev->setVid(dev_desc->idVendor);
beaglescout007 0:3dac1f1bc9e0 73 dev->setPid(dev_desc->idProduct);
beaglescout007 0:3dac1f1bc9e0 74 dev->setClass(dev_desc->bDeviceClass);
beaglescout007 0:3dac1f1bc9e0 75 USB_INFO("parent:%p port:%d speed:%s VID:%04x PID:%04x class:%02x addr:%d",
beaglescout007 0:3dac1f1bc9e0 76 parent, port, (lowSpeed ? "low " : "full"), dev->getVid(), dev->getPid(), dev->getClass(),
beaglescout007 0:3dac1f1bc9e0 77 dev->getAddress());
beaglescout007 0:3dac1f1bc9e0 78
beaglescout007 0:3dac1f1bc9e0 79 DeviceLists.push_back(dev);
beaglescout007 0:3dac1f1bc9e0 80
beaglescout007 0:3dac1f1bc9e0 81 if (dev->getClass() == HUB_CLASS) {
beaglescout007 0:3dac1f1bc9e0 82 const int config = 1;
beaglescout007 0:3dac1f1bc9e0 83 int rc = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
beaglescout007 0:3dac1f1bc9e0 84 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 85 wait_ms(100);
beaglescout007 0:3dac1f1bc9e0 86 Hub(dev);
beaglescout007 0:3dac1f1bc9e0 87 }
beaglescout007 0:3dac1f1bc9e0 88 return true;
beaglescout007 0:3dac1f1bc9e0 89 }
beaglescout007 0:3dac1f1bc9e0 90
beaglescout007 0:3dac1f1bc9e0 91 // enumerate a device with the control USBEndpoint
beaglescout007 0:3dac1f1bc9e0 92 USB_TYPE USBHost::enumerate(USBDeviceConnected * dev, IUSBEnumerator* pEnumerator)
beaglescout007 0:3dac1f1bc9e0 93 {
beaglescout007 0:3dac1f1bc9e0 94 if (dev->getClass() == HUB_CLASS) { // skip hub class
beaglescout007 0:3dac1f1bc9e0 95 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 96 }
beaglescout007 0:3dac1f1bc9e0 97 uint8_t desc[18];
beaglescout007 0:3dac1f1bc9e0 98 USB_TYPE rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 1<<8, 0, desc, sizeof(desc));
beaglescout007 0:3dac1f1bc9e0 99 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 100 USB_DBG_HEX(desc, sizeof(desc));
beaglescout007 0:3dac1f1bc9e0 101 if (rc != USB_TYPE_OK) {
beaglescout007 0:3dac1f1bc9e0 102 return rc;
beaglescout007 0:3dac1f1bc9e0 103 }
beaglescout007 0:3dac1f1bc9e0 104 DeviceDescriptor* dev_desc = reinterpret_cast<DeviceDescriptor*>(desc);
beaglescout007 0:3dac1f1bc9e0 105 dev->setClass(dev_desc->bDeviceClass);
beaglescout007 0:3dac1f1bc9e0 106 pEnumerator->setVidPid(dev->getVid(), dev->getPid());
beaglescout007 0:3dac1f1bc9e0 107
beaglescout007 0:3dac1f1bc9e0 108 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, desc, 4);
beaglescout007 0:3dac1f1bc9e0 109 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 110 USB_DBG_HEX(desc, 4);
beaglescout007 0:3dac1f1bc9e0 111
beaglescout007 0:3dac1f1bc9e0 112 int TotalLength = desc[2]|desc[3]<<8;
beaglescout007 0:3dac1f1bc9e0 113 uint8_t* buf = new uint8_t[TotalLength];
beaglescout007 0:3dac1f1bc9e0 114 rc = controlRead(dev, 0x80, GET_DESCRIPTOR, 2<<8, 0, buf, TotalLength);
beaglescout007 0:3dac1f1bc9e0 115 USB_TEST_ASSERT(rc == USB_TYPE_OK);
beaglescout007 0:3dac1f1bc9e0 116 //USB_DBG_HEX(buf, TotalLength);
beaglescout007 0:3dac1f1bc9e0 117
beaglescout007 0:3dac1f1bc9e0 118 // Parse the configuration descriptor
beaglescout007 0:3dac1f1bc9e0 119 parseConfDescr(dev, buf, TotalLength, pEnumerator);
beaglescout007 0:3dac1f1bc9e0 120 delete[] buf;
beaglescout007 0:3dac1f1bc9e0 121 // only set configuration if not enumerated before
beaglescout007 0:3dac1f1bc9e0 122 if (!dev->isEnumerated()) {
beaglescout007 0:3dac1f1bc9e0 123 USB_DBG("Set configuration 1 on dev: %p", dev);
beaglescout007 0:3dac1f1bc9e0 124 // sixth step: set configuration (only 1 supported)
beaglescout007 0:3dac1f1bc9e0 125 int config = 1;
beaglescout007 0:3dac1f1bc9e0 126 USB_TYPE res = controlWrite(dev, 0x00, SET_CONFIGURATION, config, 0, NULL, 0);
beaglescout007 0:3dac1f1bc9e0 127 if (res != USB_TYPE_OK) {
beaglescout007 0:3dac1f1bc9e0 128 USB_ERR("SET CONF FAILED");
beaglescout007 0:3dac1f1bc9e0 129 return res;
beaglescout007 0:3dac1f1bc9e0 130 }
beaglescout007 0:3dac1f1bc9e0 131 // Some devices may require this delay
beaglescout007 0:3dac1f1bc9e0 132 wait_ms(100);
beaglescout007 0:3dac1f1bc9e0 133 dev->setEnumerated();
beaglescout007 0:3dac1f1bc9e0 134 // Now the device is enumerated!
beaglescout007 0:3dac1f1bc9e0 135 USB_DBG("dev %p is enumerated", dev);
beaglescout007 0:3dac1f1bc9e0 136 }
beaglescout007 0:3dac1f1bc9e0 137 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 138 }
beaglescout007 0:3dac1f1bc9e0 139
beaglescout007 0:3dac1f1bc9e0 140 // this method fills the USBDeviceConnected object: class,.... . It also add endpoints found in the descriptor.
beaglescout007 0:3dac1f1bc9e0 141 void USBHost::parseConfDescr(USBDeviceConnected * dev, uint8_t * conf_descr, uint32_t len, IUSBEnumerator* pEnumerator)
beaglescout007 0:3dac1f1bc9e0 142 {
beaglescout007 0:3dac1f1bc9e0 143 uint32_t index = 0;
beaglescout007 0:3dac1f1bc9e0 144 uint32_t len_desc = 0;
beaglescout007 0:3dac1f1bc9e0 145 uint8_t id = 0;
beaglescout007 0:3dac1f1bc9e0 146 USBEndpoint * ep = NULL;
beaglescout007 0:3dac1f1bc9e0 147 uint8_t intf_nb = 0;
beaglescout007 0:3dac1f1bc9e0 148 bool parsing_intf = false;
beaglescout007 0:3dac1f1bc9e0 149 uint8_t current_intf = 0;
beaglescout007 0:3dac1f1bc9e0 150 EndpointDescriptor* ep_desc;
beaglescout007 0:3dac1f1bc9e0 151
beaglescout007 0:3dac1f1bc9e0 152 while (index < len) {
beaglescout007 0:3dac1f1bc9e0 153 len_desc = conf_descr[index];
beaglescout007 0:3dac1f1bc9e0 154 id = conf_descr[index+1];
beaglescout007 0:3dac1f1bc9e0 155 USB_DBG_HEX(conf_descr+index, len_desc);
beaglescout007 0:3dac1f1bc9e0 156 switch (id) {
beaglescout007 0:3dac1f1bc9e0 157 case CONFIGURATION_DESCRIPTOR:
beaglescout007 0:3dac1f1bc9e0 158 USB_DBG("dev: %p has %d intf", dev, conf_descr[4]);
beaglescout007 0:3dac1f1bc9e0 159 dev->setNbIntf(conf_descr[4]);
beaglescout007 0:3dac1f1bc9e0 160 break;
beaglescout007 0:3dac1f1bc9e0 161 case INTERFACE_DESCRIPTOR:
beaglescout007 0:3dac1f1bc9e0 162 if(pEnumerator->parseInterface(conf_descr[index + 2], conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7])) {
beaglescout007 0:3dac1f1bc9e0 163 intf_nb++;
beaglescout007 0:3dac1f1bc9e0 164 current_intf = conf_descr[index + 2];
beaglescout007 0:3dac1f1bc9e0 165 dev->addInterface(current_intf, conf_descr[index + 5], conf_descr[index + 6], conf_descr[index + 7]);
beaglescout007 0:3dac1f1bc9e0 166 USB_DBG("ADD INTF %d on device %p: class: %d, subclass: %d, proto: %d", current_intf, dev, conf_descr[index + 5],conf_descr[index + 6],conf_descr[index + 7]);
beaglescout007 0:3dac1f1bc9e0 167 parsing_intf = true;
beaglescout007 0:3dac1f1bc9e0 168 } else {
beaglescout007 0:3dac1f1bc9e0 169 parsing_intf = false;
beaglescout007 0:3dac1f1bc9e0 170 }
beaglescout007 0:3dac1f1bc9e0 171 break;
beaglescout007 0:3dac1f1bc9e0 172 case ENDPOINT_DESCRIPTOR:
beaglescout007 0:3dac1f1bc9e0 173 ep_desc = reinterpret_cast<EndpointDescriptor*>(conf_descr+index);
beaglescout007 0:3dac1f1bc9e0 174 if (parsing_intf && (intf_nb <= MAX_INTF) ) {
beaglescout007 0:3dac1f1bc9e0 175 ENDPOINT_TYPE type = (ENDPOINT_TYPE)(ep_desc->bmAttributes & 0x03);
beaglescout007 0:3dac1f1bc9e0 176 ENDPOINT_DIRECTION dir = (ep_desc->bEndpointAddress & 0x80) ? IN : OUT;
beaglescout007 0:3dac1f1bc9e0 177 if(pEnumerator->useEndpoint(current_intf, type, dir)) {
beaglescout007 0:3dac1f1bc9e0 178 ep = new USBEndpoint(dev);
beaglescout007 0:3dac1f1bc9e0 179 ep->init(type, dir, ep_desc->wMaxPacketSize, ep_desc->bEndpointAddress);
beaglescout007 0:3dac1f1bc9e0 180 USB_DBG("ADD USBEndpoint %p, on interf %d on device %p", ep, current_intf, dev);
beaglescout007 0:3dac1f1bc9e0 181 dev->addEndpoint(current_intf, ep);
beaglescout007 0:3dac1f1bc9e0 182 }
beaglescout007 0:3dac1f1bc9e0 183 }
beaglescout007 0:3dac1f1bc9e0 184 break;
beaglescout007 0:3dac1f1bc9e0 185 case HID_DESCRIPTOR:
beaglescout007 0:3dac1f1bc9e0 186 //lenReportDescr = conf_descr[index + 7] | (conf_descr[index + 8] << 8);
beaglescout007 0:3dac1f1bc9e0 187 break;
beaglescout007 0:3dac1f1bc9e0 188 default:
beaglescout007 0:3dac1f1bc9e0 189 break;
beaglescout007 0:3dac1f1bc9e0 190 }
beaglescout007 0:3dac1f1bc9e0 191 index += len_desc;
beaglescout007 0:3dac1f1bc9e0 192 }
beaglescout007 0:3dac1f1bc9e0 193 }
beaglescout007 0:3dac1f1bc9e0 194
beaglescout007 0:3dac1f1bc9e0 195 USB_TYPE USBHost::controlRead(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
beaglescout007 0:3dac1f1bc9e0 196 USBEndpoint* ep = dev->getEpCtl();
beaglescout007 0:3dac1f1bc9e0 197 SETUP_PACKET setup(requestType, request, value, index, len);
beaglescout007 0:3dac1f1bc9e0 198
beaglescout007 0:3dac1f1bc9e0 199 int result = token_setup(ep, &setup, len); // setup stage
beaglescout007 0:3dac1f1bc9e0 200 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 201 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 202 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 203 }
beaglescout007 0:3dac1f1bc9e0 204
beaglescout007 0:3dac1f1bc9e0 205 int read_len = multi_token_in(ep, buf, len); // data stage
beaglescout007 0:3dac1f1bc9e0 206 USB_TRACE1(read_len);
beaglescout007 0:3dac1f1bc9e0 207 if (read_len < 0) {
beaglescout007 0:3dac1f1bc9e0 208 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 209 }
beaglescout007 0:3dac1f1bc9e0 210
beaglescout007 0:3dac1f1bc9e0 211 setToggle(ep, 1); // DATA1
beaglescout007 0:3dac1f1bc9e0 212 result = multi_token_out(ep); // status stage
beaglescout007 0:3dac1f1bc9e0 213 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 214 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 215 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 216 }
beaglescout007 0:3dac1f1bc9e0 217 ep->setLengthTransferred(read_len);
beaglescout007 0:3dac1f1bc9e0 218 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 219 }
beaglescout007 0:3dac1f1bc9e0 220
beaglescout007 0:3dac1f1bc9e0 221 USB_TYPE USBHost::controlWrite(USBDeviceConnected* dev, uint8_t requestType, uint8_t request, uint32_t value, uint32_t index, uint8_t * buf, uint32_t len) {
beaglescout007 0:3dac1f1bc9e0 222 USBEndpoint* ep = dev->getEpCtl();
beaglescout007 0:3dac1f1bc9e0 223 SETUP_PACKET setup(requestType, request, value, index, len);
beaglescout007 0:3dac1f1bc9e0 224
beaglescout007 0:3dac1f1bc9e0 225 int result = token_setup(ep, &setup, len); // setup stage
beaglescout007 0:3dac1f1bc9e0 226 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 227 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 228 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 229 }
beaglescout007 0:3dac1f1bc9e0 230 int write_len = 0;
beaglescout007 0:3dac1f1bc9e0 231 if (buf != NULL) {
beaglescout007 0:3dac1f1bc9e0 232 write_len = multi_token_out(ep, buf, len); // data stage
beaglescout007 0:3dac1f1bc9e0 233 USB_TRACE1(write_len);
beaglescout007 0:3dac1f1bc9e0 234 if (write_len < 0) {
beaglescout007 0:3dac1f1bc9e0 235 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 236 }
beaglescout007 0:3dac1f1bc9e0 237 }
beaglescout007 0:3dac1f1bc9e0 238
beaglescout007 0:3dac1f1bc9e0 239 setToggle(ep, 1); // DATA1
beaglescout007 0:3dac1f1bc9e0 240 result = multi_token_in(ep); // status stage
beaglescout007 0:3dac1f1bc9e0 241 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 242 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 243 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 244 }
beaglescout007 0:3dac1f1bc9e0 245 ep->setLengthTransferred(write_len);
beaglescout007 0:3dac1f1bc9e0 246 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 247 }
beaglescout007 0:3dac1f1bc9e0 248
beaglescout007 0:3dac1f1bc9e0 249 USB_TYPE USBHost::bulkRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
beaglescout007 0:3dac1f1bc9e0 250 if (blocking == false) {
beaglescout007 0:3dac1f1bc9e0 251 ep->setBuffer(buf, len);
beaglescout007 0:3dac1f1bc9e0 252 ep_queue.push(ep);
beaglescout007 0:3dac1f1bc9e0 253 multi_token_inNB(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 254 return USB_TYPE_PROCESSING;
beaglescout007 0:3dac1f1bc9e0 255 }
beaglescout007 0:3dac1f1bc9e0 256 int result = multi_token_in(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 257 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 258 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 259 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 260 }
beaglescout007 0:3dac1f1bc9e0 261 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 262 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 263 }
beaglescout007 0:3dac1f1bc9e0 264
beaglescout007 0:3dac1f1bc9e0 265 USB_TYPE USBHost::bulkWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
beaglescout007 0:3dac1f1bc9e0 266 USB_TEST_ASSERT(blocking);
beaglescout007 0:3dac1f1bc9e0 267 int result = multi_token_out(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 268 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 269 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 270 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 271 }
beaglescout007 0:3dac1f1bc9e0 272 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 273 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 274 }
beaglescout007 0:3dac1f1bc9e0 275
beaglescout007 0:3dac1f1bc9e0 276 USB_TYPE USBHost::interruptRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
beaglescout007 0:3dac1f1bc9e0 277 if (blocking == false) {
beaglescout007 0:3dac1f1bc9e0 278 ep->setBuffer(buf, len);
beaglescout007 0:3dac1f1bc9e0 279 ep_queue.push(ep);
beaglescout007 0:3dac1f1bc9e0 280 multi_token_inNB(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 281 return USB_TYPE_PROCESSING;
beaglescout007 0:3dac1f1bc9e0 282 }
beaglescout007 0:3dac1f1bc9e0 283 int result = multi_token_in(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 284 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 285 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 286 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 287 }
beaglescout007 0:3dac1f1bc9e0 288 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 289 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 290 }
beaglescout007 0:3dac1f1bc9e0 291
beaglescout007 0:3dac1f1bc9e0 292 USB_TYPE USBHost::interruptWrite(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
beaglescout007 0:3dac1f1bc9e0 293 USB_TEST_ASSERT(blocking);
beaglescout007 0:3dac1f1bc9e0 294 int result = multi_token_out(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 295 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 296 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 297 return USB_TYPE_ERROR;
beaglescout007 0:3dac1f1bc9e0 298 }
beaglescout007 0:3dac1f1bc9e0 299 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 300 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 301 }
beaglescout007 0:3dac1f1bc9e0 302
beaglescout007 0:3dac1f1bc9e0 303 USB_TYPE USBHost::isochronousRead(USBDeviceConnected* dev, USBEndpoint* ep, uint8_t* buf, uint32_t len, bool blocking) {
beaglescout007 0:3dac1f1bc9e0 304 USB_TEST_ASSERT(blocking);
beaglescout007 0:3dac1f1bc9e0 305 isochronousReadNB(ep, buf, len);
beaglescout007 0:3dac1f1bc9e0 306 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 307 }
beaglescout007 0:3dac1f1bc9e0 308
beaglescout007 0:3dac1f1bc9e0 309 int USBHost::interruptReadNB(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 310 USB_TRACE1(size);
beaglescout007 0:3dac1f1bc9e0 311 if (ep->getState() != USB_TYPE_PROCESSING) {
beaglescout007 0:3dac1f1bc9e0 312 ep->setState(USB_TYPE_PROCESSING);
beaglescout007 0:3dac1f1bc9e0 313 ep->setBuffer(data, size);
beaglescout007 0:3dac1f1bc9e0 314 multi_token_inNB(ep, data, size);
beaglescout007 0:3dac1f1bc9e0 315 }
beaglescout007 0:3dac1f1bc9e0 316 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) {
beaglescout007 0:3dac1f1bc9e0 317 return ep->getLengthTransferred();
beaglescout007 0:3dac1f1bc9e0 318 }
beaglescout007 0:3dac1f1bc9e0 319 return -1;
beaglescout007 0:3dac1f1bc9e0 320 }
beaglescout007 0:3dac1f1bc9e0 321
beaglescout007 0:3dac1f1bc9e0 322 int USBHost::bulkReadNB(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 323 USB_TRACE1(size);
beaglescout007 0:3dac1f1bc9e0 324 return interruptReadNB(ep, data, size);
beaglescout007 0:3dac1f1bc9e0 325 }
beaglescout007 0:3dac1f1bc9e0 326
beaglescout007 0:3dac1f1bc9e0 327 int USBHost::isochronousReadNB(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 328 USB_TRACE1(size);
beaglescout007 0:3dac1f1bc9e0 329 int result = token_iso_in(ep, data, size);
beaglescout007 0:3dac1f1bc9e0 330 if (result >= 0) {
beaglescout007 0:3dac1f1bc9e0 331 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 332 }
beaglescout007 0:3dac1f1bc9e0 333 return result;
beaglescout007 0:3dac1f1bc9e0 334 }
beaglescout007 0:3dac1f1bc9e0 335
beaglescout007 0:3dac1f1bc9e0 336 void USBHost::task() {
beaglescout007 0:3dac1f1bc9e0 337 USBEndpoint* ep = ep_queue.pop();
beaglescout007 0:3dac1f1bc9e0 338 if (ep) {
beaglescout007 0:3dac1f1bc9e0 339 USB_TEST_ASSERT(ep->getDir() == IN);
beaglescout007 0:3dac1f1bc9e0 340 if (multi_token_inNB_result(ep) != USB_TYPE_PROCESSING) {
beaglescout007 0:3dac1f1bc9e0 341 ep->call();
beaglescout007 0:3dac1f1bc9e0 342 } else {
beaglescout007 0:3dac1f1bc9e0 343 ep_queue.push(ep);
beaglescout007 0:3dac1f1bc9e0 344 }
beaglescout007 0:3dac1f1bc9e0 345 }
beaglescout007 0:3dac1f1bc9e0 346 }
beaglescout007 0:3dac1f1bc9e0 347
beaglescout007 0:3dac1f1bc9e0 348 void usb_test_assert_internal(const char *expr, const char *file, int line){
beaglescout007 0:3dac1f1bc9e0 349 error("\n\n%s@%d %s ASSERT!\n\n", file, line, expr);
beaglescout007 0:3dac1f1bc9e0 350 }
beaglescout007 0:3dac1f1bc9e0 351
beaglescout007 0:3dac1f1bc9e0 352