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