feat(bands): surface 4m/2m on FLEX-6500/6700 via ModelCapabilities (#695)#2757
Conversation
) The FLEX-6500 (Region 1 mod) has a built-in 4m transverter; the FLEX-6700 has both 4m and 2m. These are native radio hardware, not user-configurable XVTRs, and the band selector should treat them that way — no manual XVTR-tab configuration required, just click the band button and tune. Approach mirrors FlexLib's per-model ModelInfo design: * `src/models/ModelCapabilities.{h,cpp}` — table keyed on the model string with Has4Meters / Has2Meters flags. Substring matching with R-variants ordered before base models so a "FLEX-6700R" status doesn't accidentally claim 6700 caps. Unknown models default to all-false (forward-compat). * `RadioModel::capabilities()` — thin accessor returning capabilitiesFor(m_model). * `SpectrumOverlayMenu` — new `setRadioCapabilities()` slot caches the flags and triggers a band-panel rebuild; the existing setXvtrBands() rebuild path inserts a conditional 4m/2m row between HF bands and the user-XVTR row, styled identically to HF (these are native bands, not XVTRs). * `MainWindow` refreshXvtr lambda pushes both caps and XVTR list together on every infoChanged, so capability changes on (re)connect propagate to all open panadapter menus. * `tests/model_capabilities_test` — verifies the table matches FlexLib/ModelInfo.cs row-for-row. Catches drift if Flex ever flips a flag in firmware updates; re-sync the C++ table and update the test together. Scope is intentionally narrow: only the 2m/4m checks migrate into ModelCapabilities; the existing model.contains("6700") checks elsewhere (slice count, dual-SCU, has-loop-B) stay where they are and can be opportunistically migrated in follow-ups. Fixes #695. Thanks @Juanjo-EA1CJ for the original report and @wb8cxo for the correction that the 6700's 2m is native hardware and shouldn't require XVTR configuration. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Thanks @ten9876 — this is a nicely scoped change. The capability-table approach reads cleanly and the substring/case-insensitive lookup with R/M-variants ordered before base models is exactly the right shape. Test coverage is solid (FlexLib row-for-row + suffix + case + unknown + empty).
A few observations, none blocking:
1. Double rebuild on first connect to a 4m/2m radio (minor)
In MainWindow::refreshXvtr the call sequence is:
menu->setRadioCapabilities(caps); // (a)
menu->setXvtrBands(xvtrBands); // (b)When caps differs from the default (i.e. a FLEX-6500/6700), setRadioCapabilities triggers a full setXvtrBands(m_lastXvtrBands) rebuild internally, then call (b) rebuilds the panel again with the real XVTR list. The panel is hidden during rebuild so it's not user-visible — just two deleteLater() + reconstruct cycles where one would do. For 6400/6600/8x00 the early-out skips it, so it's only on 6500/6700. Worth a comment or a small "build once with both inputs" helper if you want to address it, but I wouldn't block on this.
2. setRadioCapabilities early-out when caps equal default-constructed values
On the very first call with all-false caps (FLEX-6400, etc.), the equality check against the default-constructed m_radioCapabilities returns early without ever building the band panel. That's fine because setXvtrBands runs immediately after and does the actual build — but it means setRadioCapabilities is not safe to call in isolation as a "make sure the panel reflects current caps" trigger. The current callsite ordering keeps that invariant intact; just worth noting if a future caller leans on it.
3. 4m frequency choice
70.200 USB matches the IARU Region 1 SSB centre of activity and is the conventional default for AetherSDR's intended audience here — good pick. 144.200 USB is the NA SSB calling frequency; Region 1 users land at 144.300, but as a single default it's defensible and matches what most operators clicking the button will expect.
4. Scope
PR body explicitly defers migrating the other model.contains("6700") checks (slice count, dual-SCU, has-loop-B) to follow-ups. Good call — keeps this reviewable and the table additive.
Nothing AppSettings/RAII/error-handling related to flag. Build config, conventions, and the new test target all look right. Nice work.
|
26.5.2 added 2 and 4 m band buttons (TU) but nothing happens when clicked on. 6700 still functions on 2m using profiles. Couldn't get direct freq (2m) entry on slice to work (possibly me). Memories work inconsistantly, more testing needed. |
Summary
Implements the plan posted to #695.
FLEX-6500 (Region 1 mod) has a built-in 4m transverter; FLEX-6700 has both 4m and 2m. These are native radio hardware, not user-configurable XVTRs — click the band button and tune, no XVTR-tab setup required.
Changes
src/models/ModelCapabilities.{h,cpp}— table mirroring FlexLibModelInfo.cs(Has4Meters,Has2Meters). Substring-matching lookup with R-variants ordered before base models soFLEX-6700Rdoesn't accidentally claim 6700 caps. Unknown models default to all-false (forward-compat).RadioModel::capabilities()— thin accessor.SpectrumOverlayMenu— newsetRadioCapabilities()slot caches flags and triggers band-panel rebuild; existingsetXvtrBands()path inserts a conditional 4m/2m row between HF and user-XVTR rows, styled identically to HF bands.MainWindow::refreshXvtrlambda now pushes both caps and XVTR list on everyinfoChanged, so capability changes on (re)connect propagate to all open panadapter menus.tests/model_capabilities_test— 36 assertions verifying table against FlexLib row-for-row + substring/case-insensitive/unknown-model behavior. All passing locally.Scope
Intentionally narrow: only the 2m/4m checks migrate into
ModelCapabilities. Existingmodel.contains(\"6700\")checks for slice count, dual-SCU, has-loop-B stay where they are — can be opportunistically migrated in follow-ups.Test plan
Fixes #695. Thanks @Juanjo-EA1CJ for the original report and @wb8cxo for the correction.
🤖 Generated with Claude Code