1use embassy_nrf::gpio::{Level, Output, OutputDrive};
3use embassy_nrf::interrupt;
4use embassy_nrf::interrupt::typelevel::Binding;
5use embassy_nrf::peripherals::{P0_05, P0_20, SAADC};
6use embassy_nrf::saadc::*;
7use embassy_nrf::Peri;
8use embassy_time::{Duration, Timer};
9
10pub struct Microphone<'a> {
12 adc: Saadc<'a, 1>,
13 enable: Output<'a>,
14}
15
16impl<'a> Microphone<'a> {
17 pub fn new(
19 saadc: Peri<'static, SAADC>,
20 irq: impl Binding<interrupt::typelevel::SAADC, InterruptHandler> + 'a,
21 mic: Peri<'static, P0_05>,
22 micen: Peri<'static, P0_20>,
23 ) -> Self {
24 let config = Config::default();
25 let mut channel_config = ChannelConfig::single_ended(mic);
26 channel_config.gain = Gain::GAIN4;
27 let saadc = Saadc::new(saadc, irq, config, [channel_config]);
28 let enable = Output::new(micen, Level::Low, OutputDrive::HighDrive);
29 Self { adc: saadc, enable }
30 }
31
32 pub async fn sound_level(&mut self) -> u8 {
36 self.enable.set_high();
37 Timer::after(Duration::from_millis(10)).await;
38
39 let mut bufs = [[[0; 1]; 1024]; 2];
40
41 self.adc
42 .run_timer_sampler::<u32, _, 1024>(&mut bufs, 727, move |_| CallbackResult::Stop)
43 .await;
44 self.enable.set_low();
45
46 let mut max: i16 = i16::MIN;
47 let mut min: i16 = i16::MAX;
48 for b in bufs[0] {
49 if b[0] > max {
50 max = b[0];
51 }
52 if b[0] < min {
53 min = b[0];
54 }
55 }
56 let amplitude = max - min;
57 (amplitude / 16) as u8
59 }
60}