use embassy_nrf::gpio::{Level, Output, OutputDrive};
use embassy_nrf::interrupt;
use embassy_nrf::interrupt::typelevel::Binding;
use embassy_nrf::peripherals::{P0_05, P0_20, SAADC};
use embassy_nrf::saadc::*;
use embassy_nrf::Peri;
use embassy_time::{Duration, Timer};
pub struct Microphone<'a> {
adc: Saadc<'a, 1>,
enable: Output<'a>,
}
impl<'a> Microphone<'a> {
pub fn new(
saadc: Peri<'static, SAADC>,
irq: impl Binding<interrupt::typelevel::SAADC, InterruptHandler> + 'a,
mic: Peri<'static, P0_05>,
micen: Peri<'static, P0_20>,
) -> Self {
let config = Config::default();
let mut channel_config = ChannelConfig::single_ended(mic);
channel_config.gain = Gain::GAIN4;
let saadc = Saadc::new(saadc, irq, config, [channel_config]);
let enable = Output::new(micen, Level::Low, OutputDrive::HighDrive);
Self { adc: saadc, enable }
}
pub async fn sound_level(&mut self) -> u8 {
self.enable.set_high();
Timer::after(Duration::from_millis(10)).await;
let mut bufs = [[[0; 1]; 1024]; 2];
self.adc
.run_timer_sampler::<u32, _, 1024>(&mut bufs, 727, move |_| CallbackResult::Stop)
.await;
self.enable.set_low();
let mut max: i16 = i16::MIN;
let mut min: i16 = i16::MAX;
for b in bufs[0] {
if b[0] > max {
max = b[0];
}
if b[0] < min {
min = b[0];
}
}
let amplitude = max - min;
(amplitude / 16) as u8
}
}