fm demod
This commit is contained in:
@ -1,4 +1,6 @@
|
|||||||
use crate::iq_reader::{IqChunk, IqSample};
|
use crate::iq_reader::IqSample;
|
||||||
|
|
||||||
|
pub type Phase = f32;
|
||||||
|
|
||||||
pub struct FmDemod<I> {
|
pub struct FmDemod<I> {
|
||||||
pub inner: I,
|
pub inner: I,
|
||||||
@ -13,9 +15,10 @@ impl<I> FmDemod<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_sample(&mut self, sample: IqSample) -> IqSample {
|
pub fn process_sample(&mut self, sample: IqSample) -> Phase {
|
||||||
// TODO: FM Demodulation
|
let phase_diff = sample * self.prev_sample.conj();
|
||||||
todo!();
|
self.prev_sample = sample;
|
||||||
|
phase_diff.arg()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +26,7 @@ impl<I, E> Iterator for FmDemod<I>
|
|||||||
where
|
where
|
||||||
I: Iterator<Item = Result<IqSample, E>>,
|
I: Iterator<Item = Result<IqSample, E>>,
|
||||||
{
|
{
|
||||||
type Item = Result<IqSample, E>;
|
type Item = Result<Phase, E>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match self.inner.next()? {
|
match self.inner.next()? {
|
||||||
|
|||||||
@ -6,18 +6,18 @@ use std::io::{BufReader, ErrorKind, Read};
|
|||||||
pub type IqSample = Complex<f32>;
|
pub type IqSample = Complex<f32>;
|
||||||
|
|
||||||
// Data chunk
|
// Data chunk
|
||||||
#[derive(Debug)]
|
// #[derive(Debug)]
|
||||||
pub struct IqChunk {
|
// pub struct IqChunk {
|
||||||
pub samples: Vec<IqSample>,
|
// pub samples: Vec<IqSample>,
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
impl IqChunk {
|
// impl IqChunk {
|
||||||
pub fn new() -> Self {
|
// pub fn new() -> Self {
|
||||||
IqChunk {
|
// IqChunk {
|
||||||
samples: Vec::<IqSample>::new(),
|
// samples: Vec::<IqSample>::new(),
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub struct FileSource {
|
pub struct FileSource {
|
||||||
// Buffer
|
// Buffer
|
||||||
|
|||||||
@ -17,11 +17,12 @@ fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
let pipeline = source
|
let pipeline = source
|
||||||
.agc(20_000_000.0, 1.0, 0.001, 100.0)
|
.agc(20_000_000.0, 1.0, 0.001, 100.0)
|
||||||
.fir::<64>(taps, 4);
|
.fir::<64>(taps, 4)
|
||||||
|
.demodulate();
|
||||||
|
|
||||||
for sample_r in pipeline {
|
for phase_r in pipeline {
|
||||||
let sample = sample_r?;
|
let phase = phase_r?;
|
||||||
println!("sample : {} + i{}", sample.re, sample.im);
|
println!("phase : {}", phase);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use crate::agc::Agc;
|
use crate::agc::Agc;
|
||||||
use crate::fir::Fir;
|
use crate::fir::Fir;
|
||||||
|
use crate::fm_demod::FmDemod;
|
||||||
use crate::iq_reader::IqSample;
|
use crate::iq_reader::IqSample;
|
||||||
|
|
||||||
pub trait DspPipelineExt<E>: Iterator<Item = Result<IqSample, E>> + Sized {
|
pub trait DspPipelineExt<E>: Iterator<Item = Result<IqSample, E>> + Sized {
|
||||||
@ -10,6 +11,10 @@ pub trait DspPipelineExt<E>: Iterator<Item = Result<IqSample, E>> + Sized {
|
|||||||
fn fir<const N: usize>(self, taps: [f32; N], decimation_factor: usize) -> Fir<Self, N> {
|
fn fir<const N: usize>(self, taps: [f32; N], decimation_factor: usize) -> Fir<Self, N> {
|
||||||
Fir::new(self, taps, decimation_factor)
|
Fir::new(self, taps, decimation_factor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn demodulate(self) -> FmDemod<Self> {
|
||||||
|
FmDemod::new(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, E> DspPipelineExt<E> for I where I: Iterator<Item = Result<IqSample, E>> {}
|
impl<I, E> DspPipelineExt<E> for I where I: Iterator<Item = Result<IqSample, E>> {}
|
||||||
|
|||||||
Reference in New Issue
Block a user