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>
This commit is contained in:
Cyd
2026-07-19 15:40:57 -05:00
co-authored by Claude Fable 5
parent b5e2ad35af
commit 4ac688dfa5
3 changed files with 47 additions and 23 deletions
+6 -3
View File
@@ -99,9 +99,12 @@ 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` = reply-retransmit count (`$3184`,
the game failed to ACK a reply, `$D96A`), `zz` = reply-teardown/give-up
count (`$3185`, `$DA2F`). Each increment site immediately re-renders,
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
+24 -10
View File
@@ -419,11 +419,19 @@ detail in [`docs/hardware/display-board-1408.md`](../docs/hardware/display-board
`$FD`** (`$3170`). The TX ISR sends pending ACK/NAK ahead of reply
data (`$D8A6`). Control bytes `$FE` RESTART / `$FF` IDLE.
- **Outbound reply delivery**: replies must be ACKed by the game; the
retry machine (`$D90E`/`$D9BE`) retransmits up to 4 times
(`INC $3184` per retry), then gives up — sends `$FE` RESTART,
`INC $317A`, teardown at `$DA2F` (`INC $3185`). The give-up teardown
is where the `$2521` wedge leak lives (see above; fixed in the patched
images).
retry machine (`$D90E`/`$D9BE`) retransmits — **5 times** (bench
2026-07-19; the earlier code reading of "4" was wrong) — then gives
up: sends `$FE` RESTART, `INC $317A`, `INC $3184` (give-up counter),
teardown at `$DA2F` (`INC $3185` — teardowns: ANY reply cycle that
needed at least one retransmission ends here, including NAK-recovered
ones, so `$3185` is the counter behind a lone cockpit `E0000001`).
The give-up teardown is where the `$2521` wedge leak lives (see
above; fixed in the patched images). Bench-observed await behavior:
the ACK wait arms only after the COMPLETE reply frame is sent
(mid-frame ACK/NAK/RESTART is ignored); a game NAK of the completed
frame triggers exactly one immediate counted retransmit; once the
first retry timeout lapses the cycle runs blind to give-up — a late
ACK cannot rescue it.
- **RX overrun: unhandled.** The RX ISR reads SCSR/SCDR but never acts
on the overrun flag — dropped bytes just corrupt the frame and
surface as checksum NAKs. This is why the 125000-baud bench run
@@ -443,7 +451,7 @@ detail in [`docs/hardware/display-board-1408.md`](../docs/hardware/display-board
`$DB07-$DB3D`: silent hang, no display, no recovery.
- **Error counters** `$3173-$317B` (ACK/NAK/retry/give-up bookkeeping)
and the three displayed ones `$3187/$3184/$3185` — rendered as
`E0 <ovf> <retry> <giveup>` by `$D5F2` at every increment.
`E0 <ring-ovf> <give-ups> <teardowns>` by `$D5F2` at every increment.
### Hardware (RIO_1407 sheet 2)
@@ -482,7 +490,13 @@ Built variants (wedge fix + threshold 5):
| `RIOv4_2_patched_e0t5.bin` | 9600, native-game compatible | `9c21ac7199fb` |
| `RIOv4_2_patched_31250v2_e0t5.bin` | 31250 + widened ACK-wait (FastRIO) | `b43032b016d7` |
**Not yet burned or bench-verified.** To verify on hardware: burn, then
force reply give-ups (e.g. kill the host mid-poll repeatedly) — the
display must stay `F0000000` through the 4th event and flip to
`E00000 05` on the 5th; `RIO_TAP`/mash regression as usual.
**Bench-verified 2026-07-19 (9600 image, burned): PASS.** Driven by
`RioSerialMonitor --e0test` (DTR reset → clean handshake → four
NAK-then-ACK sub-threshold teardown cycles → one unACKed give-up
cycle): the display held `F0000000` through the handshake and all four
sub-threshold teardowns — stock paints `E0…` at the first — and flipped
exactly at the 5th teardown to **`E0000105`** (`$3187`=00 overflows,
`$3184`=01 give-up, `$3185`=05 teardowns), confirmed by eye on the
cockpit display. Mash regression still to run. The 31250v2_e0t5 image
is the same patch on the certified FastRIO base and is expected to
behave identically.
+17 -10
View File
@@ -7,15 +7,22 @@ namespace RioSerialMonitor;
/// E0-threshold firmware verification (rio-firmware `--e0thresh` images).
///
/// Two phases against a DTR-reset board (counters zeroed, display F0000000):
/// - Phase A (gate hold): analog requests whose reply we ACK only after the
/// first retransmit — each event increments the board's retransmit
/// counter ($3184) by a small sub-threshold amount, calling the display
/// renderer every time. The _e0t5 gate must keep the display F0000000;
/// stock firmware paints E0... at the first retry.
/// - Phase B (flip): analog requests we never ACK — the board runs the full
/// retry cycle (observed: 5 retransmits) and gives up ($3185++, RESTART
/// $FE). The counters cross the threshold and the display must flip to
/// the E0 readout, which the tool predicts from observed traffic.
/// - Phase A (gate hold): analog requests answered NAK-then-ACK — NAKing
/// the COMPLETED reply frame forces exactly one immediate retransmit,
/// ACKing that retransmit ends the cycle. Each event increments the
/// teardown counter $3185, invoking the display renderer sub-threshold.
/// The _e0t5 gate must keep the display F0000000; stock firmware paints
/// E0... at the first event. (Responses must follow the complete frame:
/// the board arms its reply-await only when the frame finishes sending,
/// and once the first retry timeout lapses the cycle runs blind.)
/// - Phase B (flip): analog requests we never ACK — the board runs the
/// full retry cycle (5 retransmits), gives up ($3184++, RESTART $FE)
/// and tears down ($3185++). $3185 crosses the threshold; the display
/// must flip to the E0 readout the tool predicts from observed traffic.
///
/// Bench 2026-07-19 (9600 e0t5 chip): PASS — display held F0000000 through
/// the handshake and all four phase-A teardowns, flipped exactly at the
/// 5th teardown to E0000105 ($3187=00, $3184=01, $3185=05).
///
/// dotnet run --project tools/RioSerialMonitor -- --e0test [port]
/// [--baud rate] [--hold n] [--flip n]
@@ -111,7 +118,7 @@ internal static class E0Test
{
buffer.Add(tmp[i]);
// Frame tracking: respond only once the FULL reply
// frame is on the wire the board arms its
// frame is on the wire the board arms its
// reply-await when the frame finishes sending; a
// response mid-frame is ignored.
if (frameCountdown > 0)