use core::{cell::Cell, convert::Infallible, fmt};
use embassy_futures::select::{Either, select};
use esp_hal::{i2s::master::I2s, peripherals::GPIO46};
use crate::{
Error, SpeakerPins,
microphone::Microphone,
speaker::{Speaker, i2s_config},
};
#[derive(Debug)]
pub struct AudioPins {
pub speaker: SpeakerPins,
pub din: GPIO46<'static>,
}
pub struct Audio {
speaker: Speaker,
microphone: Microphone,
}
impl Audio {
pub async fn run(
&mut self,
fill: impl FnMut(&mut [i16]),
take: impl FnMut(&[i16]),
) -> Result<Infallible, Error> {
let resettle = Cell::new(false);
let speaker = self.speaker.stream(fill, || resettle.set(true));
let microphone = self.microphone.run(&resettle, take);
match select(speaker, microphone).await {
Either::First(stopped) | Either::Second(stopped) => stopped,
}
}
}
pub fn audio(pins: AudioPins) -> Result<Audio, Error> {
let SpeakerPins {
i2s,
dma,
bclk,
ws,
dout,
} = pins.speaker;
let i2s = I2s::new(i2s, dma, i2s_config().with_signal_loopback(true))
.map_err(|_| Error::Speaker)?
.into_async();
let rx = i2s.i2s_rx.with_din(pins.din).build();
let tx = i2s
.i2s_tx
.with_bclk(bclk)
.with_ws(ws)
.with_dout(dout)
.build();
Ok(Audio {
speaker: Speaker::start(tx)?,
microphone: Microphone::start(rx)?,
})
}
impl fmt::Debug for Audio {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Audio")
.field("speaker", &self.speaker)
.field("microphone", &self.microphone)
.finish()
}
}