fix(spectrum): investigate FFT decode range drift on amplitude scale drag (#2384)#2387
fix(spectrum): investigate FFT decode range drift on amplitude scale drag (#2384)#2387M7HNF-Ian wants to merge 0 commit into
Conversation
There was a problem hiding this comment.
Thanks for the careful root-cause analysis on the dBm shift, Ian — the report from LU5DX/rnash2, the decode-formula explanation, and the "radio doesn't re-encode on viewport change" finding are exactly what this kind of bug needs. The PanadapterStream fix itself is well scoped:
On the stated fix (PanadapterStream.{h,cpp})
- Lock-on-first-call is the right shape, and clearing the entry in both
unregisterPanStreamandclearRegisteredStreamsmatches the existing per-stream cleanup pattern, so reconnect / pan-recreate paths are covered. setDbmRangeis already underm_streamMutex, so the newQSetaccess is correctly serialised — no extra locking concerns.- The inline comment is great — future readers will understand exactly why subsequent calls are a no-op.
Scope concern — please split this PR
The PR description and title only mention the two PanadapterStream files, but the diff actually changes nine files in three unrelated buckets:
- The advertised FFT decode-range fix —
PanadapterStream.cpp/h(good, ready as-is) - TciServer crash-on-quit fix —
TciServer.h(QPointer<RadioModel>) andMainWindow.cpp(explicitdelete m_tciServerin~MainWindow). This is the exact change from your PR #2386 and is unrelated to #2384. - New "Spot Lines" enable/disable feature —
DxClusterDialog.cpp,SpectrumWidget.cpp/h,SpotSettingsDialog.cpp/h, plus the twoMainWindow.cpphunks at lines ~5359 and ~8727 wiringsetSpotShowLines. Neither the title nor the body mentions this feature, and it has no connection to issues #2384 / #2310.
It looks like the branch picked up commits from #2386 plus an in-progress Spot Lines change. Could you rebase fix/spectrum-dbm-shift-on-scale-adjust onto a clean main so this PR contains only the PanadapterStream change? The TciServer fix should land via #2386 on its own merits, and the Spot Lines toggle deserves its own PR with a description (and probably its own issue) so reviewers can evaluate the UX choice (default-on, two separate dialogs both writing IsSpotsLinesEnabled, etc.) independently.
Once split, the FFT fix here looks ready to go. Thanks again for the thorough investigation and the reproducible steps from the reporters.
|
Claude here on Jeremy's behalf — wanted to share hardware test results before this lands. To get a clean test, I cherry-picked just the spectrum-fix commit ( Result: the symptom is unchanged. Dragging the amplitude scale by 10 dB still moves the noise floor reading by 10 dB, 1:1 — same drift the original reporters saw. The mechanical implication, since the lock is verifiably in the binary:
So either:
Either way the lock alone doesn't close out #2384/#2310 in practice — at least on the FLEX-8600 setup Jeremy's testing against. Would be useful to know what radio model the original reporters tested on; if Aurora vs. 6000 vs. 8000 series differ in their encoding behavior, that'd narrow it down. The two spot-lines naming commits on this branch ( Holding the cherry-pick for now (reverted locally) until we have a clearer picture of which of the two cases above is in play. Happy to help dig if you want a Wireshark capture from Jeremy's test bench, or pair on the decode formula vs. FlexLib's 73, Jeremy KK7GWY & Claude (AI dev partner) |
…2380) (#2394) SpotHub (DX cluster / RBN) did not automatically reconnect after a Wi-Fi drop or any other failed connection attempt. The app would try once when the network came back, fail, and stop retrying — requiring a manual reconnect. Root cause: Qt's QAbstractSocket only emits disconnected() on a Connected → Unconnected transition. When a socket fails during ConnectingState (host blocked, refused, or timed out), Qt emits errorOccurred but NOT disconnected. The reconnect timer was only armed inside onDisconnected(), so a single failed connect attempt permanently halted the backoff chain. Two additional failure paths had the same gap: onSocketError() emitted the UI error only and never re-armed the timer, and the 10-second connect timeout lambda called abort() without scheduling a retry. Fix: extracts a scheduleReconnect() helper called from all three failure paths, with two guards — m_intentionalDisconnect (don't override user-initiated disconnect) and m_reconnectTimer->isActive() (prevents double-scheduling when errorOccurred and the connect timeout both fire for the same failed attempt). A per-call epoch counter (m_connectEpoch) captured by the timeout lambda ensures a stale timeout from attempt N cannot abort a later attempt N+1 that has since succeeded. connectToCluster() also now rejects calls when the socket is already in ConnectingState to prevent overlapping attempts during rapid retries. Backoff sequence is unchanged: 5 s → 10 s → 20 s → 40 s → 60 s (cap). Cherry-picked from PR #2388 (M7HNF-Ian). The rest of that branch contained already-merged commits (#2349 Spot Lines toggle, #2386 TCI crash fix), the rejected #2387 spectrum fix, and two unrelated spot-lines naming-refinement commits that belong in their own focused PR. Co-authored-by: Ian M7HNF <idimmock@gmail.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the hardware test results — that's a clear outcome. Dug into FlexLib (
The radio re-encodes on viewport change. The lock forces the decoder to use a stale range against freshly re-encoded bins, producing the exact 1:1 offset Jeremy observed. The lock needs to come out. Also looked at That leaves the actual cause of #2384 still open. The most likely remaining candidate is a sync issue: Will rebase the branch to drop the lock change. |
74195f2 to
3af3df3
Compare
Status
Investigation in progress. Original fix (lock decode range to first radio value) was incorrect and has been removed from this branch.
Problem
When the user adjusts the vertical amplitude scale, signal levels and noise floor shift by the same amount as the viewport delta — reported as a consistent 1:1 shift by LU5DX (Martin) and rnash2 (Randy Nash).
What we know so far
Root cause of original fix being wrong: FlexLib (
Panadapter.cs) confirms the radio does re-encode FFT bins whenmin_dbm/max_dbmchanges —LowDbm/HighDbmare updated immediately on the client side and the radio follows. Locking the decode range to the first value forces the decoder to use a stale range against freshly re-encoded bins, producing the exact 1:1 offset Jeremy observed on FLEX-8600 fw 4.1.5.SpectrumWidgetrender path is not the cause: the render cleanly maps absolute dBm values to screen Y usingm_refLevel/m_dynamicRange— no double application of the viewport range.Likely remaining candidate: a sync issue between
PanadapterStream's decode range andSpectrumWidget's display range. Both must track the radio's current encoding range in lockstep. If the decode range update (via status echo →handlePanadapterStatus→PanadapterStream::setDbmRange) is delayed or arrives with different values than what AetherSDR sent, a permanent offset results.Next step
Add diagnostic logging in
decodeFFTto capture raw bin values before and after a viewport drag, confirming whether the radio's encoding changes and whether the decode range stays in sync.Files modified
None — branch is currently clean pending the correct fix.
Reported by LU5DX (Martin) and rnash2 (Randy Nash) with reproducible steps.