-
Notifications
You must be signed in to change notification settings - Fork 1
Matrix Gateway
A split-flap display with no split flaps.
This is the SplitFlap Gateway firmware ported to an Adafruit MatrixPortal ESP32-S3 driving a HUB75 RGB LED matrix. The RS-485 transceiver is gone; in its place is a software bus and a wall of virtual split-flap modules, each one emulating a real module's wire protocol byte-for-byte and rendering itself as a flapping character cell on the panel.
Everything above the bus is the unmodified gateway: the same web UI, REST API, MQTT, Home Assistant discovery, OTA, and module registry. The Companion drives it without any changes and cannot tell the difference from real hardware.
- Try the whole stack with no mechanical build — web UI, companion, Home Assistant, the lot, on one ~$25 board plus a panel. No modules, no RS-485, no steppers, no calibration.
- An LED-matrix display in its own right — full colour, real accented characters, lowercase, the colour flaps, and an animated flip effect with a physical-looking seam.
- A faithful test target — because it emulates at the protocol level, it exercises the same code paths a real gateway does.
| Part | Notes |
|---|---|
| Adafruit MatrixPortal ESP32-S3 | The controller (Adafruit #5778). |
| A HUB75 LED panel | Default layout is a 15 × 3 wall on a 128 × 32 chain (two 64×32 panels in series, or one native 128×32). Bigger panels give roomier cells. |
| A 5 V power supply | Sized for your panel — check the panel/Adafruit specs. |
64-row panels (128×64) use the HUB75 E address line — which the MatrixPortal wires out of the box to connector pin 8, the common panel layout, so a 64-row panel normally just works with no board changes. Only a panel that expects E on pin 16 needs the board's solder jumper moved. See the repo's README for the panel/size table.
Panel wiring varies one other way: some panels are BGR rather than RGB. Nothing can detect that — it shows up as every colour being wrong in a telltale pattern (red draws blue, yellow draws cyan, while green and white look fine). That's a setting, not a hardware fix: Settings → LED Panel → BGR.
pio run -t upload # build + flash over USB (double-tap RESET if the port is busy)
pio device monitor # 115200 baud, native USB CDCWiFi works like the real SplitFlap Gateway — with one difference: its hostname is configurable, and the fallback AP is named after it.
- On first boot it raises an access point called
splitflap-gw-<6 hex digits>(derived from the board's MAC — e.g.splitflap-gw-a3f19c), password12345678. - Join it, open http://192.168.4.1, and save your SSID + password in Settings → WiFi.
- It joins your LAN and the AP shuts off. Reach it at http://.local — and you can change the hostname to something friendlier in Settings.
The same mDNS caveats apply: if .local doesn't resolve on your network, find the board's
IP in your router's DHCP client list (look for the hostname above) and use that instead —
see Finding it on your network. From there it's the
same web UI as the gateway — same tabs, same settings.
-
Emulated: everything the gateway actually sends — display and homing commands, flap-set config, version/identity queries, broadcasts, and batch queries. Each virtual module even reports a (fabricated but stable) serial number, so the gateway discovers them exactly as it would real modules.
-
The reel is bigger: nothing is drawn from a physical reel, so nothing is rationed. A virtual module carries 237 flaps where a real one carries 64:
flaps what they are 0–155 every Windows-1252 glyph — letters, digits, punctuation, accents 156–162 the seven colour flaps — red, orange, yellow, green, blue, violet, white 163–222 the 60 lowercase letters, accents included 223–236 14 pictographs — ♥ ♦ ♣ ♠ ☀ ☺ ♪ ● ■ ⌂ and the four arrows -
Not emulated: the mechanism. There's no stepper, Hall sensor or EEPROM, so calibration, diagnostics and provisioning are no-ops (the modules are "born" provisioned). You won't use the Calibration or Provision tabs here.
-
The flip is a rendering effect, not a physics simulation — you can cap or disable it.
The last two rows of that table are the interesting ones, and they need a word of explanation, because for a long time they were on the reel but unreachable.
The gateway's original display protocol carries one byte per character, and it has a
collision it can never fix: the byte for lowercase r already means RED. That is why
m38-r sets the red flap, and it is why, on that path, lowercase has to fold to uppercase and
a heart — which has no Windows-1252 byte at all — cannot be addressed by character in any
way. This is not a bug to be tidied up; it is the price of a protocol that spends seven of its
letters on colours.
Firmware 1.6 answers it by adding a second, index-addressed endpoint:
POST /api/display/cells
{ "start": 0, "step_ms": 15,
"cells": [ {"ch": "H"}, {"ch": "i"}, {"color": "red"}, {"skip": true} ] }
A cell names a character, a colour by name, a blank, or skip (leave that module
alone). Because a colour is now a name rather than a borrowed letter, i can simply be the
letter i — and flap 223 can be a heart.
The old character protocol still works exactly as it did, byte for byte. Nothing about a physical wall changes.
You do not have to do any of this yourself. The Companion asks the gateway
what it is (GET /api/config), and if it finds a Matrix Gateway on firmware 1.6 or newer it
uses the index API automatically — so apps render in mixed case, colours stay colours, and
pictographs appear. Point it at a physical wall and it falls back to the character protocol
and folds everything to capitals. Same app, same companion, whichever wall you own.
Everything above treats the panel as a wall of flaps. But it is also, physically, a grid of RGB LEDs — and the Matrix Gateway can hand that grid over as a plain framebuffer, bypassing the split-flap emulation entirely, so you can draw anything on it. A real split-flap gateway has no framebuffer at all, so this is the one place a Matrix wall does something the hardware it emulates simply cannot.
There are three ways in, and a client discovers all of them from GET /api/capabilities — the
Matrix gateway advertises a canvas object (its pixel formats and panel width/height)
and an effects list; a physical gateway carries neither:
-
Draw ops (
POST /api/canvas/ops) — a JSON batch ofclear/pixel/hline/vline/rect/textcommands, applied in order and presented. Shapes and labels without composing a whole frame. -
A raw frame (
PUT /api/canvas/frame) — a fullwidth × heightbuffer of pixels,rgb888orrgb565(the format is inferred from the body length). The way to mirror a picture; the panel's colour depth loses nothing to it. -
On-device effects (
POST /api/canvas/effect) —plasma,fireormatrixrain, animated by the panel itself at its native ~70 fps with nothing on the network. Pushing frames over HTTP tops out near 8 fps; an on-device effect is limited only by the panel.
While a canvas is active the reel renderer stands down — the same way it does during an OTA — and the canvas owns every pixel; releasing it repaints the wall from the modules' current state. Nothing canvas is persisted, so a reboot always returns to the flaps.
You don't drive any of this by hand. The Companion exposes it through canvas
apps — apps that draw on the panel instead of returning flap pages: the built-in Effects,
Lumina Clock, Weather Sky, Overview, Date Card, World Time, Countdown Bars and Image apps, plus any you write yourself.
The endpoints are specified in full under the Canvas tag of the firmware's openapi.yaml.
The Matrix Gateway is a drop-in replacement for the modules and the gateway. Wherever the rest of this wiki says "the gateway," it applies here too — including registering the Companion and everything in Home Assistant. Skip the Hardware and Module Firmware pages entirely.
Next: Companion →
Start
Build it
- Hardware
- Module Firmware
- Provisioning
- Calibration
- Flaps & Character Sets
- SplitFlap Gateway
- Matrix Gateway
- LCD Gateway
Drive it
- Companion
- Built-in Apps
- Standalone & Docker
- Multiple Displays
- Home Assistant
- Vestaboard API
- MCP Server
- Using splitflap-os
Extend it
Reference
Hardware © Adam G Makes