A handheld gaming console built on the Raspberry Pi Pico 2 (RP2350). ECE 362 final project.
PioNeer is the firmware for a self-contained handheld game console. The device boots into a graphical launcher that reads game binaries from a microSD card and displays them as a grid of selectable tiles on a colour TFT screen. Selecting a game side-loads it: the launcher copies the binary into flash, locates its entry point, and reboots the microcontroller directly into the game.
This repository contains the launcher/bootloader firmware and the hardware drivers that back it (display, input, audio, addressable LEDs, and SD storage). Individual games are separate RP2350 binaries placed on the SD card rather than part of this project.
The name is a nod to the RP2350's PIO (Programmable I/O) block, which is used here to drive the WS2812B LED strip.
The firmware targets the RP2350 (Raspberry Pi Pico 2 class) microcontroller and
drives the following peripherals. Pin assignments are defined in
include/config.h.
| Subsystem | Device | Interface | Notes |
|---|---|---|---|
| Display | ST7796 TFT LCD, 480x320 | SPI0 @ 40 MHz | Rendered with LVGL |
| Buttons | A / B / X / Y face buttons | GPIO 34-37 | Timer-based debouncing + edge interrupts |
| Thumbstick | Analog joystick + push switch | ADC ch0/ch1 (GPIO 40/41), switch GPIO 39 | Menu navigation and select |
| Audio | Speaker driver | PWM on GPIO 38 | Two-channel wavetable synth |
| RGB LEDs | 10x WS2812B addressable strip | PIO on GPIO 9 | Driven via the RP2350 PIO |
| Storage | microSD card | SPI1 | FatFs filesystem |
- SD-card game launcher. On boot the firmware mounts the SD card, scans the
games/directory, and renders each binary as a coloured tile in an LVGL grid menu. macOS metadata files are filtered out automatically. - Side-loading bootloader. Selecting a game reads the binary into RAM, erases and programs it into flash at a 1 MB offset, scans the image for a valid RP2350 vector table (stack pointer in SRAM, program counter in flash), and jumps into the game via a watchdog reboot.
- Wavetable audio. A two-voice PWM synthesizer with sine, sawtooth, square, and triangle waveforms, updated from an interrupt handler.
- Addressable RGB lighting. WS2812B strip driven from a PIO program, with RGB/HSV colour control, per-pixel brightness, and animated effects.
- Power-on self-tests. Built-in routines exercise the display, LED strip, and
audio path (see
src/self_test.c).
The project is built with PlatformIO against the
Raspberry Pi Pico SDK. The environment is defined in platformio.ini
(board = proton, framework = picosdk), and pulls in LVGL and a FatFs SD-card
library as dependencies.
# Build
pio run
# Flash and monitor (configured for a picoprobe debugger)
pio run --target upload
pio device monitor --baud 115200The default upload and debug tool is picoprobe; serial logging runs at
115200 baud.
Place compiled game binaries in a games/ directory at the root of a
FAT-formatted microSD card:
/games/
game1.bin
game2.bin
...
Each game must be a standalone RP2350 binary linked to run from the 1 MB flash offset that the launcher programs it to.
- Thumbstick — move the highlight between game tiles in the menu.
- Thumbstick press — launch the highlighted game.
- A / B / X / Y buttons — available to games as face inputs.
platformio.ini PlatformIO build configuration (board, framework, libs)
filter_libs.py Build hook that skips SIMD/RISC-V assembly variants
include/ Public headers and hardware pin/config definitions
config.h Pin map and board configuration
lv_conf.h LVGL configuration
src/
main.c Boot sequence and menu loop
ui.c LVGL launcher menu and the side-loading bootloader
spi_display.c ST7796 TFT setup and LVGL flush callbacks
adc_joystick.c Analog thumbstick and switch
gpio_buttons.c Debounced face-button input
audio.c PWM wavetable synthesizer
led_strip.c WS2812B / PIO LED driver and effects
sd_api.c FatFs SD-card wrapper (mount, files, directories)
self_test.c Display / LED / audio power-on self-tests
ws2812.pio.h Generated PIO program for the LED strip
not_compile/ Standalone input-test harness (excluded from the build)