aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/pdm.rs13
-rw-r--r--examples/nrf/src/bin/pdm_continuous.rs13
2 files changed, 18 insertions, 8 deletions
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index 6a070e7bc..b58a0e976 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -9,6 +9,8 @@ use embassy_util::waitqueue::AtomicWaker;
9use futures::future::poll_fn; 9use futures::future::poll_fn;
10use pac::{pdm, PDM}; 10use pac::{pdm, PDM};
11use pdm::mode::{EDGE_A, OPERATION_A}; 11use pdm::mode::{EDGE_A, OPERATION_A};
12pub use pdm::pdmclkctrl::FREQ_A as Frequency;
13pub use pdm::ratio::RATIO_A as Ratio;
12use fixed::types::I7F1; 14use fixed::types::I7F1;
13 15
14use crate::interrupt::InterruptExt; 16use crate::interrupt::InterruptExt;
@@ -32,8 +34,10 @@ static WAKER: AtomicWaker = AtomicWaker::new();
32/// See the `Default` impl for suitable default values. 34/// See the `Default` impl for suitable default values.
33#[non_exhaustive] 35#[non_exhaustive]
34pub struct Config { 36pub struct Config {
35 /// Clock 37 /// Clock frequency
38 pub frequency: Frequency,
36 /// Clock ratio 39 /// Clock ratio
40 pub ratio: Ratio,
37 /// Channels 41 /// Channels
38 pub channels: Channels, 42 pub channels: Channels,
39 /// Edge to sample on 43 /// Edge to sample on
@@ -48,6 +52,8 @@ impl Default for Config {
48 /// Default configuration for single channel sampling. 52 /// Default configuration for single channel sampling.
49 fn default() -> Self { 53 fn default() -> Self {
50 Self { 54 Self {
55 frequency: Frequency::DEFAULT,
56 ratio: Ratio::RATIO80,
51 channels: Channels::Stereo, 57 channels: Channels::Stereo,
52 left_edge: Edge::FallingEdge, 58 left_edge: Edge::FallingEdge,
53 gain_left: I7F1::ZERO, 59 gain_left: I7F1::ZERO,
@@ -78,11 +84,12 @@ impl<'d> Pdm<'d> {
78 84
79 let r = unsafe { &*PDM::ptr() }; 85 let r = unsafe { &*PDM::ptr() };
80 86
81 let Config { channels, left_edge, gain_left, gain_right } = config; 87 let Config { frequency, ratio, channels, left_edge, gain_left, gain_right } = config;
82 88
83 // Configure channels 89 // Configure channels
84 r.enable.write(|w| w.enable().enabled()); 90 r.enable.write(|w| w.enable().enabled());
85 // TODO: Clock control 91 r.pdmclkctrl.write(|w| w.freq().variant(frequency));
92 r.ratio.write(|w| w.ratio().variant(ratio));
86 r.mode.write(|w| { 93 r.mode.write(|w| {
87 w.operation().variant(channels.into()); 94 w.operation().variant(channels.into());
88 w.edge().variant(left_edge.into()); 95 w.edge().variant(left_edge.into());
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 @@
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt; 7use embassy_nrf::interrupt;
8use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState}; 8use embassy_nrf::pdm::{Config, Channels, Pdm, SamplerState, Frequency, Ratio};
9use embassy_nrf::timer::Frequency;
10use fixed::types::I7F1; 9use fixed::types::I7F1;
11use num_integer::Roots; 10use num_integer::Roots;
12use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
@@ -18,11 +17,13 @@ async fn main(_p: Spawner) {
18 let mut p = embassy_nrf::init(Default::default()); 17 let mut p = embassy_nrf::init(Default::default());
19 let mut config = Config::default(); 18 let mut config = Config::default();
20 // Pins are correct for the onboard microphone on the Feather nRF52840 Sense. 19 // Pins are correct for the onboard microphone on the Feather nRF52840 Sense.
20 config.frequency = Frequency::_1280K; // 16 kHz sample rate
21 config.ratio = Ratio::RATIO80;
21 config.channels = Channels::Mono; 22 config.channels = Channels::Mono;
22 config.gain_left = I7F1::from_bits(5); // 2.5 dB 23 config.gain_left = I7F1::from_bits(5); // 2.5 dB
23 let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config); 24 let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), &mut p.P0_00, &mut p.P0_01, config);
24 25
25 let mut bufs = [[0; 500]; 2]; 26 let mut bufs = [[0; 1024]; 2];
26 27
27 pdm 28 pdm
28 .run_task_sampler( 29 .run_task_sampler(
@@ -34,13 +35,15 @@ async fn main(_p: Spawner) {
34 // sample * 1500 = 18ms. You need to measure the time taken here 35 // sample * 1500 = 18ms. You need to measure the time taken here
35 // and set the sample buffer size accordingly. Exceeding this 36 // and set the sample buffer size accordingly. Exceeding this
36 // time can lead to the peripheral re-writing the other buffer. 37 // time can lead to the peripheral re-writing the other buffer.
38 let mean = (buf.iter().map(|v| i32::from(*v)).sum::<i32>() / buf.len() as i32) as i16;
37 info!( 39 info!(
38 "{} samples, min {=i16}, max {=i16}, RMS {=i16}", 40 "{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}",
39 buf.len(), 41 buf.len(),
40 buf.iter().min().unwrap(), 42 buf.iter().min().unwrap(),
41 buf.iter().max().unwrap(), 43 buf.iter().max().unwrap(),
44 mean,
42 ( 45 (
43 buf.iter().map(|v| i32::from(*v).pow(2)).fold(0i32, |a,b| a.saturating_add(b)) 46 buf.iter().map(|v| i32::from(*v - mean).pow(2)).fold(0i32, |a,b| a.saturating_add(b))
44 / buf.len() as i32).sqrt() as i16, 47 / buf.len() as i32).sqrt() as i16,
45 ); 48 );
46 SamplerState::Sampled 49 SamplerState::Sampled