127s mash at 31250: zero wedges — but 5655 framing resyncs, duplicate
replies (215% of poll slots) and AbandonCount=65 reveal the board's
reply ACK-wait scales with byte time: ~5+ms at 9600 (USB beats it,
zero framing) vs ~1.6ms at 31250 (USB cannot). All 65 retry
exhaustions self-recovered through the patched give-up path — the
strongest field proof of the latch fix yet; unpatched firmware would
have wedged on the first. Verdict recorded in ANALYSIS.md: cabinets
run the 9600 patched chip; 31250 stays a bench branch until the retry
window is widened in firmware.
Tool: before-snapshot now retries once (can lose the post-DTR boot
race, as this run showed); evidence log archived.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Stopping early is a real operator workflow (finger fatigue); previously
an interrupt died summary-less and could orphan a process holding the
COM port. CancelKeyPress now breaks the run loop, snapshots the after-
counters, and prints the summary with the actual elapsed duration.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On a wedged (fully silent) board the receive loop sits in a pending
net48 serial read that ignores cancellation; awaiting the link before
closing the port hangs the tool at run end and loses the summary -
exactly what happened on the first real baseline run (the board wedged
at 0.62s and stayed dead, so no byte ever completed the read). Close
the port first (same order RioCoordinator.Teardown uses); applies to
both monitor and --mash modes. Selftest unaffected (its fake transport
honors cancellation, which is why it never caught this).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
make_patch.py gains --baud31250: one byte beyond the wedge patch — the SCI
init operand at $D62B ($30 -> $02). BAUD $30 = /13 prescale, /1 divider
(2MHz E / 208 = 9615); $02 = /1, /4 -> 31250 exactly, 3.3x faster. The
init write also confirms the 8MHz crystal, which is why 19200/38400 are
unreachable and why 62500/125k are left alone pending an ISR cycle count.
- 24 bytes changed vs original (sha256 9f866cf3...); re-disassembly diff
vs the classic patched image shows exactly the one operand line, and
the classic build still reproduces 3fc8170c... (script regression-safe).
- PC side: SerialPortTransport takes an optional baudRate (default 9600,
runtime untouched); RioSerialMonitor + --mash accept --baud 31250.
- Caveats documented in README/ANALYSIS: non-standard rate (FTDI-class
adapters only, no 16550s); native games still speak 9600 so this chip
is bench/RIOJoy-only; validate the wedge patch at 9600 first.
275 tests green; mash --selftest regression unchanged (FAIL/exit-1).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New --mash mode (tools/RioSerialMonitor/MashTest.cs) mechanizes the
wedge-patch validation plan from RIOv4_2-ANALYSIS.md:
- Runs the live link with the app's >5s reset-recovery DISABLED so a
board wedge stays observable, and echoes lamps on every press
(lamp/reply collisions are the wedge trigger).
- Gap timing uses ANY AnalogReply packet (0xFE sentinels included -
a sentinel still proves the reply path is alive); logs a gap
histogram + top-10 longest gaps with timestamps.
- WEDGE detector: analog silent past the threshold (default 2s) ->
beep + banner; on resume, classifies self-recovered (patched
expectation) vs button-revived (button event within 300ms of resume,
the unpatched signature) vs unresolved at run end.
- Board self-reported RestartCount/AbandonCount/FullBufferCount
snapshotted before/after via CheckRequest, delta printed
(7-bit wrap-aware).
- Fixed-layout summary teed to riomash-<label>-<stamp>.log so
baseline-vs-patched runs diff directly. Exit 0 = no wedge, 1 = wedge.
--mash --selftest drives the whole instrument against a scripted
in-memory board (SelftestTransport) that goes silent at t=4.0s and
revives 200ms after a button at t=6.5s: verified end-to-end - alarm at
6.0s, wedge classified button-revived (2.75s), counter delta +4/+0/+1,
verdict FAIL, exit 1. Use it to sanity-check the alarm at the cabinet.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>