Skip to content

feat(hid): RC-28 Button Mapping dialog with press/hold, PTT mode, and device info panel #3323

Description

@w5jwp

Follow-up to #3293 (feat(hid): initial Icom RC-28 encoder support). That PR wired up the hardware; this request exposes the configuration that operators need to use it productively.


Request preparation

  • I used an AI assistant to help structure this request
  • I checked for existing issues covering the same feature

What would you like?

Problem

The RC-28's three buttons — F1, F2, and TX bar — have hardcoded defaults (F1=StepUp, F2=StepDown, TX bar=PTT) that can only be changed by hand-editing HidKeyAction0/1/2 in AppSettings. There is no UI for it. Three things compound this:

  1. Half the hardware is unused. The RC-28 supports two gestures per button (short press and hold), but AetherSDR's parser only emits a single press event. The FlexRC-28 companion app uses a 600 ms threshold to distinguish short press from hold, mapping each F button to two independent action slots. Without hold detection, F1 and F2 each offer one action instead of two.

  2. PTT has only one mode. The TX bar is always momentary (hold-to-talk). Many operators want a toggle/latch mode so they can lift their hand off the controller during a QSO. The right place to choose between momentary and latched is a radio button in the mapping dialog — not a timed gesture.

  3. No UI indicator of any kind. The RC-28 is silently active once HidEncoderEnabled=True. There is no way to see whether the device is recognized, what path it's on, or debug why a button isn't doing what was set.


Proposed solution

Step 1 — New Settings menu entry

Add "RC-28 Button Mapping..." to the &Settings menu, following the pattern of the existing "MIDI Mapping..." and "Ulanzi Dial Mapping..." entries in MainWindow.cpp. Gated on #ifdef HAVE_HIDAPI. The entry is always visible but opens a dialog that shows a "no device" state when the RC-28 is not enabled or not connected.

Step 2 — RC28MappingDialog

A new RC28MappingDialog : PersistentDialog with four sections:


Section A — Device Info (read-only, live-updating via HidEncoderManager::connectionChanged)

Field Source
Status Connected / Not connected (colored dot)
Device "Icom RC-28" (from HidDeviceParser::supportedDevices() name table)
VID:PID 0x0C26:0x001E (from HidEncoderManager::vendorId/productId())
Path hid_device_info::path via hid_get_device_info() — e.g. /dev/hidraw0 on Linux
Serial hid_device_info::serial_number — may be blank on some RC-28 units
Firmware hid_device_info::release_number (BCD, e.g. 0x0100 → "1.00")

Requires capturing these fields during HidEncoderManager::open() by calling hid_get_device_info(m_device) after a successful hid_open(), storing path/serial/release as new members with matching getters.


Section B — TX Bar

Two mutually exclusive radio buttons (not a dropdown — only two choices):

  • Momentary — hold to transmit, release to stop (current behavior, default)
  • Latched — press to transmit, press again to stop

Saves to new key HidRC28PttMode ("Momentary" / "Latched"). Implementation: in the MainWindow buttonPressed lambda, check this key and either use the existing hold-to-talk logic or flip a m_rc28PttLatched bool on each press event. No timer-based auto-latch — the operator chooses the mode explicitly.


Section C — F1 and F2 Button Assignments

Five action slots:

Slot Default Settings key
F1 — Short press StepUp HidKeyAction0 (existing)
F1 — Hold (600 ms) TuneFast HidKeyAction0Hold (new)
F2 — Short press StepDown HidKeyAction1 (existing)
F2 — Hold (600 ms) ModeCycle HidKeyAction1Hold (new)

Each row is a GuardedComboBox. Hold detection: a QTimer started in the buttonPressed lambda on action==0 and cancelled on action==1; fires the hold action at 600 ms.

Full action list (current + additions drawn from the FlexRC-28 companion app):

ID Label
StepUp Step Up
StepDown Step Down
StepCycle Cycle Step Up
TuneFast Toggle Fast Tuning (new)
LockDial Lock/Unlock Encoder (new)
ToggleRit Toggle RIT
ClearRit Clear RIT
ToggleXit Toggle XIT
ClearXit Clear XIT
ModeCycle Cycle Mode (LSB/USB/CW/AM) (new)
BandCycle Cycle Band (160m–6m) (new)
SnapKHz Snap to Nearest 1 kHz (new)
ToggleMox Toggle MOX
ToggleMute Toggle Mute
ToggleLock Toggle Slice Lock
NextSlice Next Slice
PrevSlice Previous Slice
VolumeUp Volume Up
VolumeDown Volume Down
None No Action

F1 LED lights when TuneFast is the active F1 action and fast-tune mode is on. F2 LED mirrors active slice RIT state. TRANSMIT and LINK LED behavior is unchanged from #3293.


Section D — Debug / Activity Log

A compact scrolling log (QPlainTextEdit, read-only, 50-line cap) showing live button events while the dialog is open. Format: [HH:MM:SS] F1 press → StepUp / [HH:MM:SS] F2 hold → ModeCycle / [HH:MM:SS] TX bar press → TX ON (Latched). A Clear button empties the log. The dialog connects to HidEncoderManager::buttonPressed and resolves the action name before appending.


Implementation notes

  • New files: src/gui/RC28MappingDialog.h / .cpp
  • HidEncoderManager::open() — call hid_get_device_info() post-open; store m_devicePath (QString), m_serialNumber (QString from wchar_t*), m_releaseNumber (uint16_t); add getters
  • MainWindow::setupHidEncoder() — add QTimer* m_rc28HoldTimer for F1/F2 hold detection; wire buttonPressed to RC28MappingDialog::appendEvent() when dialog is open
  • MainWindow::createMenus() — add "RC-28 Button Mapping..." after "MIDI Mapping..." (~line 8212), gated on #ifdef HAVE_HIDAPI
  • New settings keys: HidRC28PttMode, HidKeyAction0Hold, HidKeyAction1Hold
  • New action handlers in the buttonPressed lambda: TuneFast, LockDial, ModeCycle, BandCycle, SnapKHz

Prior art consulted

  • FlexRC-28 (src/controller.js, index.html) — 5-slot button model, 600 ms hold threshold, action set, F1/F2 LED state rules, button assignment grid UI
  • wfview (src/usbcontroller.cpp) — individual per-LED control, device info capture at connect time
  • src/gui/FlexControlDialog.hPersistentDialog pattern to follow
  • MainWindow.cpp:8212 — where the new Settings menu entry lands

Out of scope

  • TRANSMIT and LINK LED behavior — unchanged
  • Other HID devices (PowerMate, ShuttleXpress, StreamDeck+)
  • RC-28 connected to the FlexRadio USB upstream port

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceNew FeatureNew feature requestexternal devicesFlexControl, MIDI, serial port, USB peripheralsmaintainer-reviewRequires maintainer review before any action is taken

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions