Back to project journal

PROJECT NOTES / EMBEDDED C++ & FREERTOS

NES Emulator on ESP32

Running a cycle-accurate NES console on an ESP32 microcontroller using dual-core FreeRTOS task scheduling, ILI9341 SPI TFT rendering, and Google Test validation.

NES emulator running on ESP32 development hardware with SPI TFT display
Hardware-in-the-loop: NES emulation running on ESP32 microcontroller with ILI9341 display.
ESP32 Dual-Core @ 240 MHz
FreeRTOS Task Scheduling
ILI9341 SPI TFT + DMA
Google Test (33 Tests Passing)

ESP32 / EMBEDDED REAL-TIME EMULATION

Cycle-Accurate Emulation on Bare-Metal Microcontrollers

Porting a cycle-sensitive console emulator to an embedded microcontroller requires strict architectural discipline. With 520 KB of internal SRAM and two 240 MHz Xtensa LX6 cores, the ESP32 provides the raw capability, but real-time performance hinges on efficient task allocation across FreeRTOS, memory-mapped I/O, and non-blocking SPI DMA transmissions.

01

Dual-core task architecture

Core 0 handles PPU scanline generation, palette color lookup, and DMA-driven SPI transmission to the ILI9341 display. Core 1 runs the 6502 CPU instruction dispatch, bus arbitration, APU sample synthesis, and gamepad polling without rendering stalls.

02

Memory & DMA optimization

The ESP32 lacks enough unified SRAM for a full uncompressed 16-bit double framebuffer. Instead, scanlines are rendered in ping-pong DMA-capable line buffers, streaming directly to the display hardware while the CPU prepares the next line.

03

Host testing with Google Test

Before flashing to hardware via PlatformIO, a desktop CMake suite executes 33 Google Test cases covering CPU addressing modes, official/unofficial opcodes, memory mirroring, and interrupt handling, ensuring rock-solid verification.

04

Hardware peripheral interfacing

Integrates an ILI9341 2.8" SPI LCD (320 × 240), an SPI SD card reader for cartridge ROM loading, I2S DAC / PWM audio output, and CD4021 shift-register gamepad deserialization.

Testing infrastructure and verification dashboard showing 33 passing Google Tests
CMake and Google Test host verification dashboard: 33/33 tests passing before flashing.

Hardware bill of materials & pinout

MCU Board
ESP32-WROOM-32 (Dual-Core @ 240 MHz, 4MB Flash)
Display
ILI9341 2.8" SPI TFT LCD (240 × 320, 16-bit color)
Storage
MicroSD Card Module via SPI bus (ROM cartridge loading)
Input
8-button NES controller via CD4021 shift register / GPIOs
Audio
I2S DAC / PWM audio output with low-pass RC filtering
Toolchain
PlatformIO + VS2022 + CMake + Google Test

Verification & build pipeline

The project uses Visual Studio 2022 and PlatformIO for ESP32 target builds, coupled with a cross-platform CMake build configuration for instantaneous desktop testing. 33 unit tests guarantee zero regression on 6502 core opcodes.

Explore ESP32 repository on GitHub