1use embassy_time::Delay;
28use esp_hal::Async;
29use esp_hal::dma::{DmaError, DmaRxStreamBuf, DmaTxStreamBuf};
30use esp_hal::i2s::master::{
31 Channels, DataFormat, I2s, I2sRx, I2sRxDmaTransfer, I2sTx, I2sTxDmaTransfer, TdmConfig,
32};
33use esp_hal::peripherals::{DMA_CH1, GPIO41, GPIO42, GPIO43, GPIO46, I2S0};
34use esp_hal::time::Rate;
35use oxstack_drivers::es8311::{ADDRESS_CE_LOW, Es8311, Mode};
36pub use oxstack_drivers::es8311::{MicGain, SampleRate, Volume};
37
38use crate::i2c::{SysI2cBus, SysI2cDevice, device};
39
40pub const FRAME_BYTES: usize = 4;
42const CHUNK: usize = 2048;
51const STREAM_BYTES: usize = 8 * 4092;
53
54pub type Codec = Es8311<SysI2cDevice>;
56
57#[derive(Debug)]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60pub enum Error {
61 I2c(embassy_embedded_hal::shared_bus::I2cDeviceError<esp_hal::i2c::master::Error>),
63 Config(esp_hal::i2s::master::ConfigError),
65 I2s(esp_hal::i2s::master::Error),
67 Dma(DmaError),
69 Overrun,
72 Underrun,
75}
76
77impl From<embassy_embedded_hal::shared_bus::I2cDeviceError<esp_hal::i2c::master::Error>> for Error {
78 fn from(
79 e: embassy_embedded_hal::shared_bus::I2cDeviceError<esp_hal::i2c::master::Error>,
80 ) -> Self {
81 Error::I2c(e)
82 }
83}
84
85#[allow(missing_docs)]
87pub struct AudioResources<'d> {
88 pub i2s: I2S0<'d>,
89 pub dma: DMA_CH1<'d>,
90 pub bclk: GPIO41<'d>,
91 pub ws: GPIO43<'d>,
92 pub dout: GPIO42<'d>,
93 pub din: GPIO46<'d>,
94}
95reborrow_group!(AudioResources {
96 i2s,
97 dma,
98 bclk,
99 ws,
100 dout,
101 din
102});
103
104fn i2s_config(rate: SampleRate) -> TdmConfig {
105 TdmConfig::new_tdm_philips()
106 .with_sample_rate(Rate::from_hz(rate.hz()))
107 .with_data_format(DataFormat::Data16Channel16)
108 .with_channels(Channels::STEREO)
109}
110
111macro_rules! stream_memory {
114 () => {
115 static_dma_memory!(STREAM_BYTES, CHUNK)
116 };
117}
118
119impl<'d> AudioResources<'d> {
120 pub async fn recorder(
122 &mut self,
123 bus: &'static SysI2cBus,
124 rate: SampleRate,
125 gain: MicGain,
126 ) -> Result<Recorder<'_>, Error> {
127 let i2s = I2s::new(self.i2s.reborrow(), self.dma.reborrow(), i2s_config(rate))
128 .map_err(Error::Config)?
129 .into_async();
130 let rx = i2s
131 .i2s_rx
132 .with_bclk(self.bclk.reborrow())
133 .with_ws(self.ws.reborrow())
134 .with_din(self.din.reborrow())
135 .build();
136 let (buffer, descriptors) = stream_memory!();
137 let buf = DmaRxStreamBuf::new(descriptors, buffer).expect("valid DMA stream buffer");
138 let transfer = rx.read(buf).map_err(|(e, _, _)| Error::I2s(e))?;
140
141 let mut codec = Es8311::new(device(bus), ADDRESS_CE_LOW);
142 codec.init(&mut Delay).await?;
143 codec.set_mic_gain(gain).await?;
144 codec.set_mode(Mode::Record).await?;
145 Ok(Recorder {
146 codec,
147 rx: Stream::Running(transfer),
148 rate,
149 })
150 }
151
152 pub async fn player(
155 &mut self,
156 bus: &'static SysI2cBus,
157 rate: SampleRate,
158 volume: Volume,
159 ) -> Result<Player<'_>, Error> {
160 let i2s = I2s::new(self.i2s.reborrow(), self.dma.reborrow(), i2s_config(rate))
161 .map_err(Error::Config)?
162 .into_async();
163 let tx = i2s
164 .i2s_tx
165 .with_bclk(self.bclk.reborrow())
166 .with_ws(self.ws.reborrow())
167 .with_dout(self.dout.reborrow())
168 .build();
169 let (mut buffer, descriptors) = stream_memory!();
170 buffer.fill(0);
172 let buf = DmaTxStreamBuf::new(descriptors, buffer).expect("valid DMA stream buffer");
173 let transfer = tx.write(buf).map_err(|(e, _, _)| Error::I2s(e))?;
174
175 let mut codec = Es8311::new(device(bus), ADDRESS_CE_LOW);
176 codec.init(&mut Delay).await?;
177 codec.set_mode(Mode::Playback).await?;
178 codec.set_dac_volume(volume).await?;
179 Ok(Player {
180 codec,
181 tx: Stream::Running(transfer),
182 rate,
183 muted: true,
184 })
185 }
186}
187
188enum Stream<T, U, B> {
190 Running(T),
191 Stopped(U, B),
192 Poisoned,
193}
194
195type RxStream<'d> =
196 Stream<I2sRxDmaTransfer<'d, Async, DmaRxStreamBuf>, I2sRx<'d, Async>, DmaRxStreamBuf>;
197type TxStream<'d> =
198 Stream<I2sTxDmaTransfer<'d, Async, DmaTxStreamBuf>, I2sTx<'d, Async>, DmaTxStreamBuf>;
199
200pub struct Recorder<'d> {
202 codec: Codec,
203 rx: RxStream<'d>,
204 rate: SampleRate,
205}
206
207impl Recorder<'_> {
208 pub async fn read(&mut self, out: &mut [i16]) -> Result<usize, Error> {
219 let want = out.len() / 2 * FRAME_BYTES;
220 if want == 0 {
221 return Ok(0);
222 }
223 loop {
224 let Stream::Running(t) = &mut self.rx else {
225 self.restart()?;
226 continue;
227 };
228 let avail = t.available_bytes();
229 if avail >= FRAME_BYTES {
230 let n = avail.min(want) / FRAME_BYTES * FRAME_BYTES;
231 let popped = t.pop(as_bytes_mut(out, n));
232 return Ok(popped / 2);
233 }
234 if t.wait_for_available_async().await.is_err() {
235 self.restart()?;
236 return Err(Error::Overrun);
237 }
238 }
239 }
240
241 pub fn buffered_bytes(&mut self) -> usize {
243 match &mut self.rx {
244 Stream::Running(t) => t.available_bytes(),
245 _ => 0,
246 }
247 }
248
249 pub fn is_stopped(&mut self) -> bool {
251 match &mut self.rx {
252 Stream::Running(t) => t.is_done(),
253 _ => true,
254 }
255 }
256
257 pub async fn set_gain(&mut self, gain: MicGain) -> Result<(), Error> {
259 Ok(self.codec.set_mic_gain(gain).await?)
260 }
261
262 pub fn rate(&self) -> SampleRate {
264 self.rate
265 }
266
267 pub fn codec(&mut self) -> &mut Codec {
269 &mut self.codec
270 }
271
272 pub async fn shutdown(mut self) -> Result<(), Error> {
275 self.codec.set_mode(Mode::Off).await?;
276 Ok(()) }
278
279 fn restart(&mut self) -> Result<(), Error> {
280 let (rx, buf) = match core::mem::replace(&mut self.rx, Stream::Poisoned) {
281 Stream::Running(t) => t.stop(),
282 Stream::Stopped(rx, buf) => (rx, buf),
283 Stream::Poisoned => return Err(Error::Dma(DmaError::DescriptorError)),
284 };
285 match rx.read(buf) {
286 Ok(t) => {
287 self.rx = Stream::Running(t);
288 Ok(())
289 }
290 Err((e, rx, buf)) => {
291 self.rx = Stream::Stopped(rx, buf);
292 Err(Error::I2s(e))
293 }
294 }
295 }
296}
297
298pub struct Player<'d> {
300 codec: Codec,
301 tx: TxStream<'d>,
302 rate: SampleRate,
303 muted: bool,
304}
305
306impl Player<'_> {
307 pub async fn write(&mut self, samples: &[i16]) -> Result<(), Error> {
317 let mut rest = samples;
318 while !rest.is_empty() {
319 let n = self.write_some(rest).await?;
320 rest = &rest[n..];
321 }
322 Ok(())
323 }
324
325 pub async fn write_some(&mut self, samples: &[i16]) -> Result<usize, Error> {
332 let bytes = as_bytes(samples);
333 let bytes = &bytes[..bytes.len() / FRAME_BYTES * FRAME_BYTES];
334 if bytes.is_empty() {
335 return Ok(0);
336 }
337 loop {
338 let Stream::Running(t) = &mut self.tx else {
339 self.restart()?;
340 continue;
341 };
342 let space = t.available_bytes() / FRAME_BYTES * FRAME_BYTES;
343 if space > 0 {
344 let n = t.push(&bytes[..space.min(bytes.len())]);
345 if self.muted {
346 self.codec.set_dac_mute(false).await?;
349 self.muted = false;
350 }
351 return Ok(n / 2);
352 }
353 if t.wait_for_available_async().await.is_err() {
354 self.restart()?;
355 return Err(Error::Underrun);
356 }
357 }
358 }
359
360 pub async fn set_volume(&mut self, volume: Volume) -> Result<(), Error> {
362 Ok(self.codec.set_dac_volume(volume).await?)
363 }
364
365 pub async fn set_mute(&mut self, mute: bool) -> Result<(), Error> {
367 self.codec.set_dac_mute(mute).await?;
368 self.muted = mute;
369 Ok(())
370 }
371
372 pub fn rate(&self) -> SampleRate {
374 self.rate
375 }
376
377 pub fn codec(&mut self) -> &mut Codec {
379 &mut self.codec
380 }
381
382 pub async fn shutdown(mut self) -> Result<(), Error> {
385 self.codec.set_dac_mute(true).await?;
386 self.codec.set_mode(Mode::Off).await?;
387 Ok(()) }
389
390 fn restart(&mut self) -> Result<(), Error> {
391 let (tx, buf) = match core::mem::replace(&mut self.tx, Stream::Poisoned) {
392 Stream::Running(t) => t.stop(),
393 Stream::Stopped(tx, buf) => (tx, buf),
394 Stream::Poisoned => return Err(Error::Dma(DmaError::DescriptorError)),
395 };
396 match tx.write(buf) {
397 Ok(t) => {
398 self.tx = Stream::Running(t);
399 Ok(())
400 }
401 Err((e, tx, buf)) => {
402 self.tx = Stream::Stopped(tx, buf);
403 Err(Error::I2s(e))
404 }
405 }
406 }
407}
408
409fn as_bytes(samples: &[i16]) -> &[u8] {
410 unsafe { core::slice::from_raw_parts(samples.as_ptr().cast(), samples.len() * 2) }
413}
414
415fn as_bytes_mut(samples: &mut [i16], len: usize) -> &mut [u8] {
416 debug_assert!(len <= samples.len() * 2);
417 unsafe { core::slice::from_raw_parts_mut(samples.as_mut_ptr().cast(), len) }
420}