EMB-01 Released
NOVA RAID — bare-metal Pico W arcade game
A complete retro space shooter in bare-metal C, released as a drag-and-drop UF2 — and fixed after its first run on real hardware exposed a defect no simulator caught.
Recruiter summary
- Problem
- The ST7796S panel takes roughly 39 ms to receive a full frame over SPI — by itself more than a 25 fps budget — on a dual-core Cortex-M0+ with no FPU (design calculations, not on-hardware measurements).
- Contribution
- Designed and wrote the whole game bare-metal, solo: the dual-core pipeline, 24.8 fixed-point math, DMA/SPI streaming, a testable HAL with a desktop host harness, and the release engineering.
- Result
- Released as drag-and-drop UF2s with green CI; the first run on real hardware exposed a panel-init defect no simulator caught — fixed and documented the same day in v1.0.1.
RP2040-RENDER
Interactive visualization · drag to inspect
3D ENGINEERING VIEW
The system as an interactive composition
Evidence-based visualization of the Pico W, display, framebuffer, and dual-core DMA render path.
Use the left and right arrow keys to rotate the scene. A complete text description is provided; no factual claim depends on the visualization alone.
The dual-core render pipeline
Flow diagram: core zero simulates and draws into the framebuffer; core one pixel-doubles and streams over DMA and SPI to the panel.
-
A fixed timestep updates game state in 24.8 fixed-point math — there is no FPU on the Cortex-M0+.
-
Ships, waves, collisions, and score in plain C structs; high scores persist in the last 4 KiB flash sector with the second core locked out.
-
Core 0 renders a 240×160 frame — a quarter of the panel resolution — to fit RP2040 memory and the frame budget.
-
Core 1 doubles each line to 480 pixels and feeds the stream — so the panel transfer overlaps the next frame's simulation instead of blocking it.
-
Double-buffered DMA streams over SPI at 62.5 MHz. The frame-budget figures are design calculations from the datasheet, not on-hardware measurements.
-
The first real boot revealed the panel runs inverted: v1.0.1 added INVON to init — the defect no desktop harness could have caught.
Select a stage to inspect it
The constraint that shaped everything
The ST7796S panel takes roughly 39 ms to receive a full 480×320 frame over SPI at 62.5 MHz — by itself more than a 25 fps frame budget. The design answer: core 0 simulates and renders a 240×160 framebuffer at a fixed timestep while core 1 pixel-doubles each line and streams it with double-buffered DMA, so the panel transfer overlaps the next frame’s simulation instead of blocking it. (These are design calculations from the datasheet and clock math, not on-hardware benchmarks — the distinction matters.)
Engineering under a Cortex-M0+
No FPU: all movement uses 24.8 fixed-point math and a 64-entry sine table. High scores persist in the last 4 KiB flash sector, written with the second core locked out and interrupts disabled, validated by a magic number. Game code touches hardware only through a small HAL — which means the identical sources compile on a desktop, where a host harness drives the game through every state (splash → menu → waves → boss → pause → death → initials → hall of fame → diagnostics) on every push in CI.
The bug that only existed on real hardware
v1.0.0 shipped CI-green and harness-verified. The first boot on the physical
board displayed a color negative — white background, inverted sprites. The
kit’s panel runs in inverted mode, and the init sequence never sent INVON.
v1.0.1 fixed it the same day, with the root cause written into the release
note. The repository keeps both releases and the pre-fix hardware photos:
the honest version of “verified on hardware” includes what the first
verification found.
Evidence
Ten gallery frames captured pixel-true by the host harness (labeled as renders, not photographs), five photos of the game running on the physical board, SVG block diagram/schematic/controls diagrams, eleven green CI runs, and two tagged releases with UF2 artifacts. All game code, sprite art, and sound sequences are original; third-party components (Pico SDK, a PIO program from pico-examples, a public-domain font) are credited in the README.
Limits
25 fps by design, single-channel buzzer audio, the kit’s touch panel is intentionally unused, and other board lots may need one-line config flips for joystick orientation.