fix: clamp panadapter center to prevent spectrum left edge below 0 Hz (#783)#2867
fix: clamp panadapter center to prevent spectrum left edge below 0 Hz (#783)#2867NF0T wants to merge 1 commit into
Conversation
…splay Seven sites across SpectrumWidget (zoom buttons, BW drag, pan drag, NativeGesture pinch) and MainWindow (applyPanRangeRequest, keyboard zoom, centerChangeRequested handler) now enforce std::max(center, bw/2) so the left edge of the spectrum can never go below 0 Hz at MW/LW frequencies. Fixes aethersdr#783. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Thanks @NF0T — clean, well-scoped fix with an unusually thorough write-up. Verified all seven clamp sites against the current code:
MainWindow.cpp:9749(applyPanRangeRequest) — clamp lands after thebandwidthMhz <= 0.0guard, so division by zero is impossible. TheapplyPanStatus+sendCommandboth see the clamped value. Correct.MainWindow.cpp:10510(centerChangeRequestedhandler) — properly null-guards them_radioModel.panadapter()lookup. If pan is unexpectedly missing the unclamped value goes through, matching prior behavior; not a regression.MainWindow.cpp:12572(keyboard zoom-out) — defense-in-depth with site 5 is justified by the brief visual desync before the radio echo; agree the redundancy is worth it.SpectrumWidget.cpp:408(emitZoom),:3446(BW drag),:3496(pan drag),:3966(pinch) — all four clamps applied at the natural choke point right after computingnewCenter, before reproject/emit. Consistent.
The PR description's explanation that the BW-drag anchor will drift when the clamp activates (not preserved as anchor) is the right tradeoff — you can't both pin an anchor at low frequency AND keep the left edge ≥ 0 when bandwidth exceeds 2×anchor. The clamp winning is correct UX.
One small observation, no change requested: site 3 emits a center already clamped against m_bandwidthMhz / 2.0, and site 7 re-clamps against pan->bandwidthMhz() / 2.0. During a pure pan drag these are equal, so site 7 is effectively a no-op in that path — but it correctly covers other emitters (NativeGesture, BW drag) which can mutate bandwidth concurrently. Good defense-in-depth.
The FLEX-8400 sub-200 kHz red-waterfall observation is a sensible separate concern — definitely out of scope here.
LGTM.
Summary
Fixes #783 — at MW/LW frequencies the spectrum waterfall could display a left edge below 0 Hz when dragging, zooming, or keyboard-navigating the panadapter.
Root cause: No lower-bound clamp existed on the panadapter center frequency. The left edge is
center − bandwidth/2; when center drops belowbandwidth/2, the left edge goes negative, displaying sub-zero spectrum that doesn't physically exist.Fix: Apply
center = std::max(center, bandwidth / 2.0)at every code path that writes a new center value — both toSpectrumWidget's local state and to the radio command.Seven fix sites
src/gui/SpectrumWidget.cppemitZoomlambda — zoom-in/out buttons, clampnewCenterafter VFO-centering branchmouseMoveEvent— clampzoomCenter(anchor-anchored center) after computing from drag positionmouseMoveEvent— clampnewCenterbeforem_centerMhz =andemit centerChangeRequestedNativeGesturepinch zoom — clampnewCenterafter anchor calculationsrc/gui/MainWindow.cpp5.
applyPanRangeRequest— clampcenterMhz(passed by value) immediately after the null-guard; this is the central choke point for allfrequencyRangeChangeRequestedpaths and keyboard zoom6.
zoomActivePanadapterlambda — clampnewCenterbeforesw->setFrequencyRange()to avoid a visual desync before the radio round-trip;applyPanRangeRequest(site 5) also clamps, providing defense-in-depth7.
centerChangeRequestedhandler — pan drag bypassesapplyPanRangeRequestand sends directly to the radio; fetch bandwidth from the pan model and clamp before thesendCommandNo upper-bound clamp is applied — the radio enforces its own band limits.
Out-of-scope observation
During testing on a FLEX-8400, the waterfall displays solid red (out-of-band indicator) below approximately 200 kHz even after this fix. This appears to be model-specific hardware behavior — other Flex models may allow the receiver to tune lower. The red waterfall in that region is the radio correctly reporting no valid spectrum data, not a client-side rendering bug. This is left for a future investigation scoped to that model's receive floor.
Test plan
[zoom-out at 160m (1.8 MHz) until left edge would go below 0 Hz → clamps cleanly🤖 Generated with Claude Code