Files
TeslaRel410/restoration/PlasmaNew/replica/README.md
T
CydandClaude Fable 5 bd082d8c4a PlasmaNew: ESC X/x box commands in the replica + MW4 bench stream
Implements the firmware-disasm-confirmed Firestorm box protocol in the
MatrixPortal replica (ESC X outline / ESC x mode-fill via a BOXOP operand
collector, plus the ESC Y region op), updates FIRMWARE.md with the findings,
and adds FS-plasma-bench.ps1 -- a simulated MW4 serial stream for benching
the display without a pod.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 12:02:37 -05:00

158 lines
7.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Plasma display replica — Adafruit Matrix Portal S3 + HUB75
A hardware replacement for the failing Babcock **PD01D221** cockpit plasma
display ([../README.md](../README.md), [../FIRMWARE.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:
```sh
# 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`):
```sh
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:
```sh
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:
```sh
# 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 A``F`).
**Ahead of vPLASMA (2026-07-22):** the box family is implemented here from the
firmware disassembly — `ESC X l t r b` (box outline) and `ESC x m l t r b`
(region blank/fill/invert), the commands **BattleTech: Firestorm**'s `CPlasma`
driver draws its score panel with; `ESC Y` (screen blit) is validated and
consumed as a no-op. vPLASMA needs the same additions before the differential
test covers Firestorm streams — until then `../FS-plasma-bench.ps1` is the
Firestorm exerciser.