From a46f33b2144df0b913b50bb8c78256e20bce84c8 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 16:37:51 -0400 Subject: Initial PDM driver --- examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm.rs | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 examples/nrf/src/bin/pdm.rs (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 2fcc31221..673bcfc6b 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -27,6 +27,7 @@ cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } rand = { version = "0.8.4", default-features = false } +fixed = "1.10.0" embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs new file mode 100644 index 000000000..d5e90e27a --- /dev/null +++ b/examples/nrf/src/bin/pdm.rs @@ -0,0 +1,34 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::pdm::{Config, Channels, Pdm}; +use embassy_time::{Duration, Timer}; +use fixed::types::I7F1; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_p: Spawner) { + let mut p = embassy_nrf::init(Default::default()); + let mut config = Config::default(); + // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.channels = Channels::Mono; + config.gain_left = I7F1::from_bits(5); // 2.5 dB + let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); + + loop { + let mut buf = [0; 128]; + pdm.sample(&mut buf).await; + info!( + "{} samples, min {=i16}, max {=i16}, mean {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16, + ); + Timer::after(Duration::from_millis(100)).await; + } +} -- cgit From 530f192acceb5a10c416e1823dc27a749e68b7dc Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 17:08:29 -0400 Subject: Set gain at runtime --- examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm.rs | 29 +++++++++++++++++++---------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index 673bcfc6b..d0567ba8e 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -31,3 +31,4 @@ fixed = "1.10.0" embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } +num-integer = { version = "0.1.45", default-features = false } diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index d5e90e27a..a73d01fb9 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -8,6 +8,7 @@ use embassy_nrf::interrupt; use embassy_nrf::pdm::{Config, Channels, Pdm}; use embassy_time::{Duration, Timer}; use fixed::types::I7F1; +use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; #[embassy_executor::main] @@ -20,15 +21,23 @@ async fn main(_p: Spawner) { let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); loop { - let mut buf = [0; 128]; - pdm.sample(&mut buf).await; - info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}", - buf.len(), - buf.iter().min().unwrap(), - buf.iter().max().unwrap(), - (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16, - ); - Timer::after(Duration::from_millis(100)).await; + for gain in [I7F1::from_num(-20), I7F1::from_num(0), I7F1::from_num(20)] { + pdm.set_gain(gain, gain); + info!("Gain = {} dB", defmt::Debug2Format(&gain)); + for _ in 0..10 { + let mut buf = [0; 128]; + pdm.sample(&mut buf).await; + info!( + "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + ( + buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + / buf.len() as i32).sqrt() as i16, + ); + Timer::after(Duration::from_millis(100)).await; + } + } } } -- cgit From 0963b5f92c9588ab00f556a6c521fad059eac72e Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sat, 20 Aug 2022 17:58:54 -0400 Subject: Add continuous PDM sampling with example --- examples/nrf/src/bin/pdm.rs | 3 +- examples/nrf/src/bin/pdm_continuous.rs | 50 ++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 examples/nrf/src/bin/pdm_continuous.rs (limited to 'examples') diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index a73d01fb9..85a59a529 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -25,7 +25,7 @@ async fn main(_p: Spawner) { pdm.set_gain(gain, gain); info!("Gain = {} dB", defmt::Debug2Format(&gain)); for _ in 0..10 { - let mut buf = [0; 128]; + let mut buf = [0; 1500]; pdm.sample(&mut buf).await; info!( "{} samples, min {=i16}, max {=i16}, RMS {=i16}", @@ -36,6 +36,7 @@ async fn main(_p: Spawner) { buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); + info!("samples = {}", &buf); Timer::after(Duration::from_millis(100)).await; } } diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs new file mode 100644 index 000000000..e7d1806bb --- /dev/null +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -0,0 +1,50 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_nrf::interrupt; +use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; +use embassy_nrf::timer::Frequency; +use fixed::types::I7F1; +use num_integer::Roots; +use {defmt_rtt as _, panic_probe as _}; + +// Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer + +#[embassy_executor::main] +async fn main(_p: Spawner) { + let mut p = embassy_nrf::init(Default::default()); + let mut config = Config::default(); + // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.channels = Channels::Mono; + config.gain_left = I7F1::from_bits(5); // 2.5 dB + let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); + + let mut bufs = [[0; 500]; 2]; + + pdm + .run_task_sampler( + &mut bufs, + move |buf| { + // NOTE: It is important that the time spent within this callback + // does not exceed the time taken to acquire the 1500 samples we + // have in this example, which would be 10us + 2us per + // sample * 1500 = 18ms. You need to measure the time taken here + // and set the sample buffer size accordingly. Exceeding this + // time can lead to the peripheral re-writing the other buffer. + info!( + "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + ( + buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + / buf.len() as i32).sqrt() as i16, + ); + SamplerState::Sampled + }, + ) + .await; +} -- cgit From 3d26573c6b36c670a170279db49e7adc5e37466b Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 01:44:04 -0400 Subject: Discard the first N samples due to transients --- examples/nrf/src/bin/pdm.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/pdm.rs b/examples/nrf/src/bin/pdm.rs index 85a59a529..605eca59e 100644 --- a/examples/nrf/src/bin/pdm.rs +++ b/examples/nrf/src/bin/pdm.rs @@ -26,14 +26,16 @@ async fn main(_p: Spawner) { info!("Gain = {} dB", defmt::Debug2Format(&gain)); for _ in 0..10 { let mut buf = [0; 1500]; - pdm.sample(&mut buf).await; + pdm.sample(5, &mut buf).await; + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; info!( - "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), + mean, ( - buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); info!("samples = {}", &buf); -- cgit From ed97e61dbecc636c3cc9f67778d4b7eb48cff893 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 02:16:26 -0400 Subject: PDM clock frequency control --- examples/nrf/src/bin/pdm_continuous.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index e7d1806bb..33ba1e274 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -5,8 +5,7 @@ use defmt::info; use embassy_executor::Spawner; use embassy_nrf::interrupt; -use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; -use embassy_nrf::timer::Frequency; +use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; @@ -18,11 +17,13 @@ async fn main(_p: Spawner) { let mut p = embassy_nrf::init(Default::default()); let mut config = Config::default(); // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. + config.frequency = Frequency::_1280K; // 16 kHz sample rate + config.ratio = Ratio::RATIO80; config.channels = Channels::Mono; config.gain_left = I7F1::from_bits(5); // 2.5 dB let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); - let mut bufs = [[0; 500]; 2]; + let mut bufs = [[0; 1024]; 2]; pdm .run_task_sampler( @@ -34,13 +35,15 @@ async fn main(_p: Spawner) { // sample * 1500 = 18ms. You need to measure the time taken here // and set the sample buffer size accordingly. Exceeding this // time can lead to the peripheral re-writing the other buffer. + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; info!( - "{} samples, min {=i16}, max {=i16}, RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), + mean, ( - buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) + buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, ); SamplerState::Sampled -- cgit From 64154fec8cd7497992ef0d93f319b98215b8a84e Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 02:43:13 -0400 Subject: Demonstrate FFT in example --- examples/nrf/Cargo.toml | 1 + examples/nrf/src/bin/pdm_continuous.rs | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml index d0567ba8e..876dcf734 100644 --- a/examples/nrf/Cargo.toml +++ b/examples/nrf/Cargo.toml @@ -32,3 +32,4 @@ embedded-storage = "0.3.0" usbd-hid = "0.5.2" serde = { version = "1.0.136", default-features = false } num-integer = { version = "0.1.45", default-features = false } +microfft = "0.5.0" diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index 33ba1e274..e78bc40dc 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -3,11 +3,13 @@ #![feature(type_alias_impl_trait)] use defmt::info; +use core::cmp::Ordering; use embassy_executor::Spawner; use embassy_nrf::interrupt; use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; use num_integer::Roots; +use microfft::real::rfft_1024; use {defmt_rtt as _, panic_probe as _}; // Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer @@ -36,8 +38,10 @@ async fn main(_p: Spawner) { // and set the sample buffer size accordingly. Exceeding this // time can lead to the peripheral re-writing the other buffer. let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; + let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); + let peak_freq = peak_freq_index * 16000 / buf.len(); info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}", + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", buf.len(), buf.iter().min().unwrap(), buf.iter().max().unwrap(), @@ -45,9 +49,27 @@ async fn main(_p: Spawner) { ( buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) / buf.len() as i32).sqrt() as i16, + peak_mag, peak_freq, ); SamplerState::Sampled }, ) .await; } + +fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { + let mut f = [0f32; 1024]; + for i in 0..input.len() { + f[i] = (input[i] as f32) / 32768.0; + } + // N.B. rfft_1024 does the FFT in-place so result is actually also a reference to f. + let result = rfft_1024(&mut f); + result[0].im = 0.0; + + result + .iter() + .map(|c| ((c.norm_sqr()*32768.0) as u32).sqrt()) + .enumerate() + .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) + .unwrap() +} \ No newline at end of file -- cgit From 14eae9ca06f63a69ccc29d5fd9e1dec3848a3e98 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Sun, 21 Aug 2022 12:40:51 -0400 Subject: Optimize pdm_continuous example --- examples/nrf/src/bin/pdm_continuous.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/nrf/src/bin/pdm_continuous.rs b/examples/nrf/src/bin/pdm_continuous.rs index e78bc40dc..284a68af2 100644 --- a/examples/nrf/src/bin/pdm_continuous.rs +++ b/examples/nrf/src/bin/pdm_continuous.rs @@ -68,8 +68,9 @@ fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { result .iter() - .map(|c| ((c.norm_sqr()*32768.0) as u32).sqrt()) + .map(|c| c.norm_sqr()) .enumerate() .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) + .map(|(i, v)| (i, ((v*32768.0) as u32).sqrt())) .unwrap() -} \ No newline at end of file +} -- cgit From c333d855fca0743de1d58ef14e3c2f6389f73145 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 17:13:43 -0400 Subject: Remove merge error --- examples/nrf/Cargo.toml | 37 ------------------------------------- 1 file changed, 37 deletions(-) delete mode 100644 examples/nrf/Cargo.toml (limited to 'examples') diff --git a/examples/nrf/Cargo.toml b/examples/nrf/Cargo.toml deleted file mode 100644 index 8309dda08..000000000 --- a/examples/nrf/Cargo.toml +++ /dev/null @@ -1,37 +0,0 @@ -[package] -edition = "2021" -name = "embassy-nrf-examples" -version = "0.1.0" - -[features] -default = ["nightly"] -nightly = ["embassy-executor/nightly", "embassy-nrf/nightly", "embassy-nrf/unstable-traits", "embassy-usb", "embassy-usb-serial", "embassy-usb-hid", "embassy-usb-ncm", "embedded-io/async", "embassy-net"] - -[dependencies] -embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } -embassy-sync = { version = "0.1.0", path = "../../embassy-sync", features = ["defmt"] } -embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "integrated-timers"] } -embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.1.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac"] } -embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", "pool-16"], optional = true } -embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"], optional = true } -embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"], optional = true } -embassy-usb-hid = { version = "0.1.0", path = "../../embassy-usb-hid", features = ["defmt"], optional = true } -embassy-usb-ncm = { version = "0.1.0", path = "../../embassy-usb-ncm", features = ["defmt"], optional = true } -embedded-io = "0.3.0" - -defmt = "0.3" -defmt-rtt = "0.3" - -static_cell = "1.0" -cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } -cortex-m-rt = "0.7.0" -panic-probe = { version = "0.3", features = ["print-defmt"] } -futures = { version = "0.3.17", default-features = false, features = ["async-await"] } -rand = { version = "0.8.4", default-features = false } -fixed = "1.10.0" -embedded-storage = "0.3.0" -usbd-hid = "0.5.2" -serde = { version = "1.0.136", default-features = false } -num-integer = { version = "0.1.45", default-features = false } -microfft = "0.5.0" -- cgit From 2c01f277c27bc6ca4f3d41ac57aa1ea24868cfc1 Mon Sep 17 00:00:00 2001 From: Quentin Smith Date: Tue, 18 Jul 2023 17:17:04 -0400 Subject: cargo fmt --- examples/nrf52840/src/bin/pdm.rs | 8 ++-- examples/nrf52840/src/bin/pdm_continuous.rs | 65 +++++++++++++++-------------- 2 files changed, 38 insertions(+), 35 deletions(-) (limited to 'examples') diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs index 47fe67733..444b9137f 100644 --- a/examples/nrf52840/src/bin/pdm.rs +++ b/examples/nrf52840/src/bin/pdm.rs @@ -41,9 +41,11 @@ async fn main(_p: Spawner) { buf.iter().min().unwrap(), buf.iter().max().unwrap(), mean, - ( - buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) - / buf.len() as i32).sqrt() as i16, + (buf.iter() + .map(|v| i32::from(*v - mean).pow(2)) + .fold(0i32, |a, b| a.saturating_add(b)) + / buf.len() as i32) + .sqrt() as i16, ); info!("samples: {:?}", &buf); diff --git a/examples/nrf52840/src/bin/pdm_continuous.rs b/examples/nrf52840/src/bin/pdm_continuous.rs index 9eaf30717..7d8531475 100644 --- a/examples/nrf52840/src/bin/pdm_continuous.rs +++ b/examples/nrf52840/src/bin/pdm_continuous.rs @@ -2,14 +2,15 @@ #![no_main] #![feature(type_alias_impl_trait)] -use defmt::info; use core::cmp::Ordering; + +use defmt::info; use embassy_executor::Spawner; +use embassy_nrf::pdm::{self, Config, Frequency, OperationMode, Pdm, Ratio, SamplerState}; use embassy_nrf::{bind_interrupts, peripherals}; -use embassy_nrf::pdm::{self, Config, OperationMode, Pdm, SamplerState, Frequency, Ratio}; use fixed::types::I7F1; -use num_integer::Roots; use microfft::real::rfft_1024; +use num_integer::Roots; use {defmt_rtt as _, panic_probe as _}; // Demonstrates both continuous sampling and scanning multiple channels driven by a PPI linked timer @@ -31,34 +32,34 @@ async fn main(_p: Spawner) { let mut bufs = [[0; 1024]; 2]; - pdm - .run_task_sampler( - &mut bufs, - move |buf| { - // NOTE: It is important that the time spent within this callback - // does not exceed the time taken to acquire the 1500 samples we - // have in this example, which would be 10us + 2us per - // sample * 1500 = 18ms. You need to measure the time taken here - // and set the sample buffer size accordingly. Exceeding this - // time can lead to the peripheral re-writing the other buffer. - let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; - let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); - let peak_freq = peak_freq_index * 16000 / buf.len(); - info!( - "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", - buf.len(), - buf.iter().min().unwrap(), - buf.iter().max().unwrap(), - mean, - ( - buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) - / buf.len() as i32).sqrt() as i16, - peak_mag, peak_freq, - ); - SamplerState::Sampled - }, - ) - .await.unwrap(); + pdm.run_task_sampler(&mut bufs, move |buf| { + // NOTE: It is important that the time spent within this callback + // does not exceed the time taken to acquire the 1500 samples we + // have in this example, which would be 10us + 2us per + // sample * 1500 = 18ms. You need to measure the time taken here + // and set the sample buffer size accordingly. Exceeding this + // time can lead to the peripheral re-writing the other buffer. + let mean = (buf.iter().map(|v| i32::from(*v)).sum::() / buf.len() as i32) as i16; + let (peak_freq_index, peak_mag) = fft_peak_freq(&buf); + let peak_freq = peak_freq_index * 16000 / buf.len(); + info!( + "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}, peak {} @ {} Hz", + buf.len(), + buf.iter().min().unwrap(), + buf.iter().max().unwrap(), + mean, + (buf.iter() + .map(|v| i32::from(*v - mean).pow(2)) + .fold(0i32, |a, b| a.saturating_add(b)) + / buf.len() as i32) + .sqrt() as i16, + peak_mag, + peak_freq, + ); + SamplerState::Sampled + }) + .await + .unwrap(); } fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { @@ -75,6 +76,6 @@ fn fft_peak_freq(input: &[i16; 1024]) -> (usize, u32) { .map(|c| c.norm_sqr()) .enumerate() .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap_or(Ordering::Equal)) - .map(|(i, v)| (i, ((v*32768.0) as u32).sqrt())) + .map(|(i, v)| (i, ((v * 32768.0) as u32).sqrt())) .unwrap() } -- cgit