Skip to content

Latest commit

 

History

History
369 lines (298 loc) · 15.5 KB

old_docs.md

File metadata and controls

369 lines (298 loc) · 15.5 KB

esp-box-emu

Emulator(s) running on ESP BOX with custom pcb and 3d printed enclosure :)

box_emu_save_state_menu_compressed.mp4
box_emu_hardware_test1.mp4

Description

This project is a little retro game emulation system running on ESP32-S3-BOX. It is built using the following:

Videos

Gameboy Color

This video shows settings page (with audio control and video scaling control), and then Links Awakening DX. While running the ROMs, the video scaling can be toggled through the three options (Original, Fit, and Fill) using the BOOT button on the side of the ESP-S3-BOX and the audio output can be toggled on / off using the MUTE button on the top.

links_awakening_dx_compressed.mp4

NES (Super Mario Bros. and Zelda, turning audio up for zelda :) )

smb-and-zelda-compressed.mp4
links_awakening_dx.mp4

Gameboy (Pokemon and Links Awakening)

pokemon-and-links-awakening-compressed.mp4

Older Videos:

Images

Rom GUI: Zelda (NES) Zelda (NES) emulated
It's Dangerous To Go Alone, Take This! Zelda (NES) Get Sword
Settings Screen (Audio Volume for now) Super Mario Bros. 3 (NES)
Pokemon Yellow (GBC) Link's Awakening (GB)
Squareline Studio Design

Features

Note: for the ECAD + MCAD I'm using the free version of Fusion360.

Prototype CAD

Link to Fusion 360 CAD: a360_mcad

The printable files can be found in the ./mcad folder or can be downloaded from printables.

This project has the following features (still WIP):

  • Squareline Studio design files for generating boilerplate LVGL (SQS files, Generated files)
  • LVGL gui for selecting emulators / roms (showing boxart and name)
  • LVGL gui for controlling settings (such as volume) (using gui component)
  • Loading of gui data (rom titles and boxart) from metadata file (example here)
  • Audio output (using I2S + es8311 audio codec, es8311 component)
  • Interaction with QwiicNes NES gamepad
  • Interaction with analog joystick + buttons (using controller component)
  • Interaction with d-pad + buttons (using controller component)
  • Interaction with touchscreen (using tt21100 component)
  • Navigation of LVGL rom menu with controller (up,down,start)
  • Runnable emulators (automatically selected by rom extension):
    • NES emulator (~100 FPS running Legend of Zelda)
    • GB/GBC emulator (~100 FPS running Link's Awakening DX (GBC))
    • SNES emulator
    • SMS / Genesis emulator
  • LittleFS file system for local storage of roms and metadata
  • Support for uSD (FAT) filesystem over SPI
  • Memory mapping of selected rom data from storage (littlefs or uSD) into raw data partition (SPIFLASH)
  • Emulator framebuffers on SPIRAM
  • Some hacky support for BT Gamepad input (see note below regarding wifi use.)
  • Refactor to have a blit function which queues up transfers for screen into a task
  • Scaling of GB/GBC display to support original, fit, and fill video scaling modes
  • Scaling for NES display to support original (which is fit) and fill video scaling modes
  • Use mute button to toggle volume output while running the roms
  • Use boot button to switch between video scaling modes while running the roms
  • Feedback through tiny haptic motor (DRV2605)
  • Save state
  • Load state
  • Feedback through BLDC haptic motor (see https://github.com/scottbez1/smartknob)
  • State management (UI to select state when loading roms, ui/buttons for saving/loading states while running)
  • Favorites menu?
  • Recently played menu?
  • Show emulator with rom for easy sorting / finding
  • Graphics in black borders next to rom display during NES / GB/C emulation
  • Schematic / Layout for control board peripheral containing
    • joystick / D-Pad / Button inputs (via i2c I/O expander / ADC)
    • Battery
    • Charger circuit
    • DRV2605 haptic motor (LRM / ECM)
    • uSD card
    • boost converter
    • usb 2.0 passthrough from usb-c
    • TMC BLDC driver chip
    • ABI magnetic encoder chip
    • BLDC motor (haptics)
  • CAD for control board peripheral case in the same footprint as GBC
    • USB-C Port for programming / charging
    • uSD card slot for roms
    • start / select buttons (same location as GBC)
    • ABXY buttons (basically same size / location as GBC)
    • Directional Pad (same size / location as GBC)
  • Use same audio + video tasks for both NES and GB/C emulation
  • FTP Client for browsing remote FTP server of roms and displaying their data in LVGL

Support for dynamically loading emulators (TBD)

Down the line I'd like to add the ability to load the emulator cores from the FTP server (which would be pre-compiled ESP32 libraries) so that they wouldn't take up as much space on the ESP32 itself. Right now that's not a huge concern though because the ESP (S3 module in the ESP BOX especially) has more than enough flash for the emulators so assuming their RAM can be managed it won't be much of an issue.

Info for loading elf files at runtime: https://github.com/niicoooo/esp32-elfloader. Here is another implementation.

Filsystem / Storage

The emu-box supports both on-board FLASH storage through LittleFS (limited to the 16 MB flash chip in the S3 in the box) as well as support for external FAT filesystems on a uSD card connected via SPI (this is the DEFAULT option):

uSD SPI ESP32 GPIO (exposed via PMOD header)
CS 10
MOSI 11
MISO 13
SCLK 12

The storage can be changed via menuconfig.

Using LittleFS (Internal FLASH):

You will need to set up a flash_data/ folder which contains your roms (.nes, .gb, .gbc), images (.jpg), and metadata.csv. (See next section for more info about Rom Images and the metadata file). The contents of this folder will be flashed into the littlefs partition.

At least once, you'll need to update the ./main/CMakeLists.txt to uncomment the line that has FLASH_IN_PROJECT as part of the littlefs_create_partition_image command - this will flash all files in your flash_data/ folder onto the littlefs partition on the embedded FLASH chip. Alternatively, you can use the esptool.py, parttool.py as mentioned in the SPIFFS docs.

Using FAT (external uSD card):

Format your uSD card as a FAT filesystem and add your roms (.nes, .gb, .gbc), images (.jpg), and metadata.csv. (See next section for more info about Rom Images and the metadata file). Make sure the uSD card is plugged into the socket and the wires are properly connected to the pins (including 3.3V and GND) listed above.

ROM Images

For ease of use, there is a ./boxart/source/resize.bash script which will resize all jpg images in the boxart/source folder to be 100x px wide (keep aspect ratio but make width 100 px) and put the resized versions in the boxart folder. You can then copy them onto your sd card and update your metadata file appropriately.

Metadata.csv format

<rom filename>, <rom boxart filename>, <rom display name>

Example:

mario.nes, boxart/mario.jpg, Mario Bros.
super_mario_1.nes, boxart/super_mario_bros_1.jpg, Super Mario Bros.
super_mario_3.nes, boxart/super_mario_bros_3.jpg, Super Mario Bros. 3
zelda.nes, boxart/zelda1.jpg, The Legend of Zelda
zelda_2.nes, boxart/zelda2.jpg, The Legend of Zelda 2: the Adventure of Link
mega_man.nes, boxart/megaman1.jpg, MegaMan
metroid.nes, boxart/metroid1.jpg, Metroid
pokemon_blue.gb, boxart/pokemon_blue.jpg, Pokemon Blue
pokemon_red.gb, boxart/pokemon_red.jpg, Pokemon Red
pokemon_yellow.gbc, boxart/pokemon_yellow.jpg, Pokemon Yellow
links_awakening.gb, boxart/tloz_links_awakening.jpg, The Legend of Zelda: Link's Awakening
links_awakening.gbc, boxart/tloz_links_awakening_dx.jpg, The Legend of Zelda: Link's Awakening DX

References and Inspiration:

ESP32 S3 Box Info:

It uses GPIO_NUM_46 to control power to the speaker, so if you do not set that as output HIGH, then you will never hear anything T.T

The ESP32 S3 Box has two PMOD headers, PMOD1 and PMOD2, which have the following pins:

  • PMOD1
    • IO40 (I2C_SCL)
    • IO41 (I2C_SDA)
    • IO38
    • IO39
    • IO42
    • IO21
    • IO19 (USB_D-, U1RTS, ADC2_CH8)
    • IO20 (USB_D+, U1CTS, ADC2_CH9)
  • PMOD2
    • IO09 (FSPIHD, TOUCH9, ADC1_CH8)
    • IO10 (FSPICS0, TOUCH10, ADC1_CH9)
    • IO11 (FSPID, TOUCH11, ADC2_CH0)
    • IO12 (FSPICLK, TOUCH12, ADC2_CH1)
    • IO13 (FSPIQ, TOUCH13, ADC2_CH2)
    • IO14 (FSPIWP, TOUCH14, ADC2_CH3)
    • IO44 (U0RXD)
    • IO43 (U0TXD)

LCD

The LCD is a ST7789 320x240 BGR display connected via SPI.

ESP32s3 LCD Pinout:

LCD Function ESP I/O Pin
Data / Command 4
Chip Select 5
Serial Data 6
Serial Clock 7
Reset 48
Backlight 45

Touch

The ESP32S3 Box uses a capacitive touch controller connected via I2C.

The touch driver can be either the TT21100 or Ft5x06 chip.

NOTE: it appears the one I have (regular ESP32 S3 BOX) which has the red circle at the bottom of the display (the HOME button) uses the TT21100 chip.

Audio

The ESP32s3 Box has a few audio codec coprocessors connected simultaneously to I2S (data) and I2C (configuration). It uses an encoder codec chip (ES7210) for audio input from the multiple mics on-board, and a decoder chip (es8311) for audio output to the speaker (output power controlled by GPIO 46).

ESP32s3 Audio Pinout:

Audio Function ESP I/O Pin
I2S MCLK 2
I2S SCLK 17
I2S LRCK 47
I2S Data Out 15
I2S Data In 16
Speaker Power 46
Mute Button 1

I2C Pinout (shared with touchscreen chip above):

I2C Function ESP I/O Pin
SCL 18
SDA 8

Controllers

Sparkfun QwiicNES

The Sparkfun QwiicNES (product page, library) is a NES controller adapter that supports direct GPIO and I2C. The controller component we have supports direct GPIO configuration if you choose to use it (find the configuration in the ./components/box-emu-hal/src/input.cpp).

It also however has a ATmega 32u4 which allows it to act as a USB gamepad and exposes the NES gamepad over I2C as well. For ease of use, the I2C functionality has been wrapped into a qwiicnes component. There is an example of using this qwiicnes component in the component's example folder.

Joy bonnet

The joy bonnet was designed as a raspberry pi hat which has abxy, start/select, analog joystick, and player 1 / player 2 buttons. It's useful for prototyping input / hardware and testing how well the emulators run (by playing them of course ;) )

The joystick is routed out via an ADS1015 I2C ADC chip (addr 0x48), with the Y-axis mapped to channel 0, and the X-axis mapped to channel 1. see here

Pinout (pin number is w.r.t. header, not pi GPIO):

Button Joy Bonnet Header Pin Number
A 32
B 31
X 36
Y 33
Start 37
Select 38
Ground 6, 9, 14, 20, 25, 30, 34, 39
5V 2, 4
3V3 1, 17
I2C SDA 3
I2C SCL 5

Other NES Emulators

Useful Background / Information