In September 2019, I set out to build an LED display cube from six matrix panels. By Halloween it was running NES Castlevania across four sides of it, with Simon Belmont walking around the outside of the cube while I rotated it with my feet. Here’s how that happened.
The Goal
The original plan was a battery-powered display piece driven by a Raspberry Pi — something that could run visual shaders, maybe some simple games. What it ended up being was a bit more involved: a fully interactive cube running emulated console games, with a lazy susan underneath and a custom de-scrolling hack in the software.
The Research Problem
The panel specs, power requirements, and driver boards were all documented and findable. The hard part was the frame. Building a rigid enclosure for six panels and all the associated electronics — one that could be assembled, opened for maintenance, and survive being moved around — was going to take a lot of CAD work, a lot of test prints, and a lot of failed iterations.
I didn’t want to go down that path. Someone must have done this before, and it turned out several people had. The LED cube builder community is small but active on Twitter and GitHub. Bob Miller’s blog (kbob.github.io) is a good overview of the landscape. HappyTeddybear had gone further and released all the STL files for a P2.5 64×64 cube frame — a clean, practical design with a hinged lid held shut by neodymium magnets, specific mounting points for the Pi and voltage regulators, and screw holes in all the right places. That design saved the project several months of work.
The Build
Panels came from Pimoroni in the UK. Six Adafruit 64×64 P2.5 panels, each running off its own 5V buck regulator, all fed from a Hexapod power distribution board with a 4S battery. The Adafruit RGB Matrix Bonnet handles the connection between the Pi 4 and the panel chain.
Testing came before assembly. I hooked the panel chain up to a bench power supply and ran Adafruit’s setup sequence before a single frame part had finished printing. The panels worked at high frame rates on the Pi 4 after a couple of software config tweaks — that was a relief. Getting Conway’s Game of Life spread across all six faces at once was the first real milestone.
Once the frames finished printing, assembly took several hours. The frame design is well-thought-out: everything fits with purpose, nothing rattles. The lid is particularly good — opens cleanly for wiring access, closes flat with the magnets.
Making It Interactive
As a visual display the cube works well on its own — Shady (github.com/polyfloyd/shady) can render any WebGL shader from shadertoy.com across all six faces, which looks excellent. But I wanted games running on it.
My day job is web development, so I started with JavaScript emulators. I found a working Game Boy emulator and got it running on one panel through a setup where Chromium renders the emulator, a Node.js server reads frames and converts them to raw data, and rpi-rgb-led-matrix sends it over GPIO to the panels. Running six different games at once on all six faces was fun to try, but the Pi’s CPU couldn’t keep all of them smooth. One game at a time worked well.
The next step was getting a single game to use all four sides at once. With Halloween coming, Castlevania was the obvious choice.
The Scrolling Problem
Most NES games with room-by-room layouts (Zelda, for instance) map cleanly to a cube — each room is a discrete screen that sits naturally on one face. Castlevania scrolls. The character stays centered and the level moves past him. On a cube, that means Simon Belmont stands still in the middle of one face while Dracula’s castle flows around him, which is exactly what I didn’t want.
I needed a de-scrolled version: Simon walking across the cube while the background holds its position. The fix was to read the value in the PPU’s scrolling register, combine it with data from a secondary memory offset, and use the result to calculate Simon’s absolute position in the level. The emulator output window gets offset by that amount each frame. The effect is that the game’s world is anchored and the character moves through it — which maps correctly onto the cube’s four faces.
Wrapping the 2D game output around the cube geometry was the second half of the problem. I find it easier to show than explain — there’s a Twitter thread at @ThereminHero with a visual breakdown.
Rotation
A single-player game on a cube has an obvious usability problem: the action moves to the face behind you. The solution was a cheap lazy susan from eBay connected to a variable voltage power supply. Two foot pedals control direction and speed in real time while I’m playing. It’s a manual setup, and automating it with a motor driver and Arduino is the next thing on the list.
Components
- 6x Adafruit 64×64 P2.5 LED matrix panels
- 1x Raspberry Pi 4
- 1x Adafruit LED Matrix Raspberry Pi Bonnet
- 6x 5V buck regulators
- 1x Hexapod power distribution board with built-in 12V and 5V regulator
- 1x 4S battery
- 3D-printed frame — HappyTeddybear’s design (github.com/AHappyTeddy/LED-Cube-Build-Files)
Software stack: jsnes JavaScript NES emulator running in Chromium, Node.js server for frame capture and GPIO conversion, rpi-rgb-led-matrix for panel output. Full build thread on Twitter at @ThereminHero.