Files
TeslaRel410/restoration/PlasmaNew/replica
CydandClaude Fable 5 4391ddd322 restoration: import PlasmaNew — the plasma display replica effort
Moved from the vRIO repository to live with the other hardware
restoration work. Contains the PD01D221 reverse-engineering reference
(FIRMWARE.md, recovered from the TMS27PC512 EPROM dump) and the working
Matrix Portal S3 + HUB75 replica firmware (flashed and bench-tested
2026-07-22, including the G/B pin swap for these panels, the
PIN_BUTTON_UP/DOWN fix, and power-on cursor rendering).

The vPLASMA reference oracle (src/VPlasma.Core) and the VPlasma.Wire
differential-test tool stay in the vRIO repo; PlasmaNew pre-move commit
history is there too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-22 17:20:25 -05:00
..

Plasma display replica — Adafruit Matrix Portal S3 + HUB75

A hardware replacement for the failing Babcock PD01D221 cockpit plasma display (../README.md, ../FIRMWARE.md). A modern microcontroller reads the same serial command stream the game sends and renders it to a modern LED matrix — a drop-in from the host's point of view, with none of the plasma physics or high voltage.

The firmware's command parser and fonts are ported verbatim from vRIO's vPLASMA emulator (src/VPlasma.Core in the vRIO repo), which is the reference oracle. Feed the replica and vPLASMA the same byte stream and they produce the same frame.

Bill of materials

Part Notes
Adafruit Matrix Portal S3 ESP32-S3 controller; plugs into the HUB75 header; native USB-C = the virtual COM port
2 × Adafruit 64×32 RGB LED Matrix (P-pitch to taste; 1/16 scan) chained → 128×32, the panel's native resolution
5 V power supply, ≥ 4 A the panels are the load; USB cannot power them
USB-C cable data (and logic power) from the host PC

An amber-leaning pitch and diffuser best mimic the neon-orange plasma; the firmware already renders in orange (255,96,0 full / 110,40,0 half).

Wiring

  1. Chain the panels: panel A OUT → panel B IN, left-to-right, so the pair reads as one 128-wide canvas (x 063 = panel A, 64127 = panel B). If the image comes out swapped, reverse the chain order.
  2. Mount the Matrix Portal S3 onto panel A's IN HUB75 header.
  3. Power: 5 V ≥ 4 A into the Matrix Portal's screw terminals; run the panels' power pigtails from the same 5 V. USB-C carries data (and powers the S3 logic) — do not rely on USB for panel current.

Build & flash

Arduino IDE (or arduino-cli):

  1. Boards Manager → install esp32 (Espressif). Select board "Adafruit Matrix Portal S3". Set USB CDC On Boot: Enabled (so Serial is the USB port the game opens).
  2. Library Manager → install Adafruit Protomatter (pulls in Adafruit GFX / BusIO).
  3. Open MatrixPortalPlasma/MatrixPortalPlasma.ino (keep PlasmaDisplay.*, plasma_fonts.h, demo_screens.h beside it) and Upload.

The HUB75 pin arrays at the top of the .ino are Adafruit's published Matrix Portal S3 values — except the G and B pins, which are exchanged because these panels have the green and blue LEDs swapped (manufacturer-confirmed; symptom was orange rendering as purple). If a different panel garbles, verify the arrays against your installed Protomatter version.

Using it with the game

The Matrix Portal enumerates as a USB CDC COM port. In Windows Device Manager you can pin it to the COM number the host expects. Point the game's plasma output at it — under the DOSBox-X fork:

serial2 = directserial realport:COMx

Baud is cosmetic over USB CDC (the 9600 line-coding is accepted as a no-op), so the display keeps up regardless. The link is one-way (the game writes, the display listens), exactly as the cockpit drove the real panel.

No-host testing (onboard buttons)

  • UP — toggle the built-in firmware demonstration (the real 10-screen PLASMADOT demo, demo_screens.h, extracted from the ROM).
  • DOWN — toggle the panel test: cycles diagnostic patterns (solid, border+grid, horizontal/vertical stripes, checkerboard) to expose dead dots and addressing faults — the multi-pattern sequence the real firmware runs.
  • Power-on briefly lights every dot (confirms both panels), then clears.

Files

File
MatrixPortalPlasma/MatrixPortalPlasma.ino sketch: Protomatter init, USB serial, render loop, buttons
MatrixPortalPlasma/PlasmaDisplay.h/.cpp the PD01D221 parser + 128×32 framebuffer — a C++ port of VPlasmaDevice
MatrixPortalPlasma/plasma_fonts.h the 8 real ROM fonts (PROGMEM), generated from tms27pc512.BIN
MatrixPortalPlasma/demo_screens.h the 10 firmware demo screens (PROGMEM)

Keeping it faithful — the differential test

PlasmaDisplay is a line-for-line port of VPlasmaDevice; keep the two in sync (same commands, fonts, orientation/plot mapping). Validate the replica by sending identical byte streams to the replica, to vPLASMA, and to the real panel, then comparing the glass.

The VPlasma.Wire tool (in the vRIO repo: tools/VPlasma.Wire, dotnet run --project tools/VPlasma.Wire -- … from that repo's root) drives this:

# 1) Build a repeatable stream (or capture a real one — see below).
VPlasma.Wire synth  --kind demo    --out demo.bin

# 2) The vPLASMA golden image (pixel-exact reference PNG).
VPlasma.Wire render --in demo.bin  --out demo-golden.png --scale 8

# 3) Replay the SAME bytes to each target, and photograph the glass:
VPlasma.Wire replay --in demo.bin  --port COM3          # the real panel (RS-232)
VPlasma.Wire replay --in demo.bin  --port COM7          # the Matrix Portal (USB-CDC)

Compare the two photos against demo-golden.png. synth kinds: selftest, demo, banner, charset. render takes --orient v for vertical.

Capture a real session to build a test corpus non-intrusively — insert the tool in the path (point the game at COM12, tool tees on to the real display on COM3):

VPlasma.Wire capture --port COM12 --out session.bin --tee COM3

Then render/replay session.bin like any other stream.

Auto-compare a photo (cropped to the glass) against the golden image, or two streams against each other — each is reduced to 128×32 and diffed:

VPlasma.Wire diff --a demo-golden.png --b panel-photo.png --out delta.png
# prints "differing dots=N/4096  match=XX%", writes a red-on-mismatch image,
# exits 1 if they differ. Inputs may be .bin (ESC P) / .png / .txt (bitmap=).

Authoring plasma content (from TeslaSuite's plasma tools)

Generate display content from text or images and push it over the wire:

# Text in a Windows font, auto-sized to the panel → preview PNG + ESC P + hex:
VPlasma.Wire text --text "ALERT 12" --font "Arial" --png a.png --bin a.bin --hex a.txt
VPlasma.Wire replay --in a.bin --port COM7          # show it on the replica

# An image → the ESC P wire stream (and/or the game's bitmap= encoding):
VPlasma.Wire encode --in logo.png --bin logo.bin --hex logo.txt

# A bitmap= encoding → a preview PNG (and/or ESC P):
VPlasma.Wire decode --in logo.txt --png logo.png

Still deferred (as in vPLASMA, documented in ../FIRMWARE.md): the 10 double-buffered pages (ESC I/ESC i are consumed but single-page) and the vector-graphics primitives (ESC AF).