Files
TeslaRel410/display-board-1408.md
T
CydandClaude Fable 5 ea6199d516 Docs: record E0-threshold bench PASS (E0000105) + corrected counter semantics
The display observation recalibrates the counters: $3184 = give-up
cycles (once per exhausted retry sequence, not per retransmit), $3185 =
teardowns of any reply cycle needing at least one retransmission — the
counter behind a lone E0000001. Also recorded in the error-handling
inventory: 5 retransmits per cycle, reply-await arms only after the
complete frame, NAK forces exactly one counted retransmit, late ACKs
cannot rescue a cycle. (Previous commit's doc edits had silently missed
their anchors; applied properly this time.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:40:57 -05:00

133 lines
7.1 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.
# Display Board 1408 — outputs, and what the RIO shows on it
Complete definition of the RIO External Display board (P/N 1408 Rev. 1,
`DSP_1408` sheet 7), from the schematic, the board photos, the GAL decode,
and the firmware disassembly (`RIOv4_2.disasm.asm`).
## Outputs: light only — the board is electrically write-only
No signal leaves the board toward the RIO or anything else. J1 has no
readback line, matching the GAL's write-only `DSP_SEL*` decode, and the
PC↔RIO protocol has no display command — only the firmware writes it.
### 1. Eight multiplexed 7-segment digits (U2U9, LTS313A, red, common-cathode)
The ICM7228B (U1) does all driving. `HEX/B/SHD` is strapped high via 2.7 K
(R1): **hexadecimal decode mode, always enabled** — each digit renders 0F
plus a decimal point; no raw-segment access exists as built.
- **Segment bus** — U1 pins 16, 17, 20, 18, 21, 22, 23, 15 drive
`SEGA``SEGG`, `SEGDP`, shared by all digits (digit pins AG, DP =
10, 9, 8, 5, 4, 2, 3, 7). Segments source the multiplexed current
(~20 mA peak).
- **Digit commons** — U1 outputs `DSP1``DSP8` (pins 4, 25, 3, 1, 26, 2,
27, 24) each sink one digit's tied-together commons (CC1+CC2, pins 6+1).
`DSP1`→U2 (leftmost) … `DSP8`→U9 (rightmost).
- Multiplex scanning is internal to the ICM7228; the host only writes
digit registers.
From the 68HC11 the digits are bytes at **`$A000``$A007`** (`AS0-2` =
A0A2, strobed by `DSP_SEL*` = `E & /R/W`-qualified, arriving as the
7228's `/WR` on J1 pin 7). Data format per write: bits 03 = hex value
(`MD[00:03]``ID0-3`), bit 4 = decimal point (`MD[04]``ID7`; DP lights
when the bit is **low** — the firmware always sets it, so the DP is never
used). **`$A000` = leftmost digit (U2), `$A007` = rightmost (U9)**; the
firmware's render buffer (`$2038`, routine `$CB49`) fills right-to-left so
multi-digit hex numbers read naturally.
### 2. Twelve passive monitor LEDs on the "IBM printer port" header (J2) — an input, not an output
J2 (26-pin IDC, standard LPT-ribbon mapping to a DB25) is electrically
isolated from the display circuit; its `DD` nets touch nothing but LEDs
and 1 K resistors referenced to the PC's own ground (`IBM_GND`). With a PC
parallel port plugged in, the LEDs show: **D0D7** = data bits (J2 pins
3, 5, 7, 9, 11, 13, 15, 17), **D8** = `/STROBE` (pin 1), **D9D11** =
`/AUTOFD`, `/INIT`, `/SELECTIN` (pins 2, 6, 8). The LPT status returns are
strapped to ground so a PC streams without waiting. It is a built-in
parallel-port activity monitor / bench tool, powered entirely by the PC.
### 3. Nothing else
J1 (14-pin, from the RIO's EXTERNAL DISPLAY port) is all input:
`MD[00:04]` on pins 2, 4, 6, 8, 10; `AS0-2` on 1, 3, 5; `BF_DSP_SEL*` on
7; GND on 9, 11, 13; VCC on 12, 14.
## What the RIO firmware displays (v4.2)
All display writes go through `$CB49` (buffer render) or five canned
patterns at `$CB7C$CC52`, driven from three contexts: initialization,
the built-in **test mode**, and the **serial error/crash displays**
(below). During normal, healthy gameplay the display is static.
**Normal operation:** `F0000000` — written at cold boot (`$C068`) and warm
re-init (`$C64B`), then left alone.
**Test mode** — entered by typing the keypad sequence **A, 9, E** on a
cockpit keypad (`$C1CB` tracks the sequence at `$20F8`); entry sets flag
`$2421`, shows `F1000000`, and notifies the PC (`TestModeChange`, cmd
`0x8C` — see [PROTOCOL.md](../PROTOCOL.md)). Within test mode the next
keypad digit selects a sub-test; **F** ends a sub-test (back to
`F1000000`), **D** exits test mode (back to `F0000000`).
Display format convention: **left pair = test number, right = value**,
zeros as filler; the decimal points are never used.
| Key | Display | Test |
|-----|---------|------|
| *(entry)* | `F1000000` | test-mode banner |
| `0` | `00000000` | encoder-counter reset: presets the five 16-bit accumulators to `$FAFA` and re-reads all HCTL-2016s (`$C446`) |
| `1` | `0100hhll` | axis test, channel 01 — counter at `$A028/$A038` |
| `2` | `0200hhll` | axis test, channel 02 — `$A020/$A030` |
| `3` | `0300hhll` | axis test, channel 03 — `$A022/$A032` |
| `C` | `0C00hhll` | axis test, channel 0C — `$A024/$A034` |
| `4` | `0400hhll` | axis test, channel 04 — `$A026/$A036` |
| `5` | `050000nn` | button test — `nn` = index of the pressed input (scan at `$D004` over the pod input state at `$2152`), with lamp feedback |
| `6` | `06000003` | lamp test, pattern 3 (`$D34A`) — right digit is the pattern code |
| `7` | `07000001` | lamp test, pattern 1 (`$D370`) |
| `8` | `080000kk` | keypad test — `kk` = keypad status byte `$204B`, refreshed while scanning (`$CC7E`) |
In the axis tests `hhll` is the **live 16-bit quadrature count in hex**
(high:low = `$201D:$201E`, alternating with the raw latched bytes
`$2026:$2025` as the loop runs) — spin the stick/throttle/pedal encoder
and watch the number move. The channel IDs are literally the keypad keys
that start them, which is why the fourth axis reads `0C`.
## Error displays (the third use)
Two more display writers live in the serial machinery — the display is
also the RIO's **error annunciator**:
- **`E0` serial-diagnostics readout** (`$D5F2`) — `E0xxyyzz` where
`xx` = TX-ring overflow count (`$3187`, outbound byte dropped because
the ring was full, `$D66A`), `yy` = give-up count (`$3184`, `$D96A`
reply cycles whose 5 timeout retransmits all went unACKed), `zz` =
reply-teardown count (`$3185`, `$DA2F` — any reply cycle that needed
at least one retransmission; the counter behind a lone `E0000001`).
Semantics bench-confirmed 2026-07-19: display read `E0000105` after
one give-up + five teardowns. Each increment site immediately re-renders,
so the display live-updates as serial trouble accumulates. If a
cockpit's display reads `E0…` instead of `F0000000`, the serial link
has been dropping or retrying. Note there is **no threshold in stock
firmware** — the first event paints `E0000001` permanently; the
`_e0t5` patched images (`make_patch.py --e0thresh`, see
[RIOv4_2-ANALYSIS.md](../../rio-firmware/RIOv4_2-ANALYSIS.md)) keep
the display quiet until a counter reaches 5.
- **`dEAd` crash screen** (`$DAB8`, loop at `$DAB2`) — the TX-ISR ring
drain (`$D8C2`) looks each outgoing command byte up in an 8-entry
dispatch table at `$3158`; an unmatched byte means internal state
corruption, and the firmware jumps to an infinite loop that renders
`#$DE #$AD`**`dEAd`** followed by RAM bytes `$0000/$0001` (nothing
in this build writes them — vestigial debug data). The board is dead
until reset; there is no watchdog to rescue it (the MAX690's WDI is
not connected to the CPU and no strobe code exists in the firmware).
## Cross-references
- [README.md](README.md) — board family, photos, schematic page map
- [gal/README.md](gal/README.md) — `DSP_SEL*` decode (`$A000-$A00F`,
write-only) recovered from the GAL fuse map
- [`rio-firmware/RIOv4_2.disasm.asm`](../../rio-firmware/RIOv4_2.disasm.asm)
— display routines `$CB20/$CB36/$CB49` (buffer render), `$CB7C` (`F0`),
`$CBA7` (`F1`), `$CBD2`/`$CBFD` (lamp-test banners), `$CC28` (zeros),
test dispatcher `$C241`, entry-sequence tracker `$C1CB`