iir_int: move lowpass coefficient calculation to iirstate
This commit is contained in:
parent
9b3a47e08b
commit
7b9fc3b2b3
@ -1,8 +1,39 @@
|
||||
use super::cossin;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// Generic vector for integer IIR filter.
|
||||
/// This struct is used to hold the x/y input/output data vector or the b/a coefficient
|
||||
/// vector.
|
||||
#[derive(Copy, Clone, Default, Deserialize, Serialize)]
|
||||
pub struct IIRState(pub [i32; 5]);
|
||||
|
||||
impl IIRState {
|
||||
/// Lowpass biquad filter using cutoff and sampling frequencies. Taken from:
|
||||
/// https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html
|
||||
///
|
||||
/// # Args
|
||||
/// * `f` - Corner frequency, or 3dB cutoff frequency (in units of sample rate).
|
||||
/// * `q` - Quality factor (1/sqrt(2) for critical).
|
||||
/// * `k` - DC gain.
|
||||
///
|
||||
/// # Returns
|
||||
/// 2nd-order IIR filter coefficients in the form [b0,b1,b2,a1,a2]. a0 is set to -1.
|
||||
pub fn lowpass(f: f64, q: f64, k: f64) -> IIRState {
|
||||
let scale = (1i64 << 32) as f64;
|
||||
let fcossin = cossin((f * scale) as u32 as i32);
|
||||
let fcos = fcossin.0 as f64 / scale;
|
||||
let fsin = fcossin.1 as f64 / scale;
|
||||
let alpha = fsin / (2. * q);
|
||||
// IIR uses Q2.30 fixed point
|
||||
let a0 = (1. + alpha) / (1 << IIR::SHIFT) as f64;
|
||||
let b0 = (k / 2. * (1. - fcos) / a0) as _;
|
||||
let a1 = (2. * fcos / a0) as _;
|
||||
let a2 = ((alpha - 1.) / a0) as _;
|
||||
|
||||
IIRState([b0, 2 * b0, b0, a1, a2])
|
||||
}
|
||||
}
|
||||
|
||||
fn macc(y0: i32, x: &[i32], a: &[i32], shift: u32) -> i32 {
|
||||
// Rounding bias, half up
|
||||
let y0 = ((y0 as i64) << shift) + (1 << (shift - 1));
|
||||
|
@ -41,7 +41,7 @@ impl Lockin {
|
||||
mod test {
|
||||
use crate::{
|
||||
atan2,
|
||||
iir_int::{IIRState, IIR},
|
||||
iir_int::IIRState,
|
||||
lockin::Lockin,
|
||||
rpll::RPLL,
|
||||
testing::{isclose, max_error},
|
||||
@ -189,28 +189,6 @@ mod test {
|
||||
None
|
||||
}
|
||||
|
||||
/// Lowpass biquad filter using cutoff and sampling frequencies. Taken from:
|
||||
/// https://webaudio.github.io/Audio-EQ-Cookbook/audio-eq-cookbook.html
|
||||
///
|
||||
/// # Args
|
||||
/// * `fc` - Corner frequency, or 3dB cutoff frequency (in units of sample rate).
|
||||
/// * `q` - Quality factor (1/sqrt(2) for critical).
|
||||
/// * `k` - DC gain.
|
||||
///
|
||||
/// # Returns
|
||||
/// 2nd-order IIR filter coefficients in the form [b0,b1,b2,a1,a2]. a0 is set to -1.
|
||||
fn lowpass_iir_coefficients(fc: f64, q: f64, k: f64) -> IIRState {
|
||||
let f = 2. * PI * fc;
|
||||
let a = f.sin() / (2. * q);
|
||||
// IIR uses Q2.30 fixed point
|
||||
let a0 = (1. + a) / (1 << IIR::SHIFT) as f64;
|
||||
let b0 = (k / 2. * (1. - f.cos()) / a0).round() as _;
|
||||
let a1 = (2. * f.cos() / a0).round() as _;
|
||||
let a2 = ((a - 1.) / a0).round() as _;
|
||||
|
||||
IIRState([b0, 2 * b0, b0, a1, a2])
|
||||
}
|
||||
|
||||
/// Compute the maximum effect of input noise on the lock-in magnitude computation.
|
||||
///
|
||||
/// The maximum effect of noise on the magnitude computation is given by:
|
||||
@ -415,7 +393,7 @@ mod test {
|
||||
harmonic,
|
||||
(demodulation_phase_offset / (2. * PI) * (1i64 << 32) as f64)
|
||||
.round() as i32,
|
||||
&lowpass_iir_coefficients(
|
||||
&IIRState::lowpass(
|
||||
corner_frequency,
|
||||
1. / 2f64.sqrt(), // critical q
|
||||
2.,
|
||||
|
@ -56,7 +56,7 @@ const APP: () = {
|
||||
let pll = RPLL::new(ADC_SAMPLE_TICKS_LOG2 + SAMPLE_BUFFER_SIZE_LOG2, 0);
|
||||
|
||||
let lockin = Lockin::new(
|
||||
&iir_int::IIRState::default(), // TODO: lowpass, expose
|
||||
&iir_int::IIRState::lowpass(1e-3, 0.707, 2.), // TODO: expose
|
||||
);
|
||||
|
||||
// Enable ADC/DAC events
|
||||
@ -119,8 +119,8 @@ const APP: () = {
|
||||
|
||||
let (pll_phase, pll_frequency) = c.resources.pll.update(
|
||||
c.resources.timestamper.latest_timestamp().map(|t| t as i32),
|
||||
21, // relative PLL frequency bandwidth: 2**-21, TODO: expose
|
||||
21, // relative PLL phase bandwidth: 2**-21, TODO: expose
|
||||
22, // relative PLL frequency bandwidth: 2**-22, TODO: expose
|
||||
22, // relative PLL phase bandwidth: 2**-22, TODO: expose
|
||||
);
|
||||
|
||||
// Harmonic index of the LO: -1 to _de_modulate the fundamental
|
||||
|
Loading…
Reference in New Issue
Block a user