From b5e2ad35af048f0a2e41183ded4ae1c5bf6504f3 Mon Sep 17 00:00:00 2001 From: Cyd Date: Sun, 19 Jul 2026 15:39:03 -0500 Subject: [PATCH] E0-threshold patch bench-verified: PASS at E0000105; counter semantics corrected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Display observation (Cyd, on-cabinet): held F0000000 through the clean handshake and four NAK-then-ACK sub-threshold cycles, flipped exactly at the 5th teardown to E0000105. That reading recalibrates the counters: $3184 counts give-up cycles (not per-retransmit) and $3185 counts teardowns of any imperfect reply cycle — the counter behind the original lone E0000001. Also recorded: 5 retransmits per cycle (not 4), reply- await arms only after the complete frame, NAK forces exactly one counted retransmit, and a late ACK cannot rescue a cycle once retries begin. Tool predictor updated to the confirmed semantics. Co-Authored-By: Claude Fable 5 --- tools/RioSerialMonitor/E0Test.cs | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tools/RioSerialMonitor/E0Test.cs b/tools/RioSerialMonitor/E0Test.cs index a228fe1..b150d60 100644 --- a/tools/RioSerialMonitor/E0Test.cs +++ b/tools/RioSerialMonitor/E0Test.cs @@ -170,19 +170,22 @@ internal static class E0Test } // Handshake bookkeeping: fold any retries/give-up into the prediction. + // Bench-calibrated counter semantics (2026-07-19, confirmed on the + // display): $3184 = timeout-retry cycles (give-ups), $3185 = reply + // teardowns, i.e. any cycle that needed at least one retransmission. await Task.Delay(300); byte[] hs = Drain(); - int retx = Math.Max(0, CountAll(0x86) - 1); // $3184 prediction - int giveup = SeenAll(0xFE) ? 1 : 0; // $3185 prediction + int cycles = SeenAll(0xFE) ? 1 : 0; // $3184 prediction + int teardowns = CountAll(0x86) > 1 ? 1 : 0; // $3185 prediction Console.WriteLine(); Console.WriteLine($"== E0-threshold test :: {transport.Description}, firmware {version?.Major}.{version?.Minor} =="); Console.WriteLine($" threshold {Threshold}; phase A: {holdEvents} sub-threshold event(s), phase B: {flipEvents} give-up event(s)"); - if (retx > 0 || giveup > 0) - Console.WriteLine($" note: handshake cost {retx} retransmit(s){(giveup > 0 ? " + a give-up" : "")}; predictions include them."); + if (cycles > 0 || teardowns > 0) + Console.WriteLine($" note: handshake was not clean (teardowns={teardowns}, give-ups={cycles}); predictions include it."); Console.WriteLine(" HANDS OFF buttons/keypads for the whole run."); Console.WriteLine(); - string expected = Expected(retx, giveup); + string expected = Expected(cycles, teardowns); Console.WriteLine($">>> WATCH THE 8-DIGIT DISPLAY. It should read {expected} right now. <<<"); await Task.Delay(4000); @@ -196,7 +199,7 @@ internal static class E0Test Console.WriteLine(); Console.WriteLine("== done =="); - Console.WriteLine($" final predicted counters: retx=${retx:X2} giveup=${giveup:X2} -> display {Expected(retx, giveup)}"); + Console.WriteLine($" final predicted counters: $3184=${cycles:X2} $3185=${teardowns:X2} -> display {Expected(cycles, teardowns)}"); Console.WriteLine(" PASS = display held F0000000 through every sub-threshold line above and"); Console.WriteLine(" matched the E0 predictions after the threshold crossing."); Console.WriteLine(" (Stock firmware flips at the very first retry.) DTR reset restores F0."); @@ -225,19 +228,19 @@ internal static class E0Test return false; } - retx += Math.Max(0, transmissions - 1); - if (sawRestart) giveup++; + if (transmissions > 1) teardowns++; // $3185: imperfect cycle + if (sawRestart && mode == AckMode.Never) cycles++; // $3184: give-up Console.WriteLine($"[event {eventNo}] {phase}: reply x{transmissions} " + - $"({transmissions - 1} retries), give-up={sawRestart} " + - $"-> retx=${retx:X2} giveup=${giveup:X2}"); - Console.WriteLine($" >>> DISPLAY SHOULD NOW READ: {Expected(retx, giveup)} <<<"); + $"({transmissions - 1} retransmit(s)), give-up cycle={mode == AckMode.Never} " + + $"-> $3184=${cycles:X2} $3185=${teardowns:X2}"); + Console.WriteLine($" >>> DISPLAY SHOULD NOW READ: {Expected(cycles, teardowns)} <<<"); await Task.Delay(4000); return true; } - string Expected(int r, int g) => - r >= Threshold || g >= Threshold ? $"E000{r:X2}{g:X2}" : "F0000000"; + string Expected(int cy, int td) => + cy >= Threshold || td >= Threshold ? $"E000{cy:X2}{td:X2}" : "F0000000"; byte[] Drain() {