dsp/lowpass,lockin: const generics

This commit is contained in:
Robert Jördens 2021-05-10 17:31:53 +02:00
parent 33549793ca
commit bcdb5e3c0f
8 changed files with 21 additions and 17 deletions

View File

@ -9,8 +9,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Added ### Added
* Telemetry
### Changed ### Changed
* Const generics bumping the MSRV to 1.51.0
### Fixed ### Fixed
## [v0.5.0] - 2021-04-21 ## [v0.5.0] - 2021-04-21

1
Cargo.lock generated
View File

@ -215,7 +215,6 @@ name = "dsp"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"easybench", "easybench",
"generic-array 0.14.4",
"libm", "libm",
"miniconf", "miniconf",
"ndarray", "ndarray",

View File

@ -37,6 +37,7 @@ to implement different use cases. Several applications are provides by default
* Get [rustup](https://rustup.rs/) * Get [rustup](https://rustup.rs/)
* `rustup target add thumbv7em-none-eabihf` * `rustup target add thumbv7em-none-eabihf`
* `cargo build --release` * `cargo build --release`
* Minimum supported Rust version (MSRV) is 1.51.0
* When using debug (non `--release`) mode, increase the sample interval significantly. * When using debug (non `--release`) mode, increase the sample interval significantly.
The added error checking code and missing optimizations may lead to the code The added error checking code and missing optimizations may lead to the code
missing deadlines and panicing. missing deadlines and panicing.

View File

@ -7,7 +7,6 @@ edition = "2018"
[dependencies] [dependencies]
libm = "0.2.1" libm = "0.2.1"
serde = { version = "1.0", features = ["derive"], default-features = false } serde = { version = "1.0", features = ["derive"], default-features = false }
generic-array = "0.14"
num = { version = "0.4.0", default-features = false } num = { version = "0.4.0", default-features = false }
miniconf = "0.1" miniconf = "0.1"

View File

@ -1,7 +1,6 @@
use core::f32::consts::PI; use core::f32::consts::PI;
use easybench::bench_env; use easybench::bench_env;
use generic_array::typenum::U4;
use dsp::{atan2, cossin, iir, iir_int, Lowpass, PLL, RPLL}; use dsp::{atan2, cossin, iir, iir_int, Lowpass, PLL, RPLL};
@ -72,13 +71,13 @@ fn iir_bench() {
} }
fn lowpass_bench() { fn lowpass_bench() {
let mut dut = Lowpass::<U4>::default(); let mut dut = Lowpass::<4>::default();
println!( println!(
"Lowpass::<U4>::update(x, k): {}", "Lowpass::<4>::update(x, k): {}",
bench_env((0x32421, 14), |(x, k)| dut.update(*x, *k)) bench_env((0x32421, 14), |(x, k)| dut.update(*x, *k))
); );
println!( println!(
"Lowpass::<U4>::update(x, 14): {}", "Lowpass::<4>::update(x, 14): {}",
bench_env(0x32421, |x| dut.update(*x, 14)) bench_env(0x32421, |x| dut.update(*x, 14))
); );
} }

View File

@ -1,12 +1,11 @@
use super::{Complex, ComplexExt, Lowpass, MulScaled}; use super::{Complex, ComplexExt, Lowpass, MulScaled};
use generic_array::ArrayLength;
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct Lockin<N: ArrayLength<i32>> { pub struct Lockin<const N: usize> {
state: [Lowpass<N>; 2], state: [Lowpass<N>; 2],
} }
impl<N: ArrayLength<i32>> Lockin<N> { impl<const N: usize> Lockin<N> {
/// Update the lockin with a sample taken at a given phase. /// Update the lockin with a sample taken at a given phase.
pub fn update(&mut self, sample: i32, phase: i32, k: u8) -> Complex<i32> { pub fn update(&mut self, sample: i32, phase: i32, k: u8) -> Complex<i32> {
// Get the LO signal for demodulation and mix the sample; // Get the LO signal for demodulation and mix the sample;

View File

@ -1,16 +1,20 @@
use generic_array::{ArrayLength, GenericArray};
/// Arbitrary order, high dynamic range, wide coefficient range, /// Arbitrary order, high dynamic range, wide coefficient range,
/// lowpass filter implementation. DC gain is 1. /// lowpass filter implementation. DC gain is 1.
/// ///
/// Type argument N is the filter order. /// Type argument N is the filter order.
#[derive(Clone, Default)] #[derive(Clone)]
pub struct Lowpass<N: ArrayLength<i32>> { pub struct Lowpass<const N: usize> {
// IIR state storage // IIR state storage
y: GenericArray<i32, N>, y: [i32; N],
} }
impl<N: ArrayLength<i32>> Lowpass<N> { impl<const N: usize> Default for Lowpass<N> {
fn default() -> Self {
Lowpass { y: [0i32; N] }
}
}
impl<const N: usize> Lowpass<N> {
/// Update the filter with a new sample. /// Update the filter with a new sample.
/// ///
/// # Args /// # Args

View File

@ -3,7 +3,6 @@
#![no_main] #![no_main]
use embedded_hal::digital::v2::InputPin; use embedded_hal::digital::v2::InputPin;
use generic_array::typenum::U4;
use serde::Deserialize; use serde::Deserialize;
@ -92,7 +91,7 @@ const APP: () = {
timestamper: InputStamper, timestamper: InputStamper,
pll: RPLL, pll: RPLL,
lockin: Lockin<U4>, lockin: Lockin<4>,
} }
#[init(spawn=[settings_update, telemetry])] #[init(spawn=[settings_update, telemetry])]