Pace TX bytes at the 9600-baud wire rate

vRIO wrote whole reply packets in one SerialPort.Write; through a
com0com null-modem (no UART) the host saw the bytes ~30-40 us apart,
a burst no real board can produce and the prime suspect in a rocky
game init. Replies now leave one byte per 10-bit frame (~1.04 ms), so
the 45-byte CheckRequest response takes ~47 ms like real hardware
(measured 0.94-1.10 ms gaps over a com0com pair).

- Transmit frames queue to a writer thread; each byte is scheduled
  against a monotonic slot deadline slot = max(prev + period, now),
  so the stream averages true 9600 baud without bursting after idle.
- After a write the schedule is floored at the actual emission time:
  a late wake-up can never be followed by a catch-up burst - two
  frames closer than the frame time is structurally impossible.
- 1 ms system timer resolution while the port is open (timeBeginPeriod)
  so the pacer sleeps most of each gap and only spins the last ~1.8 ms.
- Side benefit: UI clicks no longer block on SerialPort.Write (a
  stalled port could previously hang the UI for the 2 s write timeout).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-06 11:31:39 -05:00
co-authored by Claude Fable 5
parent e590b89c47
commit d26000f906
2 changed files with 119 additions and 11 deletions
+6
View File
@@ -41,6 +41,12 @@ device behavior grounded in the **real v4.2 firmware dump**
(`riojoy/rio-firmware/RIOv4_2-ANALYSIS.md`):
- ACKs every well-formed packet; NAKs bad-checksum packets.
- **TX is paced at the wire rate** — one byte per 10-bit frame (~1.04 ms at
9600 8N1), never closer. A virtual null-modem has no UART, so unpaced
writes would land at the host in microsecond bursts no real board could
produce; vRIO's writer thread schedules each byte against a monotonic
slot deadline instead, so e.g. the 45-byte CheckRequest response takes
the same ~47 ms it takes real hardware.
- `CheckRequest` → one `BoardOk` CheckReply per board (the 11 boards from the
legacy firmware's table). `VersionRequest` → configurable version,
default **4.2**.