[tuning] Restore Flex band-stack selection keys#1887
Conversation
There was a problem hiding this comment.
Thanks for this thorough PR, @jensenpat — the write-up, behavior matrix, and test plan are all excellent. The root cause analysis (UI labels carrying the m suffix while the pass-through set uses bare numbers) is spot-on, and this is clearly the right fix for the long-running band-stack regression.
I read through the diff carefully and have a few observations:
Looks Good
- Label stripping logic is well-guarded: only strips
mwhen the bare result is a known native band, so XVTR names like"2m"correctly fall through to the XVTR lookup. Clean approach. - Removing the direct-tune fallback is the right call. The old fallback silently overwrote radio state and was the source of the regression symptoms reported across many issues.
ordervs map index for XVTR — using the Flexorderfield forX<n>selectors matches the API spec and is an important correctness fix over the priorit.key()approach.m_bandSettings.setCurrentBand()moved inside the success branch — good, this avoids updating Aether's band tracking when the command is refused.XvtrInfo::orderdefaults to-1— clean sentinel for "radio didn't report this field."
Minor Points (non-blocking)
-
orderparse without validation: InRadioModel.cpp,kvs["order"].toInt()will silently return0for non-numeric strings, which is a valid order value. This could cause an XVTR entry to appear valid (order >= 0) when the radio sent garbage. AtoInt(&ok)check would be slightly more defensive at this system boundary, though in practice the radio firmware is unlikely to send non-numericordervalues. -
XVTR name collision: If two XVTR entries have the same
name, thebreakafter the first match means we always pick the first one. That's the existing behavior and is fine, but worth noting that the Flex API doesn't enforce unique XVTR names — an edge case that probably doesn't matter in practice. -
Status bar message lifetime: The 5-second
showMessagetimeout for refused bands is reasonable. Just flagging that if other status messages are being posted rapidly (e.g., during reconnect), this could get overwritten before the user sees it. TheqWarninglog is the durable record, so this is fine.
Relationship to #1880
This PR supersedes the draft #1880 (which only stripped the m suffix without removing the fallback or fixing XVTR selection). If this merges, #1880 can be closed.
Overall this is a clean, well-scoped fix. The changes stay within the stated scope (MainWindow band handler + RadioModel XVTR parsing), no new resource management concerns, no null pointer risks I can see. Nice work — and thank you for the detailed manual testing across native bands, XVTR, and the negative cases.
|
Claude here on behalf of Jeremy — merged via `gh pr merge --squash` as `41c1699` (you preserved as git author on the squashed commit). Nice writeup on the root cause and fallback-removal reasoning. The XVTR `order`-vs-index distinction and the pcap references made the protocol correctness easy to confirm. Looking forward to hearing how the band stack feels after this lands. Thanks Pat! 73, Jeremy KK7GWY & Claude (AI dev partner) |
…#2511) Flex's `display pan set band=X<n>` expects the xvtr status-object index (the number from `xvtr <n>` messages, 0-based), not the radio's 1-based `order` field. Using `order` produced a +1 shift: pressing the 144 MHz button sent `band=X1` instead of `band=X0`, tuning to 432 MHz instead. Reverts the index→order swap from PR #1887 back to the pcap-verified `X<index>` form from PR #1615. Updates the test assertions and renames the test function to reflect the correct semantics. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Fixes #1876.
This restores radio-authoritative Flex band-stack selection from the spectrum band menu. Native band buttons now send the Flex band-stack key the radio expects, transverter bands are mapped through the radio's XVTR setup order, and unsupported bands are refused instead of falling back to a direct slice tune.
The important behavior change is that AetherSDR again lets the radio own band-stack recall for frequency, mode, filters, pan center, bandwidth/zoom, and antenna state. We do not synthesize a local frequency/mode restore and we do not force a client-side recenter after the band switch.
Manual testing also confirmed that built-in Flex RX/TX antenna selections persist across band changes once Aether uses the correct radio-authoritative
band=path. This does not add a separate Aether-side antenna memory layer; it restores the radio-owned behavior that was bypassed by the fallback tune path.Root Cause
The band selector UI emits human-facing labels such as
20m,40m,630m, etc. The band-switching handler was checking those values against a native-band pass-through set containing bare Flex keys such as20,40, and630.That mismatch meant ordinary native bands missed the intended path:
and instead fell into the old unrecognized-band fallback. The fallback directly changed the slice mode and tuned to the static band-grid default, for example
14.225 USBon 20m. That bypassed the radio's band stack, so user state that should have been restored by the radio was replaced by Aether's hard-coded defaults.This is why users saw symptoms like:
14.225 USBinstead of their last CW frequencyWhat Changed
20m->band=20630m->band=6302200m->band=2200WWV->band=33GEN->band=34orderstatus field intoRadioModel::XvtrInfo.X<order>:2mwithorder=0->band=X070cmwithorder=1->band=X1slice set mode=...plus directslice tune ....band=key, log a warning, show a short status-bar message, and leave the slice/panadapter untouched.Flex API Notes
The public Flex
display pan setAPI exposes band selection as a panadapter property:For native bands, the key is the radio band-stack name, not the UI label with the meter suffix. For transverters, the selector is the radio's XVTR setup slot in
X<n>form. Thenamefield is the user's display label; theorderfield is the value that determines theX<n>selector.This distinction matters because the XVTR status index is not necessarily the correct selector. This PR uses
order, not thexvtr <index>map key.Behavior Matrix
160mdisplay pan set <panId> band=16080mdisplay pan set <panId> band=8060mdisplay pan set <panId> band=6040mdisplay pan set <panId> band=4030mdisplay pan set <panId> band=3020mdisplay pan set <panId> band=2017mdisplay pan set <panId> band=1715mdisplay pan set <panId> band=1512mdisplay pan set <panId> band=1210mdisplay pan set <panId> band=106mdisplay pan set <panId> band=6630mdisplay pan set <panId> band=6302200mdisplay pan set <panId> band=2200WWVdisplay pan set <panId> band=33GENdisplay pan set <panId> band=342m,order=0display pan set <panId> band=X070cm,order=1display pan set <panId> band=X1orderIssue History
This PR directly fixes the failure proven in #1876: native band changes were not using the radio band stack and instead reset VFO/span state to Aether's defaults.
It also appears to address the same regression pattern reported in:
14.300SSB instead of the previous CW QRGRelated prior history:
msuffix for native bands. This PR keeps that core idea, but also removes the unsafe fallback and fixes XVTR selection against the Flex API shape.Validation
Automated/local checks:
git diff --checkcmake --build build -j10Build succeeded. The compiler still reports unrelated pre-existing lambda-capture warnings in
MainWindow.cpp.Manual validation performed:
display pan set ... band=path.2m: RF144.200, IF28.200, LO116.000, RX Only enabled, Max Power0.070cm: RF432.100, IF28.100, LO404.000, RX Only enabled, Max Power0.02m,70cm, and native HF bands preserves frequency and zoom/span state.Suggested Test Plan
Native Band Stack
20m.14.360.000.40m.40mto a different non-default frequency and use a different zoom/span.20m.20mstate.630mor2200mif available.Two Slice Regression
WWV / GEN
WWV.GEN.Built-in Flex Antenna Persistence
20m.ANT2.40m.ANT1.20m.20mantenna selection.40m.40mantenna selection is restored.XVTR Without Physical Hardware
2mXVTR:2m144.20028.200116.00000.00.070cmXVTR:70cm432.10028.100404.00000.00.02m; verify the panadapter tunes to the XVTR band.2m; verify frequency and zoom/span persist.70cm.XVTR Order Regression
XVTR match: "2m" -> "X0"andXVTR match: "70cm" -> "X1"or the corresponding order values reported by the radio.ordervalue rather than the status object index.Negative / Safety Behavior
slice tunefallback and does not change the slice mode/frequency.Risk Notes
order. That matches the Flex API behavior we need forX<n>selectors; if a radio/firmware does not provideorder, Aether refuses the XVTR selection rather than risking the wrong transverter.rxant/txantmemory layer in Aether. If a future radio/firmware path does not save antenna changes into the band stack, that would need a separate memory in the selection of Tx Rx antennas according to the band #1886-style follow-up.Files Changed
src/gui/MainWindow.cppsrc/models/RadioModel.cppsrc/models/RadioModel.h👨🏼💻 Generated with OpenAI Codex (GPT-5.5 Pro 4/23) and tested by @jensenpat