idsp/
lockin.rs

1use super::{Complex, ComplexExt, Filter, MulScaled};
2
3/// Lockin filter
4///
5/// Combines two [`Filter`] and an NCO to perform demodulation
6#[derive(Copy, Clone, Default)]
7pub struct Lockin<T> {
8    state: [T; 2],
9}
10
11impl<T: Filter> Lockin<T> {
12    /// Update the lockin with a sample taken at a local oscillator IQ value.
13    pub fn update_iq(&mut self, sample: i32, lo: Complex<i32>, k: &T::Config) -> Complex<i32> {
14        let mix = lo.mul_scaled(sample);
15
16        // Filter with the IIR lowpass,
17        // return IQ (in-phase and quadrature) data.
18        Complex {
19            re: self.state[0].update(mix.re, k),
20            im: self.state[1].update(mix.im, k),
21        }
22    }
23
24    /// Update the lockin with a sample taken at a given phase.
25    pub fn update(&mut self, sample: i32, phase: i32, k: &T::Config) -> Complex<i32> {
26        // Get the LO signal for demodulation and mix the sample;
27        self.update_iq(sample, Complex::from_angle(phase), k)
28    }
29}