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>
133 lines
7.1 KiB
Markdown
133 lines
7.1 KiB
Markdown
# 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 (U2–U9, 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 0–F
|
||
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 A–G, 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` =
|
||
A0–A2, strobed by `DSP_SEL*` = `E & /R/W`-qualified, arriving as the
|
||
7228's `/WR` on J1 pin 7). Data format per write: bits 0–3 = 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: **D0–D7** = data bits (J2 pins
|
||
3, 5, 7, 9, 11, 13, 15, 17), **D8** = `/STROBE` (pin 1), **D9–D11** =
|
||
`/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`
|