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 /* */
beaglescout007 0:3dac1f1bc9e0 3 /* spidma.cpp : SPI DMA function */
beaglescout007 0:3dac1f1bc9e0 4 /* */
beaglescout007 0:3dac1f1bc9e0 5 /* 2016/1/20 Racoon */
beaglescout007 0:3dac1f1bc9e0 6 /* */
beaglescout007 0:3dac1f1bc9e0 7 /*===================================================================*/
beaglescout007 0:3dac1f1bc9e0 8
beaglescout007 0:3dac1f1bc9e0 9 #include "mbed.h"
beaglescout007 0:3dac1f1bc9e0 10 #include "stm32f4xx_hal.h"
beaglescout007 0:3dac1f1bc9e0 11
beaglescout007 0:3dac1f1bc9e0 12 SPI_HandleTypeDef SpiHandle;
beaglescout007 0:3dac1f1bc9e0 13
beaglescout007 0:3dac1f1bc9e0 14 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 15 /* callback */
beaglescout007 0:3dac1f1bc9e0 16 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 17 extern "C" {
beaglescout007 0:3dac1f1bc9e0 18 void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
beaglescout007 0:3dac1f1bc9e0 19 {
beaglescout007 0:3dac1f1bc9e0 20 static DMA_HandleTypeDef hdma_tx;
beaglescout007 0:3dac1f1bc9e0 21
beaglescout007 0:3dac1f1bc9e0 22 GPIO_InitTypeDef GPIO_InitStruct;
beaglescout007 0:3dac1f1bc9e0 23
beaglescout007 0:3dac1f1bc9e0 24 __HAL_RCC_GPIOA_CLK_ENABLE();
beaglescout007 0:3dac1f1bc9e0 25 __HAL_RCC_SPI1_CLK_ENABLE();
beaglescout007 0:3dac1f1bc9e0 26 __HAL_RCC_DMA2_CLK_ENABLE();
beaglescout007 0:3dac1f1bc9e0 27
beaglescout007 0:3dac1f1bc9e0 28 GPIO_InitStruct.Pin = GPIO_PIN_5;
beaglescout007 0:3dac1f1bc9e0 29 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
beaglescout007 0:3dac1f1bc9e0 30 GPIO_InitStruct.Pull = GPIO_PULLUP;
beaglescout007 0:3dac1f1bc9e0 31 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
beaglescout007 0:3dac1f1bc9e0 32 GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
beaglescout007 0:3dac1f1bc9e0 33 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
beaglescout007 0:3dac1f1bc9e0 34
beaglescout007 0:3dac1f1bc9e0 35 GPIO_InitStruct.Pin = GPIO_PIN_6;
beaglescout007 0:3dac1f1bc9e0 36 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
beaglescout007 0:3dac1f1bc9e0 37
beaglescout007 0:3dac1f1bc9e0 38 GPIO_InitStruct.Pin = GPIO_PIN_7;
beaglescout007 0:3dac1f1bc9e0 39 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
beaglescout007 0:3dac1f1bc9e0 40
beaglescout007 0:3dac1f1bc9e0 41 hdma_tx.Instance = DMA2_Stream3;
beaglescout007 0:3dac1f1bc9e0 42 hdma_tx.Init.Channel = DMA_CHANNEL_3;
beaglescout007 0:3dac1f1bc9e0 43 hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
beaglescout007 0:3dac1f1bc9e0 44 hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;
beaglescout007 0:3dac1f1bc9e0 45 hdma_tx.Init.MemInc = DMA_MINC_ENABLE;
beaglescout007 0:3dac1f1bc9e0 46 hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
beaglescout007 0:3dac1f1bc9e0 47 hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
beaglescout007 0:3dac1f1bc9e0 48 hdma_tx.Init.Mode = DMA_NORMAL;
beaglescout007 0:3dac1f1bc9e0 49 hdma_tx.Init.Priority = DMA_PRIORITY_HIGH;
beaglescout007 0:3dac1f1bc9e0 50 hdma_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
beaglescout007 0:3dac1f1bc9e0 51 hdma_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
beaglescout007 0:3dac1f1bc9e0 52 hdma_tx.Init.MemBurst = DMA_MBURST_SINGLE;
beaglescout007 0:3dac1f1bc9e0 53 hdma_tx.Init.PeriphBurst = DMA_PBURST_SINGLE;
beaglescout007 0:3dac1f1bc9e0 54
beaglescout007 0:3dac1f1bc9e0 55 HAL_DMA_Init(&hdma_tx);
beaglescout007 0:3dac1f1bc9e0 56
beaglescout007 0:3dac1f1bc9e0 57 __HAL_LINKDMA(hspi, hdmatx, hdma_tx);
beaglescout007 0:3dac1f1bc9e0 58
beaglescout007 0:3dac1f1bc9e0 59 HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 0, 1);
beaglescout007 0:3dac1f1bc9e0 60 HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
beaglescout007 0:3dac1f1bc9e0 61 }
beaglescout007 0:3dac1f1bc9e0 62
beaglescout007 0:3dac1f1bc9e0 63 void DMA2_Stream3_IRQHandler(void)
beaglescout007 0:3dac1f1bc9e0 64 {
beaglescout007 0:3dac1f1bc9e0 65 HAL_DMA_IRQHandler(SpiHandle.hdmatx);
beaglescout007 0:3dac1f1bc9e0 66 }
beaglescout007 0:3dac1f1bc9e0 67
beaglescout007 0:3dac1f1bc9e0 68 } // extern "C"
beaglescout007 0:3dac1f1bc9e0 69
beaglescout007 0:3dac1f1bc9e0 70 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 71 /* Write a byte data */
beaglescout007 0:3dac1f1bc9e0 72 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 73 void spi_write(uint8_t data)
beaglescout007 0:3dac1f1bc9e0 74 {
beaglescout007 0:3dac1f1bc9e0 75 HAL_SPI_Transmit(&SpiHandle, &data, 1, 100);
beaglescout007 0:3dac1f1bc9e0 76 }
beaglescout007 0:3dac1f1bc9e0 77
beaglescout007 0:3dac1f1bc9e0 78 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 79 /* Write a word data */
beaglescout007 0:3dac1f1bc9e0 80 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 81 void spi_writew(uint16_t data)
beaglescout007 0:3dac1f1bc9e0 82 {
beaglescout007 0:3dac1f1bc9e0 83 HAL_SPI_Transmit(&SpiHandle, (uint8_t *)&data, 2, 100);
beaglescout007 0:3dac1f1bc9e0 84 }
beaglescout007 0:3dac1f1bc9e0 85
beaglescout007 0:3dac1f1bc9e0 86 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 87 /* Initialize SPI DMA */
beaglescout007 0:3dac1f1bc9e0 88 /*-------------------------------------------------------------------*/
beaglescout007 0:3dac1f1bc9e0 89 void spi_init()
beaglescout007 0:3dac1f1bc9e0 90 {
beaglescout007 0:3dac1f1bc9e0 91 SpiHandle.Instance = SPI1;
beaglescout007 0:3dac1f1bc9e0 92 SpiHandle.Init.Mode = SPI_MODE_MASTER;
beaglescout007 0:3dac1f1bc9e0 93 SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
beaglescout007 0:3dac1f1bc9e0 94 SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
beaglescout007 0:3dac1f1bc9e0 95 SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE;
beaglescout007 0:3dac1f1bc9e0 96 SpiHandle.Init.CLKPolarity = SPI_POLARITY_HIGH;
beaglescout007 0:3dac1f1bc9e0 97 SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
beaglescout007 0:3dac1f1bc9e0 98 SpiHandle.Init.CRCPolynomial = 7;
beaglescout007 0:3dac1f1bc9e0 99 SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT;
beaglescout007 0:3dac1f1bc9e0 100 SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB;
beaglescout007 0:3dac1f1bc9e0 101 SpiHandle.Init.NSS = SPI_NSS_SOFT;
beaglescout007 0:3dac1f1bc9e0 102 SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE;
beaglescout007 0:3dac1f1bc9e0 103
beaglescout007 0:3dac1f1bc9e0 104 if (HAL_SPI_Init(&SpiHandle) != HAL_OK)
beaglescout007 0:3dac1f1bc9e0 105 while(1);
beaglescout007 0:3dac1f1bc9e0 106 }
beaglescout007 0:3dac1f1bc9e0 107