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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user