This commit is contained in:
2026-06-12 09:37:21 +02:00
parent b947256af6
commit d3375c0e22
3 changed files with 34 additions and 15 deletions

View File

@ -1,27 +1,41 @@
// Finite Impulse response + Decimation // Finite Impulse response + Decimation
use crate::utils::ring_buffer::RingBuffer; use crate::{iq_reader::IqChunk, iq_reader::IqSample, utils::ring_buffer::RingBuffer};
use num_complex::Complex32;
pub struct Fir<const N: usize> { pub struct Fir<const N: usize> {
// Filter coefs // Filter coefs
pub taps: [f32; N], pub taps: [f32; N],
// Ring Buffer of samples // Ring Buffer of samples
pub history: RingBuffer<Complex32>, pub history: RingBuffer<IqSample>,
decimation_factor: usize, // Factor of decimation
pub decimation_factor: usize,
// When to keep a sample // Track decimation
decimator_counter: usize, pub decimation_index: usize,
} }
impl<const N: usize> Fir<N> { impl<const N: usize> Fir<N> {
fn new(taps: [f32; N], decimation_factor: usize) -> Self { pub fn new(taps: [f32; N], decimation_factor: usize) -> Self {
Self { Self {
taps, taps,
history: RingBuffer::new(N), history: RingBuffer::<IqSample>::new(N),
decimation_factor, decimation_factor,
decimator_counter: 0, decimation_index: 0,
} }
} }
pub fn process_chunk(&mut self, chunk: &mut IqChunk) {
for iq in chunk.samples.iter_mut() {
self.history.push(*iq);
let mut y_n = IqSample::default();
for k in 0..N {
if let Some(sample) = self.history.read_at(k) {
y_n += *sample * self.taps[k];
}
}
*iq = y_n
}
// TODO: Decimation
}
} }

View File

@ -1,4 +1,5 @@
use crate::agc::Agc; use crate::agc::Agc;
use crate::fir::Fir;
use crate::iq_reader::FileSource; use crate::iq_reader::FileSource;
use std::error::Error; use std::error::Error;
@ -10,17 +11,21 @@ mod utils;
fn main() -> Result<(), Box<dyn Error>> { fn main() -> Result<(), Box<dyn Error>> {
let source = FileSource::new("test.iq", 32769)?; let source = FileSource::new("test.iq", 32769)?;
// for chunk in source { // TODO: make a clean pipline use like GNU radio with iterators (like chunk.agc(...).fir(...)...)
// println!("{chunk :?}");
// }
// 20 MSps // 20 MSps
let mut agc = Agc::new(20_000_000.0, 0.1, 0.001, 100.0); let mut agc = Agc::new(20_000_000.0, 0.1, 0.001, 100.0);
// Fir coefs
let taps = [1.0; 64];
// Fir
let mut fir = Fir::<64>::new(taps, 4);
// Apply Auto Gain Control // Apply Auto Gain Control
for chunk_r in source { for chunk_r in source {
let mut chunk = chunk_r?; let mut chunk = chunk_r?;
agc.process_chunk(&mut chunk); agc.process_chunk(&mut chunk);
fir.process_chunk(&mut chunk);
} }
Ok(()) Ok(())

View File

@ -21,13 +21,13 @@ impl<T: Copy + Default> RingBuffer<T> {
} }
} }
pub fn write(&mut self, value: T) { pub fn push(&mut self, value: T) {
self.data[self.head] = value; self.data[self.head] = value;
self.head = (self.head + 1) % self.capacity; self.head = (self.head + 1) % self.capacity;
self.size = (self.size + 1).min(self.capacity); self.size = (self.size + 1).min(self.capacity);
} }
pub fn read(&mut self) -> Option<T> { pub fn pop(&mut self) -> Option<T> {
if self.size == 0 { if self.size == 0 {
return None; return None;
} }
@ -55,7 +55,7 @@ impl<T: Copy + Default> RingBuffer<T> {
pub fn write_read(&mut self, value: T, delay: usize) -> Option<T> { pub fn write_read(&mut self, value: T, delay: usize) -> Option<T> {
let delayed = self.read_at(delay).copied(); let delayed = self.read_at(delay).copied();
self.write(value); self.push(value);
delayed delayed
} }