[feat](trx-backend-soapysdr): seed LNA gain from hardware at init
Add read_named_gain to IqSource (default: None) and implement it in RealIqSource via Device::gain_element. Read the "LNA" element before boxing the source so the initial sdr_lna_gain_db reflects the actual hardware state, making the UI control visible and correct on first connect. Devices without an LNA element (e.g. RTL-SDR with "TUNER") return None and the control stays hidden. Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
@@ -63,6 +63,12 @@ pub trait IqSource: Send + 'static {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the current value of a named gain element. Returns `None` for
|
||||||
|
/// sources that do not support named gain elements.
|
||||||
|
fn read_named_gain(&self, _name: &str) -> Option<f64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
/// Enable or disable hardware automatic gain control. Default
|
/// Enable or disable hardware automatic gain control. Default
|
||||||
/// implementation is a no-op for sources that do not support AGC.
|
/// implementation is a no-op for sources that do not support AGC.
|
||||||
fn set_gain_mode(&mut self, _automatic: bool) -> Result<(), String> {
|
fn set_gain_mode(&mut self, _automatic: bool) -> Result<(), String> {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ pub mod vchan_impl;
|
|||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
use dsp::IqSource as _;
|
||||||
use trx_core::radio::freq::{Band, Freq};
|
use trx_core::radio::freq::{Band, Freq};
|
||||||
use trx_core::rig::response::RigError;
|
use trx_core::rig::response::RigError;
|
||||||
use trx_core::rig::state::{RigFilterState, SpectrumData, VchanRdsEntry, WfmDenoiseLevel};
|
use trx_core::rig::state::{RigFilterState, SpectrumData, VchanRdsEntry, WfmDenoiseLevel};
|
||||||
@@ -155,13 +156,21 @@ impl SoapySdrRig {
|
|||||||
let hardware_center_hz = initial_freq.hz as i64 - center_offset_hz;
|
let hardware_center_hz = initial_freq.hz as i64 - center_offset_hz;
|
||||||
|
|
||||||
// Create real IQ source from hardware device.
|
// Create real IQ source from hardware device.
|
||||||
let iq_source: Box<dyn dsp::IqSource> = Box::new(real_iq_source::RealIqSource::new(
|
let iq_source = real_iq_source::RealIqSource::new(
|
||||||
args,
|
args,
|
||||||
hardware_center_hz as f64,
|
hardware_center_hz as f64,
|
||||||
sdr_sample_rate as f64,
|
sdr_sample_rate as f64,
|
||||||
bandwidth_hz as f64,
|
bandwidth_hz as f64,
|
||||||
effective_gain_db,
|
effective_gain_db,
|
||||||
)?);
|
)?;
|
||||||
|
// Read the initial LNA gain from the hardware before the source is
|
||||||
|
// moved into the pipeline thread. Returns None on devices that do
|
||||||
|
// not expose an "LNA" gain element (e.g. RTL-SDR exposes "TUNER").
|
||||||
|
let initial_lna_gain_db = iq_source.read_named_gain("LNA");
|
||||||
|
if let Some(lna) = initial_lna_gain_db {
|
||||||
|
tracing::info!("SDR LNA gain element present, initial value: {:.1} dB", lna);
|
||||||
|
}
|
||||||
|
let iq_source: Box<dyn dsp::IqSource> = Box::new(iq_source);
|
||||||
|
|
||||||
let primary_channel_count = channels.len();
|
let primary_channel_count = channels.len();
|
||||||
let mut all_channels = channels.to_vec();
|
let mut all_channels = channels.to_vec();
|
||||||
@@ -287,7 +296,7 @@ impl SoapySdrRig {
|
|||||||
wfm_denoise: WfmDenoiseLevel::Auto,
|
wfm_denoise: WfmDenoiseLevel::Auto,
|
||||||
gain_db,
|
gain_db,
|
||||||
max_gain_db,
|
max_gain_db,
|
||||||
lna_gain_db: None,
|
lna_gain_db: initial_lna_gain_db,
|
||||||
agc_enabled,
|
agc_enabled,
|
||||||
squelch_enabled,
|
squelch_enabled,
|
||||||
squelch_threshold_db,
|
squelch_threshold_db,
|
||||||
|
|||||||
@@ -185,6 +185,12 @@ impl IqSource for RealIqSource {
|
|||||||
.map_err(|e| format!("Failed to set SDR {} gain: {}", name, e))
|
.map_err(|e| format!("Failed to set SDR {} gain: {}", name, e))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_named_gain(&self, name: &str) -> Option<f64> {
|
||||||
|
self.device
|
||||||
|
.gain_element(soapysdr::Direction::Rx, 0, name)
|
||||||
|
.ok()
|
||||||
|
}
|
||||||
|
|
||||||
fn set_gain_mode(&mut self, automatic: bool) -> Result<(), String> {
|
fn set_gain_mode(&mut self, automatic: bool) -> Result<(), String> {
|
||||||
self.device
|
self.device
|
||||||
.set_gain_mode(soapysdr::Direction::Rx, 0, automatic)
|
.set_gain_mode(soapysdr::Direction::Rx, 0, automatic)
|
||||||
|
|||||||
Reference in New Issue
Block a user