[style](trx-rs): reformat codebase
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
@@ -2,8 +2,8 @@
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
use num_complex::Complex;
|
||||
use super::DcBlocker;
|
||||
use num_complex::Complex;
|
||||
|
||||
/// C-QUAM (Compatible Quadrature AM) stereo demodulator.
|
||||
///
|
||||
@@ -57,8 +57,7 @@ impl CquamDemod {
|
||||
self.carrier_im = alpha * self.carrier_im + one_minus_alpha * s.im;
|
||||
|
||||
// Rotate s by −φ to phase-align I with (1 + m_s) and Q with m_d.
|
||||
let mag_sq =
|
||||
self.carrier_re * self.carrier_re + self.carrier_im * self.carrier_im;
|
||||
let mag_sq = self.carrier_re * self.carrier_re + self.carrier_im * self.carrier_im;
|
||||
let (i_corr, q_corr) = if mag_sq > 1e-8 {
|
||||
let inv = mag_sq.sqrt().recip();
|
||||
let cos_phi = self.carrier_re * inv;
|
||||
@@ -94,7 +93,10 @@ mod tests {
|
||||
let out = demod.demodulate_stereo(&samples);
|
||||
assert_eq!(out.len(), 512);
|
||||
for &s in &out {
|
||||
assert!(s.abs() < 1e-5, "silence should produce near-zero output, got {s}");
|
||||
assert!(
|
||||
s.abs() < 1e-5,
|
||||
"silence should produce near-zero output, got {s}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,7 @@ use num_complex::Complex;
|
||||
/// 7th-order minimax atan approximation for |z| <= 1.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
#[target_feature(enable = "neon")]
|
||||
unsafe fn atan_poly_neon(
|
||||
z: std::arch::aarch64::float32x4_t,
|
||||
) -> std::arch::aarch64::float32x4_t {
|
||||
unsafe fn atan_poly_neon(z: std::arch::aarch64::float32x4_t) -> std::arch::aarch64::float32x4_t {
|
||||
use std::arch::aarch64::*;
|
||||
let c0 = vdupq_n_f32(0.999_999_5_f32);
|
||||
let c1 = vdupq_n_f32(-0.333_326_1_f32);
|
||||
|
||||
@@ -249,7 +249,10 @@ impl SdrPipeline {
|
||||
channel_if_hz: f64,
|
||||
mode: &RigMode,
|
||||
bandwidth_hz: u32,
|
||||
) -> (broadcast::Sender<Vec<f32>>, broadcast::Sender<Vec<Complex<f32>>>) {
|
||||
) -> (
|
||||
broadcast::Sender<Vec<f32>>,
|
||||
broadcast::Sender<Vec<Complex<f32>>>,
|
||||
) {
|
||||
const PCM_BROADCAST_CAPACITY: usize = 32;
|
||||
const IQ_BROADCAST_CAPACITY: usize = 64;
|
||||
let (pcm_tx, _) = broadcast::channel::<Vec<f32>>(PCM_BROADCAST_CAPACITY);
|
||||
@@ -456,9 +459,7 @@ fn iq_read_loop(
|
||||
// Hold a read lock only for the duration of this block's DSP pass.
|
||||
// Write lock (add/remove channel) waits at most one block (~2 ms).
|
||||
{
|
||||
let dsps = channel_dsps
|
||||
.read()
|
||||
.expect("channel_dsps RwLock poisoned");
|
||||
let dsps = channel_dsps.read().expect("channel_dsps RwLock poisoned");
|
||||
for dsp_arc in dsps.iter() {
|
||||
match dsp_arc.lock() {
|
||||
Ok(mut dsp) => dsp.process_block(samples),
|
||||
|
||||
@@ -272,7 +272,12 @@ impl ChannelDsp {
|
||||
} else {
|
||||
(cutoff_hz / self.sdr_sample_rate as f32).min(0.499)
|
||||
};
|
||||
self.lpf_iq = BlockFirFilterPair::new(cutoff_norm, ssb_shift_norm(&self.mode, cutoff_norm), auto_taps(cutoff_norm), IQ_BLOCK_SIZE);
|
||||
self.lpf_iq = BlockFirFilterPair::new(
|
||||
cutoff_norm,
|
||||
ssb_shift_norm(&self.mode, cutoff_norm),
|
||||
auto_taps(cutoff_norm),
|
||||
IQ_BLOCK_SIZE,
|
||||
);
|
||||
let rate_changed = self.decim_factor != next_decim_factor;
|
||||
self.decim_factor = next_decim_factor;
|
||||
self.decim_counter = 0;
|
||||
@@ -352,7 +357,12 @@ impl ChannelDsp {
|
||||
channel_if_hz,
|
||||
demodulator: Demodulator::for_mode(mode),
|
||||
mode: mode.clone(),
|
||||
lpf_iq: BlockFirFilterPair::new(cutoff_norm, ssb_shift_norm(mode, cutoff_norm), auto_taps(cutoff_norm), IQ_BLOCK_SIZE),
|
||||
lpf_iq: BlockFirFilterPair::new(
|
||||
cutoff_norm,
|
||||
ssb_shift_norm(mode, cutoff_norm),
|
||||
auto_taps(cutoff_norm),
|
||||
IQ_BLOCK_SIZE,
|
||||
),
|
||||
sdr_sample_rate,
|
||||
audio_sample_rate,
|
||||
audio_bandwidth_hz,
|
||||
|
||||
@@ -109,7 +109,12 @@ type FirKernel = (
|
||||
/// Setting `shift_norm = +cutoff_norm` produces a one-sided USB filter
|
||||
/// `[0, BW]`; `shift_norm = -cutoff_norm` produces a one-sided LSB filter
|
||||
/// `[-BW, 0]`; `shift_norm = 0` leaves the kernel symmetric (AM/FM/WFM).
|
||||
fn build_fir_kernel(cutoff_norm: f32, shift_norm: f32, taps: usize, block_size: usize) -> FirKernel {
|
||||
fn build_fir_kernel(
|
||||
cutoff_norm: f32,
|
||||
shift_norm: f32,
|
||||
taps: usize,
|
||||
block_size: usize,
|
||||
) -> FirKernel {
|
||||
let coeffs = windowed_sinc_coeffs(cutoff_norm, taps);
|
||||
let fft_size = (block_size + taps - 1).next_power_of_two();
|
||||
|
||||
@@ -210,8 +215,14 @@ unsafe fn mul_freq_domain_neon(
|
||||
let (h_re, h_im) = (h_ri.0, h_ri.1);
|
||||
|
||||
// Complex multiply: out.re = x.re*h.re - x.im*h.im, out.im = x.re*h.im + x.im*h.re
|
||||
let out_re = vmulq_f32(vsubq_f32(vmulq_f32(x_re, h_re), vmulq_f32(x_im, h_im)), scale_v);
|
||||
let out_im = vmulq_f32(vaddq_f32(vmulq_f32(x_re, h_im), vmulq_f32(x_im, h_re)), scale_v);
|
||||
let out_re = vmulq_f32(
|
||||
vsubq_f32(vmulq_f32(x_re, h_re), vmulq_f32(x_im, h_im)),
|
||||
scale_v,
|
||||
);
|
||||
let out_im = vmulq_f32(
|
||||
vaddq_f32(vmulq_f32(x_re, h_im), vmulq_f32(x_im, h_re)),
|
||||
scale_v,
|
||||
);
|
||||
|
||||
// Reinterleave: .0 = [re0,im0,re1,im1], .1 = [re2,im2,re3,im3]
|
||||
let out = vzipq_f32(out_re, out_im);
|
||||
@@ -313,7 +324,8 @@ impl BlockFirFilterPair {
|
||||
/// `-cutoff_norm` for LSB/CWR.
|
||||
pub fn new(cutoff_norm: f32, shift_norm: f32, taps: usize, block_size: usize) -> Self {
|
||||
let taps = taps.max(1);
|
||||
let (h_buf, fft_size, fft, ifft) = build_fir_kernel(cutoff_norm, shift_norm, taps, block_size);
|
||||
let (h_buf, fft_size, fft, ifft) =
|
||||
build_fir_kernel(cutoff_norm, shift_norm, taps, block_size);
|
||||
Self {
|
||||
h_freq: h_buf,
|
||||
overlap: vec![FftComplex::new(0.0, 0.0); taps.saturating_sub(1)],
|
||||
|
||||
@@ -7,10 +7,10 @@ pub mod dsp;
|
||||
pub mod real_iq_source;
|
||||
pub mod vchan_impl;
|
||||
|
||||
use dsp::IqSource as _;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use dsp::IqSource as _;
|
||||
use trx_core::radio::freq::{Band, Freq};
|
||||
use trx_core::rig::response::RigError;
|
||||
use trx_core::rig::state::{RigFilterState, SpectrumData, VchanRdsEntry, WfmDenoiseLevel};
|
||||
@@ -257,10 +257,7 @@ impl SoapySdrRig {
|
||||
};
|
||||
|
||||
// Initialise filter state from primary channel config (index 0), or defaults.
|
||||
let bandwidth_hz = channels
|
||||
.first()
|
||||
.map(|&(_, _, bw)| bw)
|
||||
.unwrap_or(3000);
|
||||
let bandwidth_hz = channels.first().map(|&(_, _, bw)| bw).unwrap_or(3000);
|
||||
|
||||
let spectrum_buf = pipeline.spectrum_buf.clone();
|
||||
let retune_cmd = pipeline.retune_cmd.clone();
|
||||
@@ -359,10 +356,7 @@ impl SoapySdrRig {
|
||||
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
||||
for idx in [ais_a_idx, ais_b_idx] {
|
||||
if let Some(dsp_arc) = dsps.get(idx) {
|
||||
dsp_arc
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_filter(self.bandwidth_hz);
|
||||
dsp_arc.lock().unwrap().set_filter(self.bandwidth_hz);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -749,10 +743,7 @@ impl RigCat for SoapySdrRig {
|
||||
{
|
||||
let dsps = self.pipeline.channel_dsps.read().unwrap();
|
||||
if let Some(dsp_arc) = dsps.get(self.primary_channel_idx) {
|
||||
dsp_arc
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_filter(bandwidth_hz);
|
||||
dsp_arc.lock().unwrap().set_filter(bandwidth_hz);
|
||||
}
|
||||
}
|
||||
self.apply_ais_channel_filters();
|
||||
|
||||
@@ -100,11 +100,7 @@ impl SdrVirtualChannelManager {
|
||||
/// - `fixed_slot_count`: number of fixed pipeline slots (primary + AIS),
|
||||
/// i.e. the index of the first slot available for virtual channels.
|
||||
/// - `max_total`: maximum total channels including primary (e.g. 4).
|
||||
pub fn new(
|
||||
pipeline: Arc<SdrPipeline>,
|
||||
fixed_slot_count: usize,
|
||||
max_total: usize,
|
||||
) -> Self {
|
||||
pub fn new(pipeline: Arc<SdrPipeline>, fixed_slot_count: usize, max_total: usize) -> Self {
|
||||
// Seed the channel list with a synthetic primary-channel entry.
|
||||
// We use the first PCM sender from the pipeline (index 0).
|
||||
let primary_pcm_tx = pipeline
|
||||
@@ -177,9 +173,9 @@ impl SdrVirtualChannelManager {
|
||||
}
|
||||
|
||||
let bandwidth_hz = default_bandwidth_hz(mode);
|
||||
let (pcm_tx, iq_tx) =
|
||||
self.pipeline
|
||||
.add_virtual_channel(if_hz as f64, mode, bandwidth_hz);
|
||||
let (pcm_tx, iq_tx) = self
|
||||
.pipeline
|
||||
.add_virtual_channel(if_hz as f64, mode, bandwidth_hz);
|
||||
|
||||
let pipeline_slot = self
|
||||
.pipeline
|
||||
|
||||
Reference in New Issue
Block a user