Vial settings and diagnostics

In Vial's Keymap → User group, assign a settings keycode to a physical key on any layer, then press it. Settings persist in the Coordinator's flash (the tower's, or a Coordinator cat's); the tower resends colors when a cat reconnects. The setup page (./lx setup ui, its Sensors and LEDs step) writes the sensors' settings and the layer colours into the same record before the Coordinator's firmware, or later on their own (cargo provision settings, provisioning); what it does not name stays as stored. A Coordinator cat has no radio and no link counters: on it, CH>, CH?, ST? and BAT? do nothing.

LabelOperation
MS+ / MS−Adjust mouse speed
SC+ / SC−Adjust scroll speed
LC> / LC<Cycle the currently active layer's LED color
RSTReset speeds and colors, keeping the radio channel, the motion yaw and the gyro modes
CH>Move to the next radio-channel candidate
CH?Type the applied channel into the focused text field
ST?Type a STATS? diagnostic line into the focused text field
BAT?Type each hand's presence and battery into the focused text field
YL> / YL<Turn the left hand's mouse motion (or its gyro's axes) 5° clockwise / anticlockwise
YR> / YR<The same for the right hand
GYThe gyro air mouse: held or tapped, as each hand's gyro mode says (below)
SVCHeld 2 s: service mode, for saving settings without BOOT

The bottom module sits fixed in its lid; the Coordinator turns each hand's motion by the angle the lid seats the sensor at, plus the YL/YR trim. Push the hand straight forward: if the cursor leans right, tap <; if it leans left, tap >. A breakout on the bench, outside a lid, reads right lying with its +y end pointing away from you (mechanical/dimensions.json bottom_module); trim any other way it lies.

Focus a text editor before using readouts. ST? can take 5–20 seconds and types HID characters directly, bypassing the keymap; it uses only characters that come out the same on a US and a German host (a–x, digits, space, comma). l, r, t identify left, right and tower counters; l none or r none means no snapshot yet. Each field is its name followed by its value (rtx12), and a pair is split by a comma (tx1234,3). Counters restart at that device's boot.

BAT? types one section per hand: l present bat85,3870,12 r silent bat none is the left hand heard, at 85 % and 3870 mV as of 12 s ago, and the right hand not heard for 75 s (two and a half of its 30 s telemetry reports) with no battery report ever (no battery, or none yet). stale follows a reading older than 75 s, low one at or under 15 %. On the T-Dongle the same status is the screen's top strip (L 85%, L 85%? when stale, L on for a hand without a battery, L x for a silent one, blinking red when low) with the voltages or a charge left warning along the bottom; its backlight lights for 30 s on a layer, lock or presence change and on a low cell, not on a routine report.

For diagnosis: growing rtx with tower rep suggests lost acknowledgements; with ooo, lost key frames. ovf means a filled key queue, kbto a stalled keyboard channel, and rec snapshot reconciliation. Persistent ssf indicates settings flash-write failures. Unexpectedly increasing ses suggests repeated session recovery; hign can indicate mismatched provisioned masters. Definitions and the exact output format live in telemetry.rs, with cat counters in protocol/telemetry.rs.

Keycode labels and steps are owned by settings.rs and checked against vial.json. The default Engram-derived bindings live in lynxgram.rs; customize them in Vial.

Gyro air mouse

A hand with the gyro bottom module (bg) moves the pointer when it turns: sideways for a turn about the vertical, up and down for a tilt of the fingertips; a roll does nothing. Its mode and speed are set per hand on the setup page; no key changes them, and RST resets its speed, not its mode. The modes, for the GY key:

ModeThe gyro moves the pointer
offnever (the firmware's default)
while heldwhile a GY key is held
togglefrom one GY tap to the next
alwaysalways; holding GY pauses it, to bring the hand back to a comfortable pose

The cat measures the gyro's zero-rate error itself: keep the hand still for a second after it starts (its log says calibrated), and it re-measures at every later rest. If a tilt moves the pointer sideways, trim the hand with YL/YR; the gyro's mounting angle is derived from the lid's drawing and not yet checked on a built module (gyro.rs).

Service mode

Holding SVC for 2 s takes the Coordinator off the keyboard: it writes any pending setting, stops RMK and gives its USB port back to the serial unit, which the host sees as the board's serial port again, by its MAC. Every cat blinks both LEDs blue, the Coordinator cat and the Satellites alike: the keyboard state the Coordinator keeps sending carries it. The setup page's Save the settings to the Coordinator (or cargo provision settings) then writes over that port: espflash resets the board into its bootloader itself and, after the write, into its firmware, so neither BOOT nor RST is pressed and a closed case stays closed. With no write, the board restarts as a keyboard after 2 minutes. Read from the Coordinator first shows what it stores, the Vial keys' changes included, and keeps it in its bootloader with no time limit until the save; a save writes only what changed on the page. Reflash the Coordinator flashes its firmware the same way, keeping its pairing and settings. The why and the timings are in service.rs.

LYNXgram binds SVC on layer 1 at Lp5; a lone right cat reaches it on layer 3 (both layer keys), at Rp5. A keymap stored before SVC existed keeps its own bindings (keymap persistence): bind SVC in Vial once. Only a running firmware has the key: a board's first flash, and a board whose firmware does not start, still take BOOT.

One hand

A setup with one cat starts from that hand's one-hand keymap: a cat Coordinator with no paired cat, or a tower paired with one cat. Both hands get LYNXgram as before. The hand keeps its own LYNXgram keys and reaches the other hand's at the mirrored keys:

HoldThe hand types
nothingits own LYNXgram keys
t25the other hand's keys, index for index and thumb for thumb
t15its own LYNXgram layer 1 (numbers, symbols)
t25 + t15the other hand's layer 1

The two thumb keys this takes are the left's GUI and Alt in LYNXgram: on one hand GUI sits on i7 and Alt on m0 (the right's wheel push). Vial unlocks with that hand's i4 + i1, on a tower too. The rule and its check that every LYNXgram binding stays reachable are in keymap_profile.rs.

Keymap persistence

Vial edits live in the Coordinator's rmk_storage partition (the tower's, or a Coordinator cat's); the settings above have a partition of their own. RMK erases its storage at boot when the stored hash differs from the firmware's, and it computes that hash from the build time whenever its build script runs:

  • A rebuild or reflash from the same target/ keeps the Vial edits.
  • The first build after target/ was cleaned, the container image or toolchain changed, or the RMK version changed erases them once, at the first boot of that firmware. Note your keymap in Vial (or save it to a file there) before such a change.
  • A changed default keymap in lynxgram.rs, or a changed default behaviour setting, does not reach a tower whose storage survived. RMK stores the whole keymap at its first boot, and the stored keymap wins over the code's defaults.
  • A changed setup does: when the Coordinator's hands change (a lone cat gets a partner, a tower is paired with one cat instead of two), its next boot replaces the stored keymap with the new setup's default, Vial edits included. The settings record keeps which default the stored keymap came from. Save your keymap in Vial before pairing differently.

To apply new defaults to such a tower, set clear_layout: true in storage_config() in usb.rs, flash, then remove it and flash again. It rewrites the keymap and behaviour settings from the defaults. clear_storage: true erases all of RMK's storage instead. Either takes effect at every boot while set, so Vial edits made meanwhile are lost at the next boot.

Vial integration gotchas

The pinned integration uses custom keycodes because it does not expose arbitrary preferences menus. Keep their order stable so saved bindings retain their meaning.

For an empty layout, compare with the minimal KLE properties in the shipped vial.json; decorative properties have broken rendering in past tests. For an empty Matrix Tester, check RMK's host_lock feature. The tested unlock pair is VIAL_UNLOCK_CELLS in key_index.rs — i4 + i1 of the left hand on a tower, of its own hand on a Coordinator cat; do not replace it with an untested same-row pair. build.rs owns compression and host tests check matrix labels.