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 #pragma once
beaglescout007 0:3dac1f1bc9e0 18 #include "FunctionPointer.h"
beaglescout007 0:3dac1f1bc9e0 19 #include "USBHostTypes.h"
beaglescout007 0:3dac1f1bc9e0 20 #include "USBDeviceConnected.h"
beaglescout007 0:3dac1f1bc9e0 21
beaglescout007 0:3dac1f1bc9e0 22 class USBDeviceConnected;
beaglescout007 0:3dac1f1bc9e0 23
beaglescout007 0:3dac1f1bc9e0 24 /**
beaglescout007 0:3dac1f1bc9e0 25 * USBEndpoint class
beaglescout007 0:3dac1f1bc9e0 26 */
beaglescout007 0:3dac1f1bc9e0 27 class USBEndpoint {
beaglescout007 0:3dac1f1bc9e0 28 public:
beaglescout007 0:3dac1f1bc9e0 29 /**
beaglescout007 0:3dac1f1bc9e0 30 * Constructor
beaglescout007 0:3dac1f1bc9e0 31 */
beaglescout007 0:3dac1f1bc9e0 32 USBEndpoint(USBDeviceConnected* _dev) {
beaglescout007 0:3dac1f1bc9e0 33 init(CONTROL_ENDPOINT, IN, 8, 0);
beaglescout007 0:3dac1f1bc9e0 34 dev = _dev;
beaglescout007 0:3dac1f1bc9e0 35 pData = NULL;
beaglescout007 0:3dac1f1bc9e0 36 }
beaglescout007 0:3dac1f1bc9e0 37
beaglescout007 0:3dac1f1bc9e0 38 /**
beaglescout007 0:3dac1f1bc9e0 39 * Initialize an endpoint
beaglescout007 0:3dac1f1bc9e0 40 *
beaglescout007 0:3dac1f1bc9e0 41 * @param type endpoint type
beaglescout007 0:3dac1f1bc9e0 42 * @param dir endpoint direction
beaglescout007 0:3dac1f1bc9e0 43 * @param size endpoint size
beaglescout007 0:3dac1f1bc9e0 44 * @param ep_number endpoint number
beaglescout007 0:3dac1f1bc9e0 45 */
beaglescout007 0:3dac1f1bc9e0 46 void init(ENDPOINT_TYPE _type, ENDPOINT_DIRECTION _dir, uint32_t size, uint8_t ep_number) {
beaglescout007 0:3dac1f1bc9e0 47 setState(USB_TYPE_FREE);
beaglescout007 0:3dac1f1bc9e0 48 setType(_type);
beaglescout007 0:3dac1f1bc9e0 49 dir = _dir;
beaglescout007 0:3dac1f1bc9e0 50 MaxPacketSize = size;
beaglescout007 0:3dac1f1bc9e0 51 address = ep_number;
beaglescout007 0:3dac1f1bc9e0 52 data01_toggle = DATA0;
beaglescout007 0:3dac1f1bc9e0 53 }
beaglescout007 0:3dac1f1bc9e0 54
beaglescout007 0:3dac1f1bc9e0 55 void ohci_init(uint8_t frameCount, uint8_t queueLimit) {
beaglescout007 0:3dac1f1bc9e0 56 ohci.frameCount = frameCount;
beaglescout007 0:3dac1f1bc9e0 57 ohci.queueLimit = queueLimit;
beaglescout007 0:3dac1f1bc9e0 58 }
beaglescout007 0:3dac1f1bc9e0 59
beaglescout007 0:3dac1f1bc9e0 60 /**
beaglescout007 0:3dac1f1bc9e0 61 * Attach a member function to call when a transfer is finished
beaglescout007 0:3dac1f1bc9e0 62 *
beaglescout007 0:3dac1f1bc9e0 63 * @param tptr pointer to the object to call the member function on
beaglescout007 0:3dac1f1bc9e0 64 * @param mptr pointer to the member function to be called
beaglescout007 0:3dac1f1bc9e0 65 */
beaglescout007 0:3dac1f1bc9e0 66 template<typename T>
beaglescout007 0:3dac1f1bc9e0 67 inline void attach(T* tptr, void (T::*mptr)(void)) {
beaglescout007 0:3dac1f1bc9e0 68 if((mptr != NULL) && (tptr != NULL)) {
beaglescout007 0:3dac1f1bc9e0 69 rx.attach(tptr, mptr);
beaglescout007 0:3dac1f1bc9e0 70 }
beaglescout007 0:3dac1f1bc9e0 71 }
beaglescout007 0:3dac1f1bc9e0 72
beaglescout007 0:3dac1f1bc9e0 73 /**
beaglescout007 0:3dac1f1bc9e0 74 * Attach a callback called when a transfer is finished
beaglescout007 0:3dac1f1bc9e0 75 *
beaglescout007 0:3dac1f1bc9e0 76 * @param fptr function pointer
beaglescout007 0:3dac1f1bc9e0 77 */
beaglescout007 0:3dac1f1bc9e0 78 inline void attach(void (*fptr)(void)) {
beaglescout007 0:3dac1f1bc9e0 79 if(fptr != NULL) {
beaglescout007 0:3dac1f1bc9e0 80 rx.attach(fptr);
beaglescout007 0:3dac1f1bc9e0 81 }
beaglescout007 0:3dac1f1bc9e0 82 }
beaglescout007 0:3dac1f1bc9e0 83
beaglescout007 0:3dac1f1bc9e0 84 /**
beaglescout007 0:3dac1f1bc9e0 85 * Call the handler associted to the end of a transfer
beaglescout007 0:3dac1f1bc9e0 86 */
beaglescout007 0:3dac1f1bc9e0 87 inline void call() {
beaglescout007 0:3dac1f1bc9e0 88 rx.call();
beaglescout007 0:3dac1f1bc9e0 89 };
beaglescout007 0:3dac1f1bc9e0 90
beaglescout007 0:3dac1f1bc9e0 91 void setType(ENDPOINT_TYPE _type) { type = _type; }
beaglescout007 0:3dac1f1bc9e0 92 void setState(USB_TYPE st) { state = st; }
beaglescout007 0:3dac1f1bc9e0 93 void setDevice(USBDeviceConnected* _dev) { dev = _dev; }
beaglescout007 0:3dac1f1bc9e0 94 void setBuffer(uint8_t* buf, int size) { buf_start = buf, buf_size = size; }
beaglescout007 0:3dac1f1bc9e0 95 void setLengthTransferred(int len) { transferred = len; };
beaglescout007 0:3dac1f1bc9e0 96 void setAddress(int addr) { address = addr; }
beaglescout007 0:3dac1f1bc9e0 97 void setSize(int size) { MaxPacketSize = size; }
beaglescout007 0:3dac1f1bc9e0 98 void setData01(uint8_t data01) { data01_toggle = data01; }
beaglescout007 0:3dac1f1bc9e0 99 void setNextEndpoint(USBEndpoint* ep) { nextEp = ep; };
beaglescout007 0:3dac1f1bc9e0 100 template<class T>
beaglescout007 0:3dac1f1bc9e0 101 void setHALData(T data) { pData = data; }
beaglescout007 0:3dac1f1bc9e0 102
beaglescout007 0:3dac1f1bc9e0 103 USBDeviceConnected* getDevice() { return dev; }
beaglescout007 0:3dac1f1bc9e0 104 ENDPOINT_TYPE getType() { return type; };
beaglescout007 0:3dac1f1bc9e0 105 USB_TYPE getState() { return state; }
beaglescout007 0:3dac1f1bc9e0 106 int getLengthTransferred() { return transferred; }
beaglescout007 0:3dac1f1bc9e0 107 uint8_t *getBufStart() { return buf_start; }
beaglescout007 0:3dac1f1bc9e0 108 int getBufSize() { return buf_size; }
beaglescout007 0:3dac1f1bc9e0 109 uint8_t getAddress(){ return address; };
beaglescout007 0:3dac1f1bc9e0 110 int getSize() { return MaxPacketSize; }
beaglescout007 0:3dac1f1bc9e0 111 ENDPOINT_DIRECTION getDir() { return dir; }
beaglescout007 0:3dac1f1bc9e0 112 uint8_t getData01() { return data01_toggle; }
beaglescout007 0:3dac1f1bc9e0 113 void toggleData01() {
beaglescout007 0:3dac1f1bc9e0 114 data01_toggle = (data01_toggle == DATA0) ? DATA1 : DATA0;
beaglescout007 0:3dac1f1bc9e0 115 }
beaglescout007 0:3dac1f1bc9e0 116 USBEndpoint* nextEndpoint() { return nextEp; };
beaglescout007 0:3dac1f1bc9e0 117 template<class T>
beaglescout007 0:3dac1f1bc9e0 118 T getHALData() { return reinterpret_cast<T>(pData); }
beaglescout007 0:3dac1f1bc9e0 119
beaglescout007 0:3dac1f1bc9e0 120 struct {
beaglescout007 0:3dac1f1bc9e0 121 uint8_t queueLimit;
beaglescout007 0:3dac1f1bc9e0 122 uint8_t frameCount; // 1-8
beaglescout007 0:3dac1f1bc9e0 123 } ohci;
beaglescout007 0:3dac1f1bc9e0 124 private:
beaglescout007 0:3dac1f1bc9e0 125 USBEndpoint(){}
beaglescout007 0:3dac1f1bc9e0 126 ENDPOINT_TYPE type;
beaglescout007 0:3dac1f1bc9e0 127 USB_TYPE state;
beaglescout007 0:3dac1f1bc9e0 128 ENDPOINT_DIRECTION dir;
beaglescout007 0:3dac1f1bc9e0 129 USBDeviceConnected* dev;
beaglescout007 0:3dac1f1bc9e0 130 uint8_t data01_toggle; // DATA0,DATA1
beaglescout007 0:3dac1f1bc9e0 131 uint8_t address;
beaglescout007 0:3dac1f1bc9e0 132 int transferred;
beaglescout007 0:3dac1f1bc9e0 133 uint8_t * buf_start;
beaglescout007 0:3dac1f1bc9e0 134 int buf_size;
beaglescout007 0:3dac1f1bc9e0 135 FunctionPointer rx;
beaglescout007 0:3dac1f1bc9e0 136 int MaxPacketSize;
beaglescout007 0:3dac1f1bc9e0 137 USBEndpoint* nextEp;
beaglescout007 0:3dac1f1bc9e0 138 void* pData;
beaglescout007 0:3dac1f1bc9e0 139 };
beaglescout007 0:3dac1f1bc9e0 140
beaglescout007 0:3dac1f1bc9e0 141 class EndpointQueue {
beaglescout007 0:3dac1f1bc9e0 142 public:
beaglescout007 0:3dac1f1bc9e0 143 EndpointQueue():head(NULL),tail(NULL) {}
beaglescout007 0:3dac1f1bc9e0 144 void push(USBEndpoint* ep) {
beaglescout007 0:3dac1f1bc9e0 145 if (head) {
beaglescout007 0:3dac1f1bc9e0 146 tail->setNextEndpoint(ep);
beaglescout007 0:3dac1f1bc9e0 147 } else {
beaglescout007 0:3dac1f1bc9e0 148 head = ep;
beaglescout007 0:3dac1f1bc9e0 149 }
beaglescout007 0:3dac1f1bc9e0 150 tail = ep;
beaglescout007 0:3dac1f1bc9e0 151 ep->setNextEndpoint(NULL);
beaglescout007 0:3dac1f1bc9e0 152 }
beaglescout007 0:3dac1f1bc9e0 153 USBEndpoint* pop() {
beaglescout007 0:3dac1f1bc9e0 154 USBEndpoint* ep = head;
beaglescout007 0:3dac1f1bc9e0 155 if (ep) {
beaglescout007 0:3dac1f1bc9e0 156 head = ep->nextEndpoint();
beaglescout007 0:3dac1f1bc9e0 157 }
beaglescout007 0:3dac1f1bc9e0 158 return ep;
beaglescout007 0:3dac1f1bc9e0 159 }
beaglescout007 0:3dac1f1bc9e0 160 bool empty() { return head == NULL; }
beaglescout007 0:3dac1f1bc9e0 161
beaglescout007 0:3dac1f1bc9e0 162 private:
beaglescout007 0:3dac1f1bc9e0 163 USBEndpoint* head;
beaglescout007 0:3dac1f1bc9e0 164 USBEndpoint* tail;
beaglescout007 0:3dac1f1bc9e0 165 };
beaglescout007 0:3dac1f1bc9e0 166
beaglescout007 0:3dac1f1bc9e0 167
beaglescout007 0:3dac1f1bc9e0 168