Mini CRT Arcade Box
I wanted a little retro arcade thing sitting on my desk — something that looked like it belonged in 1985, not a generic HDMI monitor screwed to a shelf. The result is a miniature CRT-shaped box running RetroPie on a Raspberry Pi Zero W, with built-in stereo speakers, a front-panel volume knob, and a 3.5” HDMI display at native 4:3 resolution. NES games look exactly right on it.
This is a full build guide: what you need, how to wire it, how to set up the software, and how to make the enclosure.
The complete project files — config, setup scripts, and 3D-print source — are at github.com/matt-bey/elk-mini-crt-arcade.
How it works
The Pi Zero W runs RetroPie and outputs video over mini-HDMI to a 3.5” Waveshare display. That display has a 3.5mm audio jack — audio goes HDMI → display → 3.5mm jack → PAM8403 amplifier → two small speakers. The PAM8403’s built-in potentiometer becomes the front-panel volume knob.
Power comes from a TP4056 + 5V/2A boost combo board: one USB-C port to charge, a momentary button wired to the K (key) point to switch the output on and off, and a pair of small speakers behind side-vent grilles. A Samsung 30Q 18650 cell runs the whole thing for a couple of hours.
Parts
| Component | Qty | Notes | Source |
|---|---|---|---|
| Raspberry Pi Zero W | 1 | Main board | |
| Waveshare 3.5" HDMI LCD (E) | 1 | 640×480 IPS, 3.5mm audio out; powered via pogo pins from Pi 5V | |
| PAM8403 amplifier board | 1 | 5V, 2×3W, with volume potentiometer | |
| Gikfun 2" 4Ω 3W speaker | 2 | Full range | |
| 3.5mm stereo to bare wire | 1 | Audio in to PAM8403 | |
| Mini-HDMI to HDMI cable | 1 | Pi Zero W to display | |
| USB NES-style controller | 1 | Player input | |
| TP4056 + 5V/2A boost combo board | 1 | DWEII or equivalent — USB-C charge in, K point for power button, +/− output pads | |
| Samsung 30Q 18650 cell | 1 | 3000mAh, 15A continuous — source from a reputable vendor | 18650batterystore.com |
| 18650 battery holder (single cell) | 1 | Wire leads to BAT+/BAT− on combo board | SparkFun PRT-12899 |
| Momentary push button | 1 | Wires to K point on boost board — toggles output on/off | |
| Power distribution block, 2-pole 6-position | 1 | Teansic 2×6 or equivalent — one row 5V, one row GND | |
| 100µF electrolytic capacitor | 1 | On supply rail; go up to 1000µF if reboots occur under load | |
| 22 AWG stranded silicone wire | — | General internal wiring |
3D-printed enclosure — files in the repo (enclosure/), built with build123d.
Electronics
Power chain
The boost combo board is the heart of the power system. Wire the 18650 cell to BAT+/BAT−, a momentary button to the K point (short to ground to toggle), and run the 5V output to the distribution block. From there:
- Pi GPIO 5V pin (pin 2 or 4) and GND (pin 6)
- PAM8403 5V and GND
- Waveshare display — the display’s pogo pins sit against the Pi’s 5V and GND GPIO pins when they’re stacked, so it gets power that way
Put a 100µF capacitor across the 5V rail on the distribution block to smooth out brown-outs when the display and Pi both start up. If the Pi still reboots under load (usually when the display backlight peaks), go up to 1000µF.
Audio
3.5mm stereo from the Waveshare display’s audio jack → PAM8403 L/R/GND inputs. Left and right speaker wire to the PAM8403 outputs. The volume potentiometer on the PAM8403 board becomes your front-panel knob — extend its shaft through the enclosure bezel.
One important software step: cap the ALSA software volume at 70%. The PAM8403 is a class D amp and its power draw scales with signal amplitude squared — a 70% cap meaningfully cuts average battery drain during gameplay without any noticeable volume loss at normal listening levels. The setup script handles this.
Display
The Waveshare 3.5” (E) stacks directly onto the Pi via the GPIO connector (the pogo pins carry power; HDMI carries video separately). Run a mini-HDMI to HDMI cable from the Pi to the display’s HDMI port. The boot-config-hdmi.txt in the repo sets the correct 640×480 resolution.
Enclosure
The enclosure is styled as a shrunken CRT television: thick bezel, recessed screen, tapered rear profile, vent slots on the sides that double as speaker grilles. The v1 was cardboard (faster to prototype, easier to cut vent holes). The 3D-printed v2 is parametric Python via build123d.
Key design choices that make it feel right:
- Volume knob on the front bezel — reach the shaft of the PAM8403 pot through a hole in the bezel
- Side vents as grilles — speakers mount inside, pointing out through a grid of holes
- Screen recessed a few mm behind the bezel face — CRTs didn’t sit flush
Print the main body and bezel separately. The stand has a tilt mechanism so you can angle the screen.
Software setup
Flash a Raspbian Buster + RetroPie image to the SD card, then run the setup script from your machine:
bash scripts/setup.sh
This copies the config files to the Pi, enables the right display mode, sets the ALSA volume cap, and persists the audio state. Full details in SOFTWARE.md in the repo.
RetroPie handles the rest — ROMs go in the usual place, EmulationStation is the frontend.
Notes
The 640×480 native resolution of the Waveshare display is the thing that makes NES and SNES content look right. Most arcade and console games from that era were designed for 240p or 480i on a CRT — this display hits 480p without any scaling artifacts. GameBoy and GBA content also looks good at this size.
Battery life is around 2 hours at moderate volume. The PAM8403 is the main drain when playing; the 70% software cap helps noticeably. If you want longer runtime, a 3500mAh cell (Samsung 35E or similar) drops in without any changes.
The cardboard v1 was worth building first. It let me figure out speaker placement and cable routing before committing to the 3D print. The vent slot positions changed twice based on where the cables naturally wanted to run.