From 6f0902256373bf8f63b6bb518f9806f89383c2c5 Mon Sep 17 00:00:00 2001 From: Stan Grams Date: Sat, 28 Feb 2026 11:04:40 +0100 Subject: [PATCH] [fix](trx-rs): sync sdr rds tuning and deemphasis default Make the primary SoapySDR DSP channel follow the tuned\nfrequency so RDS decoding stays aligned with the active\nfrequency rather than the hardware center.\n\nMove the default WFM deemphasis setting to server SDR\nconfig and default it to 50 us, then pass that value into\nthe SoapySDR backend.\n\nCo-authored-by: Codex Signed-off-by: Stan Grams --- src/trx-server/src/config.rs | 3 +++ src/trx-server/src/main.rs | 1 + .../trx-backend/trx-backend-soapysdr/src/dsp.rs | 9 +++++++++ .../trx-backend/trx-backend-soapysdr/src/lib.rs | 15 +++++++++++++-- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/trx-server/src/config.rs b/src/trx-server/src/config.rs index 83daaf1..e50c48c 100644 --- a/src/trx-server/src/config.rs +++ b/src/trx-server/src/config.rs @@ -331,6 +331,8 @@ pub struct SdrConfig { pub sample_rate: u32, /// Hardware IF filter bandwidth (Hz). pub bandwidth: u32, + /// WFM deemphasis time constant in microseconds (50 or 75). + pub wfm_deemphasis_us: u32, /// SDR tunes this many Hz below the dial frequency to keep signal off DC. pub center_offset_hz: i64, /// Gain configuration. @@ -344,6 +346,7 @@ impl Default for SdrConfig { Self { sample_rate: 1_920_000, bandwidth: 1_500_000, + wfm_deemphasis_us: 50, center_offset_hz: 100_000, gain: SdrGainConfig::default(), channels: Vec::new(), diff --git a/src/trx-server/src/main.rs b/src/trx-server/src/main.rs index 66bff84..5002166 100644 --- a/src/trx-server/src/main.rs +++ b/src/trx-server/src/main.rs @@ -316,6 +316,7 @@ fn build_sdr_rig_from_instance( rig_cfg.audio.sample_rate, rig_cfg.audio.channels as usize, rig_cfg.audio.frame_duration_ms, + rig_cfg.sdr.wfm_deemphasis_us, Freq { hz: rig_cfg.rig.initial_freq_hz, }, diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp.rs index ad82b32..927884c 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/dsp.rs @@ -296,6 +296,15 @@ pub struct ChannelDsp { } impl ChannelDsp { + pub fn set_channel_if_hz(&mut self, channel_if_hz: f64) { + self.channel_if_hz = channel_if_hz; + self.mixer_phase_inc = if self.sdr_sample_rate == 0 { + 0.0 + } else { + 2.0 * std::f64::consts::PI * channel_if_hz / self.sdr_sample_rate as f64 + }; + } + fn pipeline_rates( mode: &RigMode, sdr_sample_rate: u32, diff --git a/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs b/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs index 774a2d0..abedbde 100644 --- a/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs +++ b/src/trx-server/trx-backend/trx-backend-soapysdr/src/lib.rs @@ -73,6 +73,7 @@ impl SoapySdrRig { audio_sample_rate: u32, audio_channels: usize, frame_duration_ms: u16, + wfm_deemphasis_us: u32, initial_freq: Freq, initial_mode: RigMode, sdr_sample_rate: u32, @@ -113,7 +114,7 @@ impl SoapySdrRig { audio_sample_rate, audio_channels, frame_duration_ms, - 75, + wfm_deemphasis_us, channels, ); @@ -180,7 +181,7 @@ impl SoapySdrRig { center_offset_hz, center_hz: hardware_center_hz, retune_cmd, - wfm_deemphasis_us: 75, + wfm_deemphasis_us, }) } @@ -196,6 +197,7 @@ impl SoapySdrRig { 48_000, 1, 20, + 50, Freq { hz: 144_300_000 }, RigMode::USB, 1_920_000, @@ -266,6 +268,11 @@ impl RigCat for SoapySdrRig { *cmd = Some(hardware_hz as f64); } } + + if let Some(dsp_arc) = self.pipeline.channel_dsps.get(self.primary_channel_idx) { + let channel_if_hz = (self.freq.hz as i64 - self.center_hz) as f64; + dsp_arc.lock().unwrap().set_channel_if_hz(channel_if_hz); + } Ok(()) }) } @@ -280,6 +287,10 @@ impl RigCat for SoapySdrRig { if let Ok(mut cmd) = self.retune_cmd.lock() { *cmd = Some(self.center_hz as f64); } + if let Some(dsp_arc) = self.pipeline.channel_dsps.get(self.primary_channel_idx) { + let channel_if_hz = (self.freq.hz as i64 - self.center_hz) as f64; + dsp_arc.lock().unwrap().set_channel_if_hz(channel_if_hz); + } Ok(()) }) }