Phase 2: serial + RIO protocol core (RioJoy.Core) with unit tests

Port the RIO wire protocol from legacy/riovjoy2.cpp into testable C#:

- Protocol/: command + length table, 7-bit checksum, packet builder, and a
  streaming receive-side framing state machine (PacketParser) that mirrors the
  legacy ReadCommBlock framing/resync (high-bit-mid-packet abort). Typed RIO->PC
  decodes: AnalogReport (14-bit sign-extend), VersionInfo, CheckStatus; lamp-state
  composition.
- Serial/: RioSerialLink drives an async receive loop with ACK/NAK reply policy
  (legacy force-accept vs. opt-in VerifyInboundChecksum), the analog poll timer,
  and the >5s reset-recovery watchdog. IRioTransport abstracts the COM port; the
  SerialPort-backed transport does 9600 8N1 + DTR reset pulse, and acquire/release
  is just create/dispose (foundation for native-game serial yield).
- tests/RioJoy.Core.Tests: 54 xUnit tests covering checksum, framing/resync,
  builder round-trips, analog sign-extension + sentinel rejection, lamp combos,
  and the read loop driven against an in-memory fake transport.

Hardware verification (version/check/analog against a cabinet) remains; it can't
be done off-device.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-06-26 13:04:03 -05:00
co-authored by Claude Opus 4.8
parent 39a3dab1fc
commit b3cb764f4d
26 changed files with 1553 additions and 7 deletions
+15 -6
View File
@@ -113,12 +113,21 @@ tray menu is always available.
- Test harness (throwaway C#) wiggles axes/buttons; verify in `joy.cpl`.
- Test-signing setup for the cabinets.
### Phase 2 — Serial + RIO protocol core (`RioJoy.Core`)
- `SerialPort` wrapper; packet parser/builder (length table, 7-bit checksum,
ACK/NAK, framing resync).
- Analog poll timer + >5 s reset-recovery.
- **Clean COM-port acquire/release** (foundation for serial yield).
- Verify against hardware: version reply, check reply, analog stream.
### Phase 2 — Serial + RIO protocol core (`RioJoy.Core`) — code-complete ✅
Implemented in `src/RioJoy.Core/Protocol` + `Serial`, covered by
`tests/RioJoy.Core.Tests` (xUnit, 54 tests):
- Packet parser/builder: command/length table, 7-bit checksum, control chars,
framing resync on a high-bit byte mid-packet (`PacketParser`, `PacketBuilder`).
- Typed RIO→PC decodes: `AnalogReport` (14-bit sign-extend), `VersionInfo`,
`CheckStatus`; lamp-state composition (`RioLampState`).
- `RioSerialLink`: async receive loop with ACK/NAK policy (legacy force-accept
vs. opt-in `VerifyInboundChecksum`), analog poll timer + >5 s reset-recovery.
- `IRioTransport` abstraction with a `SerialPort`-backed implementation
(9600 8N1, DTR reset pulse); **clean COM-port acquire/release** = create/dispose
the transport (foundation for serial yield). The read loop is tested against an
in-memory fake transport.
-**Remaining:** verify against real hardware (version reply, check reply,
analog stream) — needs a cabinet; can't be done off-device.
### Phase 3 — Input mapping + output routing
- Port `iRIO` decode and routing precedence (keyboard/mouse/joy/hat/RIO-command).