Rework the shipped default profile around a required Xbox controller, refined from live-game testing: - All five axes are pad-only now (left stick / triggers / right stick); the key-axis bindings (arrows/WASD-style deflect and rate) are gone from the defaults, though the grammar remains supported. - Keyboard becomes the button field, geometry mirroring the panel: number row + QWERTY row = upper MFD bank, home + bottom rows = lower MFD bank as two 4-key blocks with an unbound gap key (G / B) standing in for the panel keypad gap, F1-F6 / F7-F12 = the Secondary / Screen columns top-to-bottom (0x16/0x17, 0x1E/0x1F deliberately unmapped), numpad = the full internal keypad with the hex keys on the operators (/ * - + . Enter = A-F). - Hat rides the arrow keys, Main stays on Space; Pinky / Middle / Upper / Panic are pad-only so no panic key sits inside the MFD field. - Pad B and LeftShoulder swap to Middle / Panic. - Rest of the throttle column and the external keypad stay unmapped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
103 lines
5.1 KiB
Markdown
103 lines
5.1 KiB
Markdown
# vRIO — virtual RIO cockpit device
|
||
|
||
A software replica of the cockpit **RIO** (Remote Input/Output) board: it opens
|
||
a COM port and speaks the **device side** of the RIO serial protocol, so any
|
||
host that expects the real hardware — most importantly
|
||
[RIOJoy](../riojoy/) — can talk to it without a cockpit attached.
|
||
|
||
The window is an interactive version of the cockpit control panel that
|
||
RIOJoy's profile editor draws (the same functional layout from the original
|
||
Win32 RIO design: five MFD clusters, four board columns, two keypads, encoder
|
||
gauges). But where the editor *edits bindings*, vRIO's cells are the physical
|
||
controls:
|
||
|
||
- **Left-click** a cell — momentary button press (`ButtonPressed`/`Released`
|
||
or `KeyPressed`/`Released` on the wire). **Right-click** — latch it down.
|
||
- **Drag** the X/Y box and the Z / L / R gauges — the five analog axes,
|
||
returned by the next `AnalogReply` (14-bit signed, 7-bit-pair packed).
|
||
Gauges span each axis' realistic hardware travel, not the full 14-bit
|
||
range: Z/L/R rest at raw 0 at the gauge bottom and travel to −800
|
||
(throttle — forward travel runs negative, matching RIOJoy's ratchet) or
|
||
+500 (spring-loaded pedals), and the stick covers ±80 around center —
|
||
the windows RIOJoy's calibrator expects.
|
||
- Cells shade to the **lamp state the host commands** (`LampRequest`:
|
||
off / dim / bright, with slow/med/fast flash), so RIOJoy's press-feedback
|
||
lights the on-screen panel just like the real buttons.
|
||
- **Keyboard and Xbox (XInput) controller input** drive the same controls
|
||
through a bindings file (`%APPDATA%\vRIO\bindings.txt`, created with
|
||
commented defaults on first run — *Edit bindings…* opens it, *Reload
|
||
bindings* applies edits live). Keys and pad buttons press any RIO address;
|
||
pad sticks/triggers and keys drive the axes in each axis' realistic travel
|
||
window, with deflect (spring-back), rate (throttle-style, position holds),
|
||
deadzone, and invert options. The default profile makes the controller
|
||
mandatory: all five axes live on the pad (left stick / triggers / right
|
||
stick = stick / pedals / throttle) and the keyboard covers the button
|
||
field — number row + QWERTY row = the upper MFD bank, home + bottom
|
||
rows = the lower MFD bank (4-key blocks split by an unbound gap key),
|
||
F1–F6 / F7–F12 = the Secondary / Screen columns, numpad = internal
|
||
keypad (hex keys on the operators), arrows + Space = hat + main, with
|
||
ABXY / dpad / shoulders on the pad's named buttons.
|
||
|
||
## Wire behavior
|
||
|
||
Protocol per `riojoy/docs/PROTOCOL.md` (9600 8N1, `[cmd][payload…][7-bit
|
||
checksum]`, ACK `0xFC` / NAK `0xFD` / RESTART `0xFE` / IDLE `0xFF`), with
|
||
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**.
|
||
- `ResetRequest` re-zeroes the targeted axis (or all).
|
||
- A NAK re-sends the last event up to **4 times**, then gives up with a
|
||
RESTART byte — the real board's retry budget.
|
||
- Optional **v4.2 reply-wedge emulation**: after retry exhaustion (or the
|
||
"Wedge analog now" button), analog requests are silently dropped — still
|
||
ACK'd, RX path alive — until a host `ResetRequest`, reproducing the
|
||
latch-leak fault the firmware analysis documents. Use it to exercise
|
||
RIOJoy's 5-second no-analog recovery watchdog.
|
||
|
||
## Using it with RIOJoy on one PC
|
||
|
||
The two apps need a crossed serial link. Install a
|
||
[com0com](https://com0com.sourceforge.net/) virtual null-modem pair
|
||
(e.g. `COM5 ⇄ COM6`), then:
|
||
|
||
1. Run `VRio.App`, pick `COM5`, **Open**.
|
||
2. Point RIOJoy at `COM6`.
|
||
|
||
RIOJoy's DTR open-pulse shows up in the wire log (DSR handshake), its ~55 ms
|
||
analog polling drives the "analog polls served" counter, and every click on
|
||
the vRIO panel arrives at RIOJoy as real cockpit input. Two physical PCs with
|
||
a null-modem cable work the same way.
|
||
|
||
## Repository layout
|
||
|
||
| Path | Contents |
|
||
|------|----------|
|
||
| `src/VRio.Core` | Protocol framing/builder/parser, the `VRioDevice` state machine, serial pump, panel layout data (class library) |
|
||
| `src/VRio.App` | WinForms panel UI |
|
||
| `tests/VRio.Core.Tests` | xUnit tests for the protocol + device engine |
|
||
|
||
## Building
|
||
|
||
Same toolchain as RIOJoy: **.NET SDK** (8.0+) with the **.NET Framework 4.8**
|
||
targeting pack; apps target net48 so deployed builds run in-box on
|
||
Windows 10/11.
|
||
|
||
```sh
|
||
dotnet build VRio.sln -c Release
|
||
dotnet test VRio.sln
|
||
```
|
||
|
||
Interop is additionally verified against RIOJoy's real `RioSerialLink`
|
||
(version/check/analog/lamp/button/keypad/reset round-trips over an in-memory
|
||
transport) — see the RIOJoy repo for the host side.
|