fir
This commit is contained in:
32
src/fir.rs
32
src/fir.rs
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/main.rs
11
src/main.rs
@ -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(())
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user