Discard the first N samples due to transients
This commit is contained in:
parent
0963b5f92c
commit
3d26573c6b
@ -139,7 +139,8 @@ impl<'d> Pdm<'d> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// One shot sampling. If the PDM is configured for multiple channels, the samples will be interleaved.
|
/// One shot sampling. If the PDM is configured for multiple channels, the samples will be interleaved.
|
||||||
pub async fn sample<const N: usize>(&mut self, buf: &mut [i16; N]) {
|
/// The first samples from the PDM peripheral and microphone usually contain garbage data, so the discard parameter sets the number of complete buffers to discard before returning.
|
||||||
|
pub async fn sample<const N: usize>(&mut self, mut discard: usize, buf: &mut [i16; N]) {
|
||||||
let r = Self::regs();
|
let r = Self::regs();
|
||||||
|
|
||||||
// Set up the DMA
|
// Set up the DMA
|
||||||
@ -148,9 +149,11 @@ impl<'d> Pdm<'d> {
|
|||||||
|
|
||||||
// Reset and enable the events
|
// Reset and enable the events
|
||||||
r.events_end.reset();
|
r.events_end.reset();
|
||||||
|
r.events_started.reset();
|
||||||
r.events_stopped.reset();
|
r.events_stopped.reset();
|
||||||
r.intenset.write(|w| {
|
r.intenset.write(|w| {
|
||||||
w.end().set();
|
w.end().set();
|
||||||
|
w.started().set();
|
||||||
w.stopped().set();
|
w.stopped().set();
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
@ -168,13 +171,26 @@ impl<'d> Pdm<'d> {
|
|||||||
WAKER.register(cx.waker());
|
WAKER.register(cx.waker());
|
||||||
|
|
||||||
if r.events_end.read().bits() != 0 {
|
if r.events_end.read().bits() != 0 {
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
// END means the whole buffer has been received.
|
// END means the whole buffer has been received.
|
||||||
r.events_end.reset();
|
r.events_end.reset();
|
||||||
// Note that the beginning of the buffer might be overwritten before the task fully stops :(
|
r.intenset.write(|w| w.end().set());
|
||||||
r.tasks_stop.write(|w| w.tasks_stop().set_bit());
|
|
||||||
|
if discard > 0 {
|
||||||
|
discard -= 1;
|
||||||
|
} else {
|
||||||
|
// Note that the beginning of the buffer might be overwritten before the task fully stops :(
|
||||||
|
r.tasks_stop.write(|w| w.tasks_stop().set_bit());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.events_started.read().bits() != 0 {
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
|
r.events_started.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.events_stopped.read().bits() != 0 {
|
if r.events_stopped.read().bits() != 0 {
|
||||||
|
compiler_fence(Ordering::SeqCst);
|
||||||
r.events_stopped.reset();
|
r.events_stopped.reset();
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
|
@ -26,14 +26,16 @@ async fn main(_p: Spawner) {
|
|||||||
info!("Gain = {} dB", defmt::Debug2Format(&gain));
|
info!("Gain = {} dB", defmt::Debug2Format(&gain));
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
let mut buf = [0; 1500];
|
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::<i32>() / buf.len() as i32) as i16;
|
||||||
info!(
|
info!(
|
||||||
"{} samples, min {=i16}, max {=i16}, RMS {=i16}",
|
"{} samples, min {=i16}, max {=i16}, mean {=i16}, AC RMS {=i16}",
|
||||||
buf.len(),
|
buf.len(),
|
||||||
buf.iter().min().unwrap(),
|
buf.iter().min().unwrap(),
|
||||||
buf.iter().max().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,
|
/ buf.len() as i32).sqrt() as i16,
|
||||||
);
|
);
|
||||||
info!("samples = {}", &buf);
|
info!("samples = {}", &buf);
|
||||||
|
Loading…
Reference in New Issue
Block a user