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 #if defined(TARGET_NUCLEO_F401RE)||defined(TARGET_NUCLEO_F411RE)||defined(TARGET_NUCLEO_F446RE)
beaglescout007 0:3dac1f1bc9e0 2 #include "USBHALHost.h"
beaglescout007 0:3dac1f1bc9e0 3 #include <algorithm>
beaglescout007 0:3dac1f1bc9e0 4
beaglescout007 0:3dac1f1bc9e0 5 #ifdef _USB_DBG
beaglescout007 0:3dac1f1bc9e0 6 extern RawSerial pc;
beaglescout007 0:3dac1f1bc9e0 7 //RawSerial pc(USBTX,USBRX);
beaglescout007 0:3dac1f1bc9e0 8 #include "mydebug.h"
beaglescout007 0:3dac1f1bc9e0 9 #define USB_DBG(...) do{pc.printf("[%s@%d] ",__PRETTY_FUNCTION__,__LINE__);pc.printf(__VA_ARGS__);pc.puts("\n");} while(0);
beaglescout007 0:3dac1f1bc9e0 10 #define USB_DBG_HEX(A,B) debug_hex<RawSerial>(pc,A,B)
beaglescout007 0:3dac1f1bc9e0 11
beaglescout007 0:3dac1f1bc9e0 12 #else
beaglescout007 0:3dac1f1bc9e0 13 #define USB_DBG(...) while(0)
beaglescout007 0:3dac1f1bc9e0 14 #define USB_DBG_HEX(A,B) while(0)
beaglescout007 0:3dac1f1bc9e0 15 #endif
beaglescout007 0:3dac1f1bc9e0 16
beaglescout007 0:3dac1f1bc9e0 17 #undef USB_TEST_ASSERT
beaglescout007 0:3dac1f1bc9e0 18 void usb_test_assert_internal(const char *expr, const char *file, int line);
beaglescout007 0:3dac1f1bc9e0 19 #define USB_TEST_ASSERT(EXPR) while(!(EXPR)){usb_test_assert_internal(#EXPR,__FILE__,__LINE__);}
beaglescout007 0:3dac1f1bc9e0 20
beaglescout007 0:3dac1f1bc9e0 21 #define USB_TRACE1(A) while(0)
beaglescout007 0:3dac1f1bc9e0 22
beaglescout007 0:3dac1f1bc9e0 23 #define USB_INFO(...) do{fprintf(stderr,__VA_ARGS__);fprintf(stderr,"\n");}while(0);
beaglescout007 0:3dac1f1bc9e0 24
beaglescout007 0:3dac1f1bc9e0 25 __IO bool attach_done = false;
beaglescout007 0:3dac1f1bc9e0 26
beaglescout007 0:3dac1f1bc9e0 27 void delay_ms(uint32_t t)
beaglescout007 0:3dac1f1bc9e0 28 {
beaglescout007 0:3dac1f1bc9e0 29 HAL_Delay(t);
beaglescout007 0:3dac1f1bc9e0 30 }
beaglescout007 0:3dac1f1bc9e0 31
beaglescout007 0:3dac1f1bc9e0 32 // usbh_conf.c
beaglescout007 0:3dac1f1bc9e0 33 extern HCD_HandleTypeDef hhcd_USB_OTG_FS;
beaglescout007 0:3dac1f1bc9e0 34
beaglescout007 0:3dac1f1bc9e0 35 void HAL_HCD_MspInit(HCD_HandleTypeDef* hhcd)
beaglescout007 0:3dac1f1bc9e0 36 {
beaglescout007 0:3dac1f1bc9e0 37 GPIO_InitTypeDef GPIO_InitStruct;
beaglescout007 0:3dac1f1bc9e0 38 if(hhcd->Instance==USB_OTG_FS)
beaglescout007 0:3dac1f1bc9e0 39 {
beaglescout007 0:3dac1f1bc9e0 40 /* Peripheral clock enable */
beaglescout007 0:3dac1f1bc9e0 41 __USB_OTG_FS_CLK_ENABLE();
beaglescout007 0:3dac1f1bc9e0 42
beaglescout007 0:3dac1f1bc9e0 43 /**USB_OTG_FS GPIO Configuration
beaglescout007 0:3dac1f1bc9e0 44 PA11 ------> USB_OTG_FS_DM
beaglescout007 0:3dac1f1bc9e0 45 PA12 ------> USB_OTG_FS_DP
beaglescout007 0:3dac1f1bc9e0 46 */
beaglescout007 0:3dac1f1bc9e0 47 GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
beaglescout007 0:3dac1f1bc9e0 48 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
beaglescout007 0:3dac1f1bc9e0 49 GPIO_InitStruct.Pull = GPIO_NOPULL;
beaglescout007 0:3dac1f1bc9e0 50 GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
beaglescout007 0:3dac1f1bc9e0 51 GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
beaglescout007 0:3dac1f1bc9e0 52 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
beaglescout007 0:3dac1f1bc9e0 53
beaglescout007 0:3dac1f1bc9e0 54 /* Peripheral interrupt init*/
beaglescout007 0:3dac1f1bc9e0 55 /* Sets the priority grouping field */
beaglescout007 0:3dac1f1bc9e0 56 HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_0);
beaglescout007 0:3dac1f1bc9e0 57 HAL_NVIC_SetPriority(OTG_FS_IRQn, 0, 0);
beaglescout007 0:3dac1f1bc9e0 58 HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
beaglescout007 0:3dac1f1bc9e0 59 }
beaglescout007 0:3dac1f1bc9e0 60 }
beaglescout007 0:3dac1f1bc9e0 61
beaglescout007 0:3dac1f1bc9e0 62 // stm32f4xx_it.c
beaglescout007 0:3dac1f1bc9e0 63 extern "C" {
beaglescout007 0:3dac1f1bc9e0 64 void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
beaglescout007 0:3dac1f1bc9e0 65 {
beaglescout007 0:3dac1f1bc9e0 66 USB_TRACE1(hhcd);
beaglescout007 0:3dac1f1bc9e0 67 attach_done = true;
beaglescout007 0:3dac1f1bc9e0 68 }
beaglescout007 0:3dac1f1bc9e0 69
beaglescout007 0:3dac1f1bc9e0 70 } // extern "C"
beaglescout007 0:3dac1f1bc9e0 71
beaglescout007 0:3dac1f1bc9e0 72 USBHALHost* USBHALHost::instHost;
beaglescout007 0:3dac1f1bc9e0 73
beaglescout007 0:3dac1f1bc9e0 74 USBHALHost::USBHALHost() {
beaglescout007 0:3dac1f1bc9e0 75 instHost = this;
beaglescout007 0:3dac1f1bc9e0 76 }
beaglescout007 0:3dac1f1bc9e0 77
beaglescout007 0:3dac1f1bc9e0 78 void USBHALHost::init() {
beaglescout007 0:3dac1f1bc9e0 79 hhcd_USB_OTG_FS.Instance = USB_OTG_FS;
beaglescout007 0:3dac1f1bc9e0 80 hhcd_USB_OTG_FS.Init.Host_channels = 8;
beaglescout007 0:3dac1f1bc9e0 81 hhcd_USB_OTG_FS.Init.speed = HCD_SPEED_FULL;
beaglescout007 0:3dac1f1bc9e0 82 hhcd_USB_OTG_FS.Init.dma_enable = DISABLE;
beaglescout007 0:3dac1f1bc9e0 83 hhcd_USB_OTG_FS.Init.phy_itface = HCD_PHY_EMBEDDED;
beaglescout007 0:3dac1f1bc9e0 84 hhcd_USB_OTG_FS.Init.Sof_enable = DISABLE;
beaglescout007 0:3dac1f1bc9e0 85 hhcd_USB_OTG_FS.Init.low_power_enable = ENABLE;
beaglescout007 0:3dac1f1bc9e0 86 hhcd_USB_OTG_FS.Init.vbus_sensing_enable = DISABLE;
beaglescout007 0:3dac1f1bc9e0 87 hhcd_USB_OTG_FS.Init.use_external_vbus = DISABLE;
beaglescout007 0:3dac1f1bc9e0 88
beaglescout007 0:3dac1f1bc9e0 89 HAL_HCD_Init(&hhcd_USB_OTG_FS);
beaglescout007 0:3dac1f1bc9e0 90 HAL_HCD_Start(&hhcd_USB_OTG_FS);
beaglescout007 0:3dac1f1bc9e0 91
beaglescout007 0:3dac1f1bc9e0 92 bool lowSpeed = wait_attach();
beaglescout007 0:3dac1f1bc9e0 93 delay_ms(200);
beaglescout007 0:3dac1f1bc9e0 94 HAL_HCD_ResetPort(&hhcd_USB_OTG_FS);
beaglescout007 0:3dac1f1bc9e0 95 delay_ms(100); // Wait for 100 ms after Reset
beaglescout007 0:3dac1f1bc9e0 96 addDevice(NULL, 0, lowSpeed);
beaglescout007 0:3dac1f1bc9e0 97 }
beaglescout007 0:3dac1f1bc9e0 98
beaglescout007 0:3dac1f1bc9e0 99 bool USBHALHost::wait_attach() {
beaglescout007 0:3dac1f1bc9e0 100 Timer t;
beaglescout007 0:3dac1f1bc9e0 101 t.reset();
beaglescout007 0:3dac1f1bc9e0 102 t.start();
beaglescout007 0:3dac1f1bc9e0 103 while(!attach_done) {
beaglescout007 0:3dac1f1bc9e0 104 if (t.read_ms() > 5*1000) {
beaglescout007 0:3dac1f1bc9e0 105 t.reset();
beaglescout007 0:3dac1f1bc9e0 106 USB_INFO("Please attach USB device.");
beaglescout007 0:3dac1f1bc9e0 107 }
beaglescout007 0:3dac1f1bc9e0 108 }
beaglescout007 0:3dac1f1bc9e0 109 wait_ms(100);
beaglescout007 0:3dac1f1bc9e0 110 return HAL_HCD_GetCurrentSpeed(&hhcd_USB_OTG_FS) == USB_OTG_SPEED_LOW;
beaglescout007 0:3dac1f1bc9e0 111 }
beaglescout007 0:3dac1f1bc9e0 112
beaglescout007 0:3dac1f1bc9e0 113 int USBHALHost::token_setup(USBEndpoint* ep, SETUP_PACKET* setup, uint16_t wLength) {
beaglescout007 0:3dac1f1bc9e0 114 const uint8_t ep_addr = 0x00;
beaglescout007 0:3dac1f1bc9e0 115 HC hc;
beaglescout007 0:3dac1f1bc9e0 116 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 117 hc.Init(ep_addr,
beaglescout007 0:3dac1f1bc9e0 118 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 119 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 120 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 121
beaglescout007 0:3dac1f1bc9e0 122 setup->wLength = wLength;
beaglescout007 0:3dac1f1bc9e0 123 hc.SubmitRequest((uint8_t*)setup, 8, true); // PID_SETUP
beaglescout007 0:3dac1f1bc9e0 124 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 125
beaglescout007 0:3dac1f1bc9e0 126 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 127 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 128 LastStatus = ACK;
beaglescout007 0:3dac1f1bc9e0 129 break;
beaglescout007 0:3dac1f1bc9e0 130 default:
beaglescout007 0:3dac1f1bc9e0 131 LastStatus = 0xff;
beaglescout007 0:3dac1f1bc9e0 132 break;
beaglescout007 0:3dac1f1bc9e0 133 }
beaglescout007 0:3dac1f1bc9e0 134 ep->setData01(DATA1);
beaglescout007 0:3dac1f1bc9e0 135 return 8;
beaglescout007 0:3dac1f1bc9e0 136 }
beaglescout007 0:3dac1f1bc9e0 137
beaglescout007 0:3dac1f1bc9e0 138 int USBHALHost::token_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 139 switch(ep->getType()) {
beaglescout007 0:3dac1f1bc9e0 140 case CONTROL_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 141 return token_ctl_in(ep, data, size, retryLimit);
beaglescout007 0:3dac1f1bc9e0 142 case INTERRUPT_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 143 return token_int_in(ep, data, size);
beaglescout007 0:3dac1f1bc9e0 144 case BULK_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 145 return token_blk_in(ep, data, size, retryLimit);
beaglescout007 0:3dac1f1bc9e0 146 }
beaglescout007 0:3dac1f1bc9e0 147 return -1;
beaglescout007 0:3dac1f1bc9e0 148 }
beaglescout007 0:3dac1f1bc9e0 149
beaglescout007 0:3dac1f1bc9e0 150 int USBHALHost::token_ctl_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 151 const uint8_t ep_addr = 0x80;
beaglescout007 0:3dac1f1bc9e0 152 HC hc;
beaglescout007 0:3dac1f1bc9e0 153 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 154 hc.Init(ep_addr,
beaglescout007 0:3dac1f1bc9e0 155 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 156 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 157 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 158
beaglescout007 0:3dac1f1bc9e0 159 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 160
beaglescout007 0:3dac1f1bc9e0 161 hc.SubmitRequest(data, size);
beaglescout007 0:3dac1f1bc9e0 162 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 163
beaglescout007 0:3dac1f1bc9e0 164 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 165 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 166 LastStatus = ACK;
beaglescout007 0:3dac1f1bc9e0 167 break;
beaglescout007 0:3dac1f1bc9e0 168 default:
beaglescout007 0:3dac1f1bc9e0 169 LastStatus = 0xff;
beaglescout007 0:3dac1f1bc9e0 170 return -1;
beaglescout007 0:3dac1f1bc9e0 171 }
beaglescout007 0:3dac1f1bc9e0 172 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 173 return hc.GetXferCount();
beaglescout007 0:3dac1f1bc9e0 174 }
beaglescout007 0:3dac1f1bc9e0 175
beaglescout007 0:3dac1f1bc9e0 176 int USBHALHost::token_int_in(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 177 HC hc;
beaglescout007 0:3dac1f1bc9e0 178 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 179 hc.Init(
beaglescout007 0:3dac1f1bc9e0 180 ep->getAddress(),
beaglescout007 0:3dac1f1bc9e0 181 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 182 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 183 EP_TYPE_INTR, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 184
beaglescout007 0:3dac1f1bc9e0 185 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 186
beaglescout007 0:3dac1f1bc9e0 187 hc.SubmitRequest(data, size);
beaglescout007 0:3dac1f1bc9e0 188 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 189 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 190 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 191 switch(hc.GetState()) {
beaglescout007 0:3dac1f1bc9e0 192 case HC_XFRC:
beaglescout007 0:3dac1f1bc9e0 193 LastStatus = ep->getData01();
beaglescout007 0:3dac1f1bc9e0 194 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 195 return hc.GetXferCount();
beaglescout007 0:3dac1f1bc9e0 196 case HC_NAK:
beaglescout007 0:3dac1f1bc9e0 197 LastStatus = NAK;
beaglescout007 0:3dac1f1bc9e0 198 return -1;
beaglescout007 0:3dac1f1bc9e0 199 }
beaglescout007 0:3dac1f1bc9e0 200 break;
beaglescout007 0:3dac1f1bc9e0 201 }
beaglescout007 0:3dac1f1bc9e0 202 LastStatus = STALL;
beaglescout007 0:3dac1f1bc9e0 203 return -1;
beaglescout007 0:3dac1f1bc9e0 204 }
beaglescout007 0:3dac1f1bc9e0 205
beaglescout007 0:3dac1f1bc9e0 206 int USBHALHost::token_blk_in(USBEndpoint* ep, uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 207 HC hc;
beaglescout007 0:3dac1f1bc9e0 208 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 209 hc.Init(
beaglescout007 0:3dac1f1bc9e0 210 ep->getAddress(),
beaglescout007 0:3dac1f1bc9e0 211 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 212 HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 213 EP_TYPE_BULK, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 214
beaglescout007 0:3dac1f1bc9e0 215 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 216
beaglescout007 0:3dac1f1bc9e0 217 int retry = 0;
beaglescout007 0:3dac1f1bc9e0 218 do {
beaglescout007 0:3dac1f1bc9e0 219 hc.SubmitRequest(data, size);
beaglescout007 0:3dac1f1bc9e0 220 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 221
beaglescout007 0:3dac1f1bc9e0 222 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 223 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 224 switch(hc.GetState()) {
beaglescout007 0:3dac1f1bc9e0 225 case HC_XFRC:
beaglescout007 0:3dac1f1bc9e0 226 LastStatus = ep->getData01();
beaglescout007 0:3dac1f1bc9e0 227 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 228 return hc.GetXferCount();
beaglescout007 0:3dac1f1bc9e0 229 case HC_NAK:
beaglescout007 0:3dac1f1bc9e0 230 LastStatus = NAK;
beaglescout007 0:3dac1f1bc9e0 231 if (retryLimit > 0) {
beaglescout007 0:3dac1f1bc9e0 232 delay_ms(1 + 10 * retry);
beaglescout007 0:3dac1f1bc9e0 233 }
beaglescout007 0:3dac1f1bc9e0 234 break;
beaglescout007 0:3dac1f1bc9e0 235 default:
beaglescout007 0:3dac1f1bc9e0 236 break;
beaglescout007 0:3dac1f1bc9e0 237 }
beaglescout007 0:3dac1f1bc9e0 238 break;
beaglescout007 0:3dac1f1bc9e0 239 case URB_STALL:
beaglescout007 0:3dac1f1bc9e0 240 LastStatus = STALL;
beaglescout007 0:3dac1f1bc9e0 241 return -1;
beaglescout007 0:3dac1f1bc9e0 242 default:
beaglescout007 0:3dac1f1bc9e0 243 LastStatus = STALL;
beaglescout007 0:3dac1f1bc9e0 244 delay_ms(500 + 100 * retry);
beaglescout007 0:3dac1f1bc9e0 245 break;
beaglescout007 0:3dac1f1bc9e0 246 }
beaglescout007 0:3dac1f1bc9e0 247 }while(retry++ < retryLimit);
beaglescout007 0:3dac1f1bc9e0 248 return -1;
beaglescout007 0:3dac1f1bc9e0 249 }
beaglescout007 0:3dac1f1bc9e0 250
beaglescout007 0:3dac1f1bc9e0 251 int USBHALHost::token_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 252 switch(ep->getType()) {
beaglescout007 0:3dac1f1bc9e0 253 case CONTROL_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 254 return token_ctl_out(ep, data, size, retryLimit);
beaglescout007 0:3dac1f1bc9e0 255 case INTERRUPT_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 256 return token_int_out(ep, data, size);
beaglescout007 0:3dac1f1bc9e0 257 case BULK_ENDPOINT:
beaglescout007 0:3dac1f1bc9e0 258 return token_blk_out(ep, data, size, retryLimit);
beaglescout007 0:3dac1f1bc9e0 259 }
beaglescout007 0:3dac1f1bc9e0 260 return -1;
beaglescout007 0:3dac1f1bc9e0 261 }
beaglescout007 0:3dac1f1bc9e0 262
beaglescout007 0:3dac1f1bc9e0 263 int USBHALHost::token_ctl_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 264 const uint8_t ep_addr = 0x00;
beaglescout007 0:3dac1f1bc9e0 265 HC hc;
beaglescout007 0:3dac1f1bc9e0 266 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 267 hc.Init(ep_addr,
beaglescout007 0:3dac1f1bc9e0 268 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 269 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 270 EP_TYPE_CTRL, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 271
beaglescout007 0:3dac1f1bc9e0 272 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 273
beaglescout007 0:3dac1f1bc9e0 274 do {
beaglescout007 0:3dac1f1bc9e0 275 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:3dac1f1bc9e0 276 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 277
beaglescout007 0:3dac1f1bc9e0 278 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 279 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 280 LastStatus = ACK;
beaglescout007 0:3dac1f1bc9e0 281 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 282 return size;
beaglescout007 0:3dac1f1bc9e0 283
beaglescout007 0:3dac1f1bc9e0 284 default:
beaglescout007 0:3dac1f1bc9e0 285 break;
beaglescout007 0:3dac1f1bc9e0 286 }
beaglescout007 0:3dac1f1bc9e0 287 delay_ms(1);
beaglescout007 0:3dac1f1bc9e0 288 }while(retryLimit-- > 0);
beaglescout007 0:3dac1f1bc9e0 289 return -1;
beaglescout007 0:3dac1f1bc9e0 290 }
beaglescout007 0:3dac1f1bc9e0 291
beaglescout007 0:3dac1f1bc9e0 292 int USBHALHost::token_int_out(USBEndpoint* ep, const uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 293 HC hc;
beaglescout007 0:3dac1f1bc9e0 294 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 295 hc.Init(
beaglescout007 0:3dac1f1bc9e0 296 ep->getAddress(),
beaglescout007 0:3dac1f1bc9e0 297 dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 298 dev->getSpeed() ? HCD_SPEED_LOW : HCD_SPEED_FULL,
beaglescout007 0:3dac1f1bc9e0 299 EP_TYPE_INTR, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 300
beaglescout007 0:3dac1f1bc9e0 301 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 302
beaglescout007 0:3dac1f1bc9e0 303 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:3dac1f1bc9e0 304 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 305 if (hc.GetURBState() != URB_DONE) {
beaglescout007 0:3dac1f1bc9e0 306 return -1;
beaglescout007 0:3dac1f1bc9e0 307 }
beaglescout007 0:3dac1f1bc9e0 308 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 309 return size;
beaglescout007 0:3dac1f1bc9e0 310 }
beaglescout007 0:3dac1f1bc9e0 311
beaglescout007 0:3dac1f1bc9e0 312 int USBHALHost::token_blk_out(USBEndpoint* ep, const uint8_t* data, int size, int retryLimit) {
beaglescout007 0:3dac1f1bc9e0 313 HC hc;
beaglescout007 0:3dac1f1bc9e0 314 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 315 hc.Init(
beaglescout007 0:3dac1f1bc9e0 316 ep->getAddress(), dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 317 HCD_SPEED_FULL, EP_TYPE_BULK, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 318
beaglescout007 0:3dac1f1bc9e0 319 hc.SetToggle((ep->getData01() == DATA0) ? 0 : 1);
beaglescout007 0:3dac1f1bc9e0 320
beaglescout007 0:3dac1f1bc9e0 321 int retry = 0;
beaglescout007 0:3dac1f1bc9e0 322 do {
beaglescout007 0:3dac1f1bc9e0 323 hc.SubmitRequest((uint8_t*)data, size);
beaglescout007 0:3dac1f1bc9e0 324 while(hc.GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 325
beaglescout007 0:3dac1f1bc9e0 326 switch(hc.GetURBState()) {
beaglescout007 0:3dac1f1bc9e0 327 case URB_DONE:
beaglescout007 0:3dac1f1bc9e0 328 switch(hc.GetState()) {
beaglescout007 0:3dac1f1bc9e0 329 case HC_XFRC: // ACK
beaglescout007 0:3dac1f1bc9e0 330 LastStatus = ep->getData01();
beaglescout007 0:3dac1f1bc9e0 331 ep->toggleData01();
beaglescout007 0:3dac1f1bc9e0 332 return size;
beaglescout007 0:3dac1f1bc9e0 333 default:
beaglescout007 0:3dac1f1bc9e0 334 break;
beaglescout007 0:3dac1f1bc9e0 335 }
beaglescout007 0:3dac1f1bc9e0 336 break;
beaglescout007 0:3dac1f1bc9e0 337 case URB_NOTREADY: // HC_NAK
beaglescout007 0:3dac1f1bc9e0 338 LastStatus = NAK;
beaglescout007 0:3dac1f1bc9e0 339 delay_ms(100 * retry);
beaglescout007 0:3dac1f1bc9e0 340 break;
beaglescout007 0:3dac1f1bc9e0 341 default:
beaglescout007 0:3dac1f1bc9e0 342 LastStatus = STALL;
beaglescout007 0:3dac1f1bc9e0 343 return -1;
beaglescout007 0:3dac1f1bc9e0 344 }
beaglescout007 0:3dac1f1bc9e0 345 } while(retry++ < retryLimit);
beaglescout007 0:3dac1f1bc9e0 346 return -1;
beaglescout007 0:3dac1f1bc9e0 347 }
beaglescout007 0:3dac1f1bc9e0 348
beaglescout007 0:3dac1f1bc9e0 349 int USBHALHost::token_iso_in(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 350 HC* hc = ep->getHALData<HC*>();
beaglescout007 0:3dac1f1bc9e0 351 if (hc == NULL) {
beaglescout007 0:3dac1f1bc9e0 352 hc = new HC;
beaglescout007 0:3dac1f1bc9e0 353 ep->setHALData<HC*>(hc);
beaglescout007 0:3dac1f1bc9e0 354 USBDeviceConnected* dev = ep->getDevice();
beaglescout007 0:3dac1f1bc9e0 355 hc->Init(
beaglescout007 0:3dac1f1bc9e0 356 ep->getAddress(), dev->getAddress(),
beaglescout007 0:3dac1f1bc9e0 357 HCD_SPEED_FULL, EP_TYPE_ISOC, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 358 }
beaglescout007 0:3dac1f1bc9e0 359 hc->SubmitRequest(data, size);
beaglescout007 0:3dac1f1bc9e0 360 while(hc->GetURBState() == URB_IDLE);
beaglescout007 0:3dac1f1bc9e0 361 return hc->GetXferCount();
beaglescout007 0:3dac1f1bc9e0 362 }
beaglescout007 0:3dac1f1bc9e0 363
beaglescout007 0:3dac1f1bc9e0 364 int USBHALHost::multi_token_in(USBEndpoint* ep, uint8_t* data, size_t total, bool block) {
beaglescout007 0:3dac1f1bc9e0 365 if (total == 0) {
beaglescout007 0:3dac1f1bc9e0 366 return token_in(ep);
beaglescout007 0:3dac1f1bc9e0 367 }
beaglescout007 0:3dac1f1bc9e0 368 int retryLimit = block ? 10 : 0;
beaglescout007 0:3dac1f1bc9e0 369 int read_len = 0;
beaglescout007 0:3dac1f1bc9e0 370 for(int n = 0; read_len < total; n++) {
beaglescout007 0:3dac1f1bc9e0 371 int size = std::min((int)total-read_len, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 372 int result = token_in(ep, data+read_len, size, retryLimit);
beaglescout007 0:3dac1f1bc9e0 373 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 374 if (block) {
beaglescout007 0:3dac1f1bc9e0 375 return -1;
beaglescout007 0:3dac1f1bc9e0 376 }
beaglescout007 0:3dac1f1bc9e0 377 if (LastStatus == NAK) {
beaglescout007 0:3dac1f1bc9e0 378 if (n == 0) {
beaglescout007 0:3dac1f1bc9e0 379 return -1;
beaglescout007 0:3dac1f1bc9e0 380 }
beaglescout007 0:3dac1f1bc9e0 381 break;
beaglescout007 0:3dac1f1bc9e0 382 }
beaglescout007 0:3dac1f1bc9e0 383 return result;
beaglescout007 0:3dac1f1bc9e0 384 }
beaglescout007 0:3dac1f1bc9e0 385 read_len += result;
beaglescout007 0:3dac1f1bc9e0 386 if (result < ep->getSize()) {
beaglescout007 0:3dac1f1bc9e0 387 break;
beaglescout007 0:3dac1f1bc9e0 388 }
beaglescout007 0:3dac1f1bc9e0 389 }
beaglescout007 0:3dac1f1bc9e0 390 return read_len;
beaglescout007 0:3dac1f1bc9e0 391 }
beaglescout007 0:3dac1f1bc9e0 392
beaglescout007 0:3dac1f1bc9e0 393 int USBHALHost::multi_token_out(USBEndpoint* ep, const uint8_t* data, size_t total) {
beaglescout007 0:3dac1f1bc9e0 394 if (total == 0) {
beaglescout007 0:3dac1f1bc9e0 395 return token_out(ep);
beaglescout007 0:3dac1f1bc9e0 396 }
beaglescout007 0:3dac1f1bc9e0 397 int write_len = 0;
beaglescout007 0:3dac1f1bc9e0 398 for(int n = 0; write_len < total; n++) {
beaglescout007 0:3dac1f1bc9e0 399 int size = std::min((int)total-write_len, ep->getSize());
beaglescout007 0:3dac1f1bc9e0 400 int result = token_out(ep, data+write_len, size);
beaglescout007 0:3dac1f1bc9e0 401 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 402 if (LastStatus == NAK) {
beaglescout007 0:3dac1f1bc9e0 403 if (n == 0) {
beaglescout007 0:3dac1f1bc9e0 404 return -1;
beaglescout007 0:3dac1f1bc9e0 405 }
beaglescout007 0:3dac1f1bc9e0 406 break;
beaglescout007 0:3dac1f1bc9e0 407 }
beaglescout007 0:3dac1f1bc9e0 408 USB_DBG("token_out result=%d %02x", result, LastStatus);
beaglescout007 0:3dac1f1bc9e0 409 return result;
beaglescout007 0:3dac1f1bc9e0 410 }
beaglescout007 0:3dac1f1bc9e0 411 write_len += result;
beaglescout007 0:3dac1f1bc9e0 412 if (result < ep->getSize()) {
beaglescout007 0:3dac1f1bc9e0 413 break;
beaglescout007 0:3dac1f1bc9e0 414 }
beaglescout007 0:3dac1f1bc9e0 415 }
beaglescout007 0:3dac1f1bc9e0 416 return write_len;
beaglescout007 0:3dac1f1bc9e0 417 }
beaglescout007 0:3dac1f1bc9e0 418 void USBHALHost::multi_token_inNB(USBEndpoint* ep, uint8_t* data, int size) {
beaglescout007 0:3dac1f1bc9e0 419 USB_TRACE1(size);
beaglescout007 0:3dac1f1bc9e0 420 USB_TEST_ASSERT(ep->getState() != USB_TYPE_PROCESSING);
beaglescout007 0:3dac1f1bc9e0 421 ep->setBuffer(data, size);
beaglescout007 0:3dac1f1bc9e0 422 ep->setState(USB_TYPE_PROCESSING);
beaglescout007 0:3dac1f1bc9e0 423 }
beaglescout007 0:3dac1f1bc9e0 424
beaglescout007 0:3dac1f1bc9e0 425 USB_TYPE USBHALHost::multi_token_inNB_result(USBEndpoint* ep) {
beaglescout007 0:3dac1f1bc9e0 426 USB_TEST_ASSERT(ep->getState() == USB_TYPE_PROCESSING);
beaglescout007 0:3dac1f1bc9e0 427 uint8_t* buf = ep->getBufStart();
beaglescout007 0:3dac1f1bc9e0 428 int size = ep->getBufSize();
beaglescout007 0:3dac1f1bc9e0 429 int result = multi_token_in(ep, buf, size, false);
beaglescout007 0:3dac1f1bc9e0 430 USB_TRACE1(result);
beaglescout007 0:3dac1f1bc9e0 431 if (result < 0) {
beaglescout007 0:3dac1f1bc9e0 432 return USB_TYPE_PROCESSING;
beaglescout007 0:3dac1f1bc9e0 433 }
beaglescout007 0:3dac1f1bc9e0 434 ep->setLengthTransferred(result);
beaglescout007 0:3dac1f1bc9e0 435 ep->setState(USB_TYPE_IDLE);
beaglescout007 0:3dac1f1bc9e0 436 return USB_TYPE_OK;
beaglescout007 0:3dac1f1bc9e0 437
beaglescout007 0:3dac1f1bc9e0 438 }
beaglescout007 0:3dac1f1bc9e0 439
beaglescout007 0:3dac1f1bc9e0 440 void USBHALHost::setToggle(USBEndpoint* ep, uint8_t toggle) {
beaglescout007 0:3dac1f1bc9e0 441 USB_TEST_ASSERT(toggle == 1);
beaglescout007 0:3dac1f1bc9e0 442 ep->setData01(toggle == 0 ? DATA0 : DATA1);
beaglescout007 0:3dac1f1bc9e0 443 }
beaglescout007 0:3dac1f1bc9e0 444
beaglescout007 0:3dac1f1bc9e0 445 uint8_t HC::slot = 0x00;
beaglescout007 0:3dac1f1bc9e0 446
beaglescout007 0:3dac1f1bc9e0 447 HC::HC() {
beaglescout007 0:3dac1f1bc9e0 448 static const int start = 1;
beaglescout007 0:3dac1f1bc9e0 449 uint8_t mask = (1<<start);
beaglescout007 0:3dac1f1bc9e0 450 for(int i = start; i < 8; i++, mask <<= 1) {
beaglescout007 0:3dac1f1bc9e0 451 if (!(slot & mask)) {
beaglescout007 0:3dac1f1bc9e0 452 slot |= mask;
beaglescout007 0:3dac1f1bc9e0 453 _ch = i;
beaglescout007 0:3dac1f1bc9e0 454 return;
beaglescout007 0:3dac1f1bc9e0 455 }
beaglescout007 0:3dac1f1bc9e0 456 }
beaglescout007 0:3dac1f1bc9e0 457 _ch = 0; // ERROR!!!
beaglescout007 0:3dac1f1bc9e0 458 }
beaglescout007 0:3dac1f1bc9e0 459
beaglescout007 0:3dac1f1bc9e0 460 HC::HC(int ch) {
beaglescout007 0:3dac1f1bc9e0 461 _ch = ch;
beaglescout007 0:3dac1f1bc9e0 462 slot |= (1<<_ch);
beaglescout007 0:3dac1f1bc9e0 463 }
beaglescout007 0:3dac1f1bc9e0 464
beaglescout007 0:3dac1f1bc9e0 465 HC::~HC() {
beaglescout007 0:3dac1f1bc9e0 466 slot &= ~(1<<_ch);
beaglescout007 0:3dac1f1bc9e0 467 }
beaglescout007 0:3dac1f1bc9e0 468
beaglescout007 0:3dac1f1bc9e0 469 HAL_StatusTypeDef HC::Init(uint8_t epnum, uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps) {
beaglescout007 0:3dac1f1bc9e0 470 _ep_addr = epnum;
beaglescout007 0:3dac1f1bc9e0 471 _ep_type = ep_type;
beaglescout007 0:3dac1f1bc9e0 472 return HAL_HCD_HC_Init(&hhcd_USB_OTG_FS, _ch,
beaglescout007 0:3dac1f1bc9e0 473 epnum, dev_address, speed, ep_type, mps);
beaglescout007 0:3dac1f1bc9e0 474 }
beaglescout007 0:3dac1f1bc9e0 475
beaglescout007 0:3dac1f1bc9e0 476 HAL_StatusTypeDef HC::SubmitRequest(uint8_t* pbuff, uint16_t length, bool setup) {
beaglescout007 0:3dac1f1bc9e0 477 uint8_t direction = (_ep_addr & 0x80) ? DIR_IN : DIR_OUT;
beaglescout007 0:3dac1f1bc9e0 478 if (_ep_type == EP_TYPE_CTRL) {
beaglescout007 0:3dac1f1bc9e0 479 HCD_HCTypeDef* hc = &hhcd_USB_OTG_FS.hc[_ch];
beaglescout007 0:3dac1f1bc9e0 480 if (setup) {
beaglescout007 0:3dac1f1bc9e0 481 hc->data_pid = HC_PID_SETUP;
beaglescout007 0:3dac1f1bc9e0 482 hc->toggle_out = 0;
beaglescout007 0:3dac1f1bc9e0 483 } else {
beaglescout007 0:3dac1f1bc9e0 484 if (direction == DIR_IN) {
beaglescout007 0:3dac1f1bc9e0 485 if (hc->toggle_in == 0) {
beaglescout007 0:3dac1f1bc9e0 486 hc->data_pid = HC_PID_DATA0;
beaglescout007 0:3dac1f1bc9e0 487 } else {
beaglescout007 0:3dac1f1bc9e0 488 hc->data_pid = HC_PID_DATA1;
beaglescout007 0:3dac1f1bc9e0 489 }
beaglescout007 0:3dac1f1bc9e0 490 } else { // OUT
beaglescout007 0:3dac1f1bc9e0 491 if (hc->toggle_out == 0) {
beaglescout007 0:3dac1f1bc9e0 492 hc->data_pid = HC_PID_DATA0;
beaglescout007 0:3dac1f1bc9e0 493 } else {
beaglescout007 0:3dac1f1bc9e0 494 hc->data_pid = HC_PID_DATA1;
beaglescout007 0:3dac1f1bc9e0 495 }
beaglescout007 0:3dac1f1bc9e0 496 }
beaglescout007 0:3dac1f1bc9e0 497 }
beaglescout007 0:3dac1f1bc9e0 498 hc->xfer_buff = pbuff;
beaglescout007 0:3dac1f1bc9e0 499 hc->xfer_len = length;
beaglescout007 0:3dac1f1bc9e0 500 hc->urb_state = URB_IDLE;
beaglescout007 0:3dac1f1bc9e0 501 hc->xfer_count = 0;
beaglescout007 0:3dac1f1bc9e0 502 hc->ch_num = _ch;
beaglescout007 0:3dac1f1bc9e0 503 hc->state = HC_IDLE;
beaglescout007 0:3dac1f1bc9e0 504
beaglescout007 0:3dac1f1bc9e0 505 return USB_HC_StartXfer(hhcd_USB_OTG_FS.Instance, hc, 0);
beaglescout007 0:3dac1f1bc9e0 506 }
beaglescout007 0:3dac1f1bc9e0 507 return HAL_HCD_HC_SubmitRequest(&hhcd_USB_OTG_FS, _ch,
beaglescout007 0:3dac1f1bc9e0 508 direction, _ep_type, 0, pbuff, length, 0);
beaglescout007 0:3dac1f1bc9e0 509 }
beaglescout007 0:3dac1f1bc9e0 510
beaglescout007 0:3dac1f1bc9e0 511 HCD_URBStateTypeDef HC::GetURBState() {
beaglescout007 0:3dac1f1bc9e0 512 return HAL_HCD_HC_GetURBState(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:3dac1f1bc9e0 513 }
beaglescout007 0:3dac1f1bc9e0 514
beaglescout007 0:3dac1f1bc9e0 515 HCD_HCStateTypeDef HC::GetState() {
beaglescout007 0:3dac1f1bc9e0 516 return HAL_HCD_HC_GetState(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:3dac1f1bc9e0 517 }
beaglescout007 0:3dac1f1bc9e0 518
beaglescout007 0:3dac1f1bc9e0 519 uint32_t HC::GetXferCount() {
beaglescout007 0:3dac1f1bc9e0 520 return HAL_HCD_HC_GetXferCount(&hhcd_USB_OTG_FS, _ch);
beaglescout007 0:3dac1f1bc9e0 521 }
beaglescout007 0:3dac1f1bc9e0 522
beaglescout007 0:3dac1f1bc9e0 523 void HC::SetToggle(uint8_t toggle) {
beaglescout007 0:3dac1f1bc9e0 524 if (_ep_addr & 0x80) { // IN
beaglescout007 0:3dac1f1bc9e0 525 hhcd_USB_OTG_FS.hc[_ch].toggle_in = toggle;
beaglescout007 0:3dac1f1bc9e0 526 } else { // OUT
beaglescout007 0:3dac1f1bc9e0 527 hhcd_USB_OTG_FS.hc[_ch].toggle_out = toggle;
beaglescout007 0:3dac1f1bc9e0 528 }
beaglescout007 0:3dac1f1bc9e0 529 }
beaglescout007 0:3dac1f1bc9e0 530
beaglescout007 0:3dac1f1bc9e0 531 #endif
beaglescout007 0:3dac1f1bc9e0 532
beaglescout007 0:3dac1f1bc9e0 533
beaglescout007 0:3dac1f1bc9e0 534