Fix KiwiSDR CW BFO offset so a tuned carrier produces an audible tone (#4423) - #1
Closed
wa2n-code wants to merge 2 commits into
Closed
Fix KiwiSDR CW BFO offset so a tuned carrier produces an audible tone (#4423)#1wa2n-code wants to merge 2 commits into
wa2n-code wants to merge 2 commits into
Conversation
…4423) KiwiSDR's SET freq= is the BFO/mixdown point, not a dial frequency; low_cut/high_cut are applied as an audio passband relative to it. Our CW passband is already centered on the sidetone pitch above (or, for CWL, below) the carrier, so sending freq=carrier put the carrier at 0 Hz, outside the passband, and the tone was filtered out even though the tuned-frequency pip overlaid the signal. Extract SET mod=/low_cut=/high_cut=/freq= construction into KiwiSdrProtocol::formatSoundTuneCommand() so the CW BFO math is unit testable, and shift freq by the passband center for mode=="cw". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…center (aethersdr#4423) A real session log (attached to the issue) showed Flex reports the CW passband symmetric about the carrier (low_cut=-400 high_cut=400) — the sidetone pitch is a DSP shift Flex applies AFTER that filter, not baked into the reported passband. With a symmetric passband the previous fix's "shift by passband center" computed a zero offset, so nothing changed: the carrier still demodulated to 0 Hz (heard as a DC thump while tuning, not a tone), matching what was reported after the first fix landed. Shift the whole receive chain by the radio's actual CW pitch instead: move the Kiwi BFO down by the pitch so the carrier demodulates to +cwPitchHz, and slide low_cut/high_cut up by the same amount so that frequency is still inside the passband. Plumb TransmitModel::cwPitch() from MainWindow down through KiwiSdrManager and into KiwiSdrClient::setTrackedSlice(), and re-send tracked-slice state when the pitch changes live so an active KiwiSDR CW session doesn't go stale. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Owner
Author
|
Closing — reopening against the upstream aethersdr/AetherSDR repo instead of my own fork. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SET ... freq=is the BFO/mixdown point, not a dial frequency —low_cut/high_cutare an audio passband applied relative to it. Sendingfreq=carrierputs the carrier at 0 Hz, which either falls outside the passband (no tone) or lands as an inaudible DC thump (tone, but not a tone).Why two commits
This shipped in two steps because the first fix's assumption was disproved by a real session log attached to the issue, and I want that story visible rather than squashed away:
Offset KiwiSDR CW sound-stream BFO by the passband center— an automated triage comment on the issue had already root-caused the "BFO stays at the carrier" problem and proposed shiftingfreqby the CW passband's center (assuming Flex reports the passband already offset toward the pitch, e.g.400..800). I implemented that. It compiled and looked reasonable, but testing on real hardware showed no change in behavior — still no tone, and audible "DC shifting" while tuning.Use the radio's actual CW pitch for KiwiSDR BFO offset, not passband center— pulling the log files attached to the issue showed the actual commands AetherSDR was sending:SET mod=cw low_cut=-400 high_cut=400 freq=.... Flex's real CW passband is symmetric about the carrier, not offset — the sidetone pitch is a DSP shift Flex applies after that filter, not something baked into the reported passband. With a symmetric passband,(low+high)/2is always0, so commit 1's shift was a no-op — the carrier kept landing at 0 Hz, which is exactly the "DC thump" that was reported back.The fix: use the radio's actual configured CW pitch (
TransmitModel::cwPitch(), the same value driving the Flex sidetone/monitor tone) instead of deriving anything from the passband. Move the Kiwi BFO down by the pitch (carrier demodulates to+pitchHz) and slidelow_cut/high_cutup by the same amount (so that+pitchHz frequency is still inside the passband instead of getting filtered out). This reproduces, in software, the shift the Flex's own onboard DSP does natively — which is also why Flex antennas never needed this fix in the first place.Also plumbed
cwPitchfromMainWindow→KiwiSdrManager→KiwiSdrClient::setTrackedSlice(), and wired a live re-send when the operator changes CW pitch mid-session (MainWindow_Wiring.cpp), so an already-active KiwiSDR CW session doesn't go stale if the pitch is adjusted after switching to the Kiwi.Test plan
formatSoundTuneCommandunit coverage intests/kiwi_sdr_protocol_test.cpp(CW with real symmetric passband + pitch, CW with pitch disabled, USB/LSB unaffected).SET mod=cw low_cut=-400 high_cut=400 freq=...commands captured in the issue's attached session log.🤖 Generated with Claude Code