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 /*
beaglescout007 0:3dac1f1bc9e0 2 * mbed USBHost Gamepad driver sample
beaglescout007 0:3dac1f1bc9e0 3 * Copyright (c) 2014 Yuuichi Akagawa
beaglescout007 0:3dac1f1bc9e0 4 *
beaglescout007 0:3dac1f1bc9e0 5 * modified from mbed USBHostMouse
beaglescout007 0:3dac1f1bc9e0 6 *
beaglescout007 0:3dac1f1bc9e0 7 * mbed USBHost Library
beaglescout007 0:3dac1f1bc9e0 8 * Copyright (c) 2006-2013 ARM Limited
beaglescout007 0:3dac1f1bc9e0 9 *
beaglescout007 0:3dac1f1bc9e0 10 * Licensed under the Apache License, Version 2.0 (the "License");
beaglescout007 0:3dac1f1bc9e0 11 * you may not use this file except in compliance with the License.
beaglescout007 0:3dac1f1bc9e0 12 * You may obtain a copy of the License at
beaglescout007 0:3dac1f1bc9e0 13 *
beaglescout007 0:3dac1f1bc9e0 14 * http://www.apache.org/licenses/LICENSE-2.0
beaglescout007 0:3dac1f1bc9e0 15 *
beaglescout007 0:3dac1f1bc9e0 16 * Unless required by applicable law or agreed to in writing, software
beaglescout007 0:3dac1f1bc9e0 17 * distributed under the License is distributed on an "AS IS" BASIS,
beaglescout007 0:3dac1f1bc9e0 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
beaglescout007 0:3dac1f1bc9e0 19 * See the License for the specific language governing permissions and
beaglescout007 0:3dac1f1bc9e0 20 * limitations under the License.
beaglescout007 0:3dac1f1bc9e0 21 */
beaglescout007 0:3dac1f1bc9e0 22
beaglescout007 0:3dac1f1bc9e0 23 #include "USBHostGamepad.h"
beaglescout007 0:3dac1f1bc9e0 24 //#if USBHOST_GAMEPAD
beaglescout007 0:3dac1f1bc9e0 25
beaglescout007 0:3dac1f1bc9e0 26 USBHostGamepad::USBHostGamepad() {
beaglescout007 0:3dac1f1bc9e0 27 host = USBHost::getHostInst();
beaglescout007 0:3dac1f1bc9e0 28 init();
beaglescout007 0:3dac1f1bc9e0 29 }
beaglescout007 0:3dac1f1bc9e0 30
beaglescout007 0:3dac1f1bc9e0 31 void USBHostGamepad::init() {
beaglescout007 0:3dac1f1bc9e0 32 dev = NULL;
beaglescout007 0:3dac1f1bc9e0 33 int_in = NULL;
beaglescout007 0:3dac1f1bc9e0 34 dev_connected = false;
beaglescout007 0:3dac1f1bc9e0 35 gamepad_device_found = false;
beaglescout007 0:3dac1f1bc9e0 36 gamepad_intf = -1;
beaglescout007 0:3dac1f1bc9e0 37 }
beaglescout007 0:3dac1f1bc9e0 38
beaglescout007 0:3dac1f1bc9e0 39 bool USBHostGamepad::connected() {
beaglescout007 0:3dac1f1bc9e0 40 return dev_connected;
beaglescout007 0:3dac1f1bc9e0 41 }
beaglescout007 0:3dac1f1bc9e0 42
beaglescout007 0:3dac1f1bc9e0 43 bool USBHostGamepad::connect() {
beaglescout007 0:3dac1f1bc9e0 44 if (dev_connected) {
beaglescout007 0:3dac1f1bc9e0 45 return true;
beaglescout007 0:3dac1f1bc9e0 46 }
beaglescout007 0:3dac1f1bc9e0 47
beaglescout007 0:3dac1f1bc9e0 48 for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
beaglescout007 0:3dac1f1bc9e0 49 if ((dev = host->getDevice(i)) != NULL) {
beaglescout007 0:3dac1f1bc9e0 50
beaglescout007 0:3dac1f1bc9e0 51 if(host->enumerate(dev, this))
beaglescout007 0:3dac1f1bc9e0 52 break;
beaglescout007 0:3dac1f1bc9e0 53
beaglescout007 0:3dac1f1bc9e0 54 if (gamepad_device_found) {
beaglescout007 0:3dac1f1bc9e0 55
beaglescout007 0:3dac1f1bc9e0 56 int_in = dev->getEndpoint(gamepad_intf, INTERRUPT_ENDPOINT, IN);
beaglescout007 0:3dac1f1bc9e0 57 if (!int_in)
beaglescout007 0:3dac1f1bc9e0 58 break;
beaglescout007 0:3dac1f1bc9e0 59
beaglescout007 0:3dac1f1bc9e0 60 USB_INFO("New Gamepad/Joystick device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, gamepad_intf);
beaglescout007 0:3dac1f1bc9e0 61 #if DEBUG > 3
beaglescout007 0:3dac1f1bc9e0 62 //Parse HID Report Descriptor
beaglescout007 0:3dac1f1bc9e0 63 parseHidDescr();
beaglescout007 0:3dac1f1bc9e0 64 #endif
beaglescout007 0:3dac1f1bc9e0 65 dev->setName("Gamepad", gamepad_intf);
beaglescout007 0:3dac1f1bc9e0 66 host->registerDriver(dev, gamepad_intf, this, &USBHostGamepad::init);
beaglescout007 0:3dac1f1bc9e0 67
beaglescout007 0:3dac1f1bc9e0 68 int_in->attach(this, &USBHostGamepad::rxHandler);
beaglescout007 0:3dac1f1bc9e0 69 rxSize = int_in->getSize();
beaglescout007 0:3dac1f1bc9e0 70 if (rxSize > sizeof(report))
beaglescout007 0:3dac1f1bc9e0 71 rxSize = sizeof(report);
beaglescout007 0:3dac1f1bc9e0 72 host->interruptRead(dev, int_in, report, rxSize, false);
beaglescout007 0:3dac1f1bc9e0 73
beaglescout007 0:3dac1f1bc9e0 74 dev_connected = true;
beaglescout007 0:3dac1f1bc9e0 75 return true;
beaglescout007 0:3dac1f1bc9e0 76 }
beaglescout007 0:3dac1f1bc9e0 77 }
beaglescout007 0:3dac1f1bc9e0 78 }
beaglescout007 0:3dac1f1bc9e0 79 init();
beaglescout007 0:3dac1f1bc9e0 80 return false;
beaglescout007 0:3dac1f1bc9e0 81 }
beaglescout007 0:3dac1f1bc9e0 82
beaglescout007 0:3dac1f1bc9e0 83 void USBHostGamepad::rxHandler() {
beaglescout007 0:3dac1f1bc9e0 84 if (dev)
beaglescout007 0:3dac1f1bc9e0 85 host->interruptRead(dev, int_in, report, rxSize, false);
beaglescout007 0:3dac1f1bc9e0 86
beaglescout007 0:3dac1f1bc9e0 87 /* modified 2016 Racoon */
beaglescout007 0:3dac1f1bc9e0 88
beaglescout007 0:3dac1f1bc9e0 89 }
beaglescout007 0:3dac1f1bc9e0 90
beaglescout007 0:3dac1f1bc9e0 91 /*virtual*/ void USBHostGamepad::setVidPid(uint16_t vid, uint16_t pid)
beaglescout007 0:3dac1f1bc9e0 92 {
beaglescout007 0:3dac1f1bc9e0 93 // we don't check VID/PID for gamepad driver
beaglescout007 0:3dac1f1bc9e0 94 }
beaglescout007 0:3dac1f1bc9e0 95
beaglescout007 0:3dac1f1bc9e0 96 /*virtual*/ bool USBHostGamepad::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
beaglescout007 0:3dac1f1bc9e0 97 {
beaglescout007 0:3dac1f1bc9e0 98 if ((gamepad_intf == -1) &&
beaglescout007 0:3dac1f1bc9e0 99 (intf_class == HID_CLASS) &&
beaglescout007 0:3dac1f1bc9e0 100 (intf_subclass == 0x00) &&
beaglescout007 0:3dac1f1bc9e0 101 (intf_protocol == 0x00)) {
beaglescout007 0:3dac1f1bc9e0 102 gamepad_intf = intf_nb;
beaglescout007 0:3dac1f1bc9e0 103 return true;
beaglescout007 0:3dac1f1bc9e0 104 }
beaglescout007 0:3dac1f1bc9e0 105 return false;
beaglescout007 0:3dac1f1bc9e0 106 }
beaglescout007 0:3dac1f1bc9e0 107
beaglescout007 0:3dac1f1bc9e0 108 /*virtual*/ bool USBHostGamepad::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
beaglescout007 0:3dac1f1bc9e0 109 {
beaglescout007 0:3dac1f1bc9e0 110 if (intf_nb == gamepad_intf) {
beaglescout007 0:3dac1f1bc9e0 111 if (type == INTERRUPT_ENDPOINT && dir == IN) {
beaglescout007 0:3dac1f1bc9e0 112 gamepad_device_found = true;
beaglescout007 0:3dac1f1bc9e0 113 return true;
beaglescout007 0:3dac1f1bc9e0 114 }
beaglescout007 0:3dac1f1bc9e0 115 }
beaglescout007 0:3dac1f1bc9e0 116 return false;
beaglescout007 0:3dac1f1bc9e0 117 }
beaglescout007 0:3dac1f1bc9e0 118
beaglescout007 0:3dac1f1bc9e0 119