[fix](trx-rs): wire DSP signal strength to Signal strength field and per-vchan SSE

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-27 14:24:44 +01:00
parent d864969742
commit 4fc32f0e90
6 changed files with 49 additions and 9 deletions
@@ -296,6 +296,7 @@ pub struct ChannelDsp {
force_mono_pcm: bool,
squelch: VirtualSquelch,
noise_blanker: NoiseBlanker,
last_signal_db: f32,
}
impl ChannelDsp {
@@ -521,6 +522,7 @@ impl ChannelDsp {
force_mono_pcm,
squelch: VirtualSquelch::new(squelch_cfg),
noise_blanker: NoiseBlanker::new(nb_cfg.enabled, nb_cfg.threshold),
last_signal_db: -120.0,
}
}
@@ -615,6 +617,10 @@ impl ChannelDsp {
.unwrap_or(0)
}
pub fn signal_db(&self) -> f32 {
self.last_signal_db
}
pub fn reset_rds(&mut self) {
if let Some(decoder) = &mut self.wfm_decoder {
decoder.reset_rds();
@@ -740,6 +746,7 @@ impl ChannelDsp {
.sum::<f32>()
/ decimated.len() as f32;
let signal_db = 10.0 * signal_power.max(1e-12).log10();
self.last_signal_db = signal_db;
const WFM_OUTPUT_GAIN: f32 = 0.50;
let mut audio = if let Some(decoder) = self.wfm_decoder.as_mut() {
let mut out = decoder.process_iq(decimated);
@@ -550,8 +550,21 @@ impl RigCat for SoapySdrRig {
fn get_signal_strength<'a>(
&'a mut self,
) -> Pin<Box<dyn std::future::Future<Output = DynResult<u8>> + Send + 'a>> {
// RSSI from real device pending SDR hardware wiring; return 0 for now.
Box::pin(async move { Ok(0u8) })
Box::pin(async move {
let signal_db = self
.pipeline
.channel_dsps
.read()
.unwrap()
.get(self.primary_channel_idx)
.and_then(|dsp| dsp.lock().ok().map(|d| d.signal_db()))
.unwrap_or(-120.0);
// Map DSP signal power (roughly -120 .. 0 dBFS) to 0..15 range
// to match the FT-817 meter scale used by map_signal_strength.
let clamped = signal_db.clamp(-120.0, 0.0);
let raw = ((clamped + 120.0) / 120.0 * 15.0).round() as u8;
Ok(raw.min(15))
})
}
// -- TX / unsupported methods -------------------------------------------
@@ -245,12 +245,19 @@ impl SdrVirtualChannelManager {
let dsps = self.pipeline.channel_dsps.read().unwrap();
channels
.iter()
.filter(|ch| matches!(ch.mode, RigMode::WFM))
.map(|ch| {
let rds = dsps
.get(ch.pipeline_slot)
.and_then(|dsp| dsp.lock().ok().and_then(|d| d.rds_data()));
VchanRdsEntry { id: ch.id, rds }
let dsp_guard = dsps.get(ch.pipeline_slot).and_then(|dsp| dsp.lock().ok());
let rds = if matches!(ch.mode, RigMode::WFM) {
dsp_guard.as_ref().and_then(|d| d.rds_data())
} else {
None
};
let signal_db = dsp_guard.as_ref().map(|d| d.signal_db());
VchanRdsEntry {
id: ch.id,
rds,
signal_db,
}
})
.collect()
}