1use embedded_hal_async::delay::DelayNs;
17use embedded_hal_async::i2c::I2c;
18
19pub const ADDRESS_CE_LOW: u8 = 0x18;
21pub const ADDRESS_CE_HIGH: u8 = 0x19;
23pub const CHIP_ID: [u8; 2] = [0x83, 0x11];
25
26#[derive(Clone, Copy, Debug, PartialEq, Eq)]
30#[cfg_attr(feature = "defmt", derive(defmt::Format))]
31#[allow(missing_docs)]
32pub enum SampleRate {
33 Hz22050,
34 Hz32000,
35 Hz44100,
36 Hz48000,
37 Hz64000,
38 Hz88200,
39 Hz96000,
40}
41
42impl SampleRate {
43 pub const fn hz(self) -> u32 {
45 match self {
46 SampleRate::Hz22050 => 22_050,
47 SampleRate::Hz32000 => 32_000,
48 SampleRate::Hz44100 => 44_100,
49 SampleRate::Hz48000 => 48_000,
50 SampleRate::Hz64000 => 64_000,
51 SampleRate::Hz88200 => 88_200,
52 SampleRate::Hz96000 => 96_000,
53 }
54 }
55}
56
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
59#[cfg_attr(feature = "defmt", derive(defmt::Format))]
60pub enum Mode {
61 Off,
63 Playback,
65 Record,
68 Duplex,
71}
72
73impl Mode {
74 const fn plays(self) -> bool {
75 matches!(self, Mode::Playback | Mode::Duplex)
76 }
77 const fn records(self) -> bool {
78 matches!(self, Mode::Record | Mode::Duplex)
79 }
80}
81
82#[derive(Clone, Copy, Debug, PartialEq, Eq)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub struct MicGain(u8);
87
88impl MicGain {
89 pub const DB0: Self = Self(0);
91 pub const DB30: Self = Self(10);
93
94 pub const fn from_db(db: u8) -> Self {
96 let step = db / 3;
97 Self(if step > 10 { 10 } else { step })
98 }
99
100 pub const fn db(self) -> u8 {
102 self.0 * 3
103 }
104}
105
106#[derive(Clone, Copy, Debug, PartialEq, Eq)]
108#[cfg_attr(feature = "defmt", derive(defmt::Format))]
109pub struct Volume(pub u8);
110
111impl Volume {
112 pub const MIN: Self = Self(0x00);
114 pub const UNITY: Self = Self(0xBF);
116
117 pub const fn from_half_db(half_db: i16) -> Self {
119 let raw = 0xBF + half_db;
120 Self(if raw < 0 {
121 0
122 } else if raw > 0xFF {
123 0xFF
124 } else {
125 raw as u8
126 })
127 }
128}
129
130mod reg {
131 pub const RESET: u8 = 0x00;
132 pub const CLK_MANAGER_01: u8 = 0x01;
133 pub const CLK_MANAGER_02: u8 = 0x02;
134 pub const CLK_MANAGER_03: u8 = 0x03;
135 pub const CLK_MANAGER_04: u8 = 0x04;
136 pub const CLK_MANAGER_05: u8 = 0x05;
137 pub const CLK_MANAGER_07: u8 = 0x07;
138 pub const CLK_MANAGER_08: u8 = 0x08;
139 pub const SDP_IN: u8 = 0x09;
140 pub const SDP_OUT: u8 = 0x0A;
141 pub const SYSTEM_0D: u8 = 0x0D;
142 pub const SYSTEM_0E: u8 = 0x0E;
143 pub const SYSTEM_12: u8 = 0x12;
144 pub const SYSTEM_13: u8 = 0x13;
145 pub const SYSTEM_14: u8 = 0x14;
146 pub const ADC_17: u8 = 0x17;
147 pub const ADC_1C: u8 = 0x1C;
148 pub const DAC_31: u8 = 0x31;
149 pub const DAC_32: u8 = 0x32;
150 pub const DAC_37: u8 = 0x37;
151 pub const CHD1: u8 = 0xFD;
152 pub const CHD2: u8 = 0xFE;
153}
154
155mod val {
156 pub const RESET_ALL: u8 = 0x1F;
158 pub const CSM_ON_SLAVE: u8 = 0x80;
160 pub const CLK_FROM_BCLK: u8 = 0x80;
163 pub const CLK_COMMON: u8 = 0x30;
164 pub const CLK_DAC: u8 = 0x05;
165 pub const CLK_ADC: u8 = 0x0A;
166 pub const PRE_DIV1_MUL8: u8 = 0x18;
168 pub const OSR: u8 = 0x10;
170 pub const I2S_16BIT: u8 = 0x0C;
172 pub const ANALOG_ON: u8 = 0x01;
174 pub const ANALOG_OFF: u8 = 0xFC;
175 pub const ADC_ON: u8 = 0x02;
177 pub const ADC_OFF: u8 = 0x6A;
178 pub const DAC_ON: u8 = 0x00;
180 pub const DAC_OFF: u8 = 0x02;
181 pub const HP_DRIVE: u8 = 0x10;
186 pub const OUTPUT_RESET: u8 = 0x40;
187 pub const MIC1_SELECT: u8 = 0x10;
189 pub const ADC_EQ_BYPASS_DC_CANCEL: u8 = 0x6A;
191 pub const DAC_MUTE: u8 = 0x60;
193 pub const DAC_EQ_BYPASS: u8 = 0x08;
195}
196
197pub struct Es8311<I2C> {
199 i2c: I2C,
200 addr: u8,
201 mode: Mode,
202 mic_gain: MicGain,
203}
204
205impl<I2C: I2c> Es8311<I2C> {
206 pub const fn new(i2c: I2C, addr: u8) -> Self {
208 Self {
209 i2c,
210 addr,
211 mode: Mode::Off,
212 mic_gain: MicGain::DB0,
213 }
214 }
215
216 pub async fn chip_id(&mut self) -> Result<[u8; 2], I2C::Error> {
219 Ok([self.read(reg::CHD1).await?, self.read(reg::CHD2).await?])
220 }
221
222 pub async fn init(&mut self, delay: &mut impl DelayNs) -> Result<(), I2C::Error> {
225 self.write(reg::RESET, val::RESET_ALL).await?;
226 delay.delay_ms(20).await;
227 self.write(reg::RESET, 0x00).await?;
228 self.write(reg::DAC_31, val::DAC_MUTE).await?;
230 self.write(reg::DAC_32, Volume::MIN.0).await?;
231 self.write(reg::RESET, val::CSM_ON_SLAVE).await?;
232
233 self.write(reg::CLK_MANAGER_01, val::CLK_FROM_BCLK).await?;
234 self.write(reg::CLK_MANAGER_02, val::PRE_DIV1_MUL8).await?;
235 self.write(reg::CLK_MANAGER_03, val::OSR).await?;
236 self.write(reg::CLK_MANAGER_04, val::OSR).await?;
237 self.write(reg::CLK_MANAGER_05, 0x00).await?;
238 self.write(reg::CLK_MANAGER_07, 0x00).await?;
239 self.write(reg::CLK_MANAGER_08, 0xFF).await?;
240 self.write(reg::SDP_IN, val::I2S_16BIT).await?;
241 self.write(reg::SDP_OUT, val::I2S_16BIT).await?;
242 self.write(reg::ADC_1C, val::ADC_EQ_BYPASS_DC_CANCEL)
243 .await?;
244 self.write(reg::DAC_37, val::DAC_EQ_BYPASS).await?;
245
246 self.mode = Mode::Duplex; self.set_mode(Mode::Off).await
248 }
249
250 pub const fn mode(&self) -> Mode {
252 self.mode
253 }
254
255 pub async fn set_mode(&mut self, mode: Mode) -> Result<(), I2C::Error> {
266 if mode == self.mode {
267 return Ok(());
268 }
269 if !mode.plays() {
270 self.write(reg::SYSTEM_13, val::OUTPUT_RESET).await?;
271 self.write(reg::SYSTEM_12, val::DAC_OFF).await?;
272 }
273 if !mode.records() {
274 self.write(reg::SYSTEM_0E, val::ADC_OFF).await?;
275 }
276
277 let mut clocks = val::CLK_FROM_BCLK;
278 if mode != Mode::Off {
279 clocks |= val::CLK_COMMON;
280 }
281 if mode.plays() {
282 clocks |= val::CLK_DAC;
283 }
284 if mode.records() {
285 clocks |= val::CLK_ADC;
286 }
287 self.write(reg::CLK_MANAGER_01, clocks).await?;
288
289 if mode == Mode::Off {
290 self.write(reg::SYSTEM_0D, val::ANALOG_OFF).await?;
291 } else {
292 self.write(reg::SYSTEM_0D, val::ANALOG_ON).await?;
293 }
294 if mode.records() {
295 self.write(reg::SYSTEM_14, val::MIC1_SELECT | self.mic_gain.0)
296 .await?;
297 self.write(reg::ADC_17, Volume::UNITY.0).await?;
298 self.write(reg::SYSTEM_0E, val::ADC_ON).await?;
299 }
300 if mode.plays() {
301 self.write(reg::SYSTEM_12, val::DAC_ON).await?;
302 self.write(reg::SYSTEM_13, val::HP_DRIVE).await?;
303 }
304 self.mode = mode;
305 Ok(())
306 }
307
308 pub async fn set_mic_gain(&mut self, gain: MicGain) -> Result<(), I2C::Error> {
310 self.mic_gain = gain;
311 if self.mode.records() {
312 self.write(reg::SYSTEM_14, val::MIC1_SELECT | gain.0)
313 .await?;
314 }
315 Ok(())
316 }
317
318 pub async fn set_adc_volume(&mut self, volume: Volume) -> Result<(), I2C::Error> {
320 self.write(reg::ADC_17, volume.0).await
321 }
322
323 pub async fn set_dac_volume(&mut self, volume: Volume) -> Result<(), I2C::Error> {
325 self.write(reg::DAC_32, volume.0).await
326 }
327
328 pub async fn set_dac_mute(&mut self, mute: bool) -> Result<(), I2C::Error> {
330 self.write(reg::DAC_31, if mute { val::DAC_MUTE } else { 0x00 })
331 .await
332 }
333
334 pub fn release(self) -> I2C {
336 self.i2c
337 }
338
339 async fn write(&mut self, reg: u8, value: u8) -> Result<(), I2C::Error> {
340 self.i2c.write(self.addr, &[reg, value]).await
341 }
342
343 async fn read(&mut self, reg: u8) -> Result<u8, I2C::Error> {
344 let mut b = [0];
345 self.i2c.write_read(self.addr, &[reg], &mut b).await?;
346 Ok(b[0])
347 }
348}
349
350#[cfg(test)]
351mod tests {
352 extern crate std;
353 use super::*;
354 use crate::test_util::block_on;
355 use core::convert::Infallible;
356 use embedded_hal_async::i2c::Operation;
357 use std::vec::Vec;
358
359 #[derive(Default)]
361 struct Log(Vec<(u8, u8)>);
362
363 impl Log {
364 fn last(&self, reg: u8) -> Option<u8> {
365 self.0
366 .iter()
367 .rev()
368 .find(|(r, _)| *r == reg)
369 .map(|(_, v)| *v)
370 }
371 fn position(&self, reg: u8, value: u8) -> usize {
372 self.0.iter().position(|w| *w == (reg, value)).unwrap()
373 }
374 }
375
376 impl embedded_hal_async::i2c::ErrorType for Log {
377 type Error = Infallible;
378 }
379
380 impl I2c for Log {
381 async fn transaction(
382 &mut self,
383 addr: u8,
384 ops: &mut [Operation<'_>],
385 ) -> Result<(), Infallible> {
386 assert_eq!(addr, ADDRESS_CE_LOW);
387 for op in ops {
388 if let Operation::Write([r, v]) = op {
389 self.0.push((*r, *v));
390 }
391 }
392 Ok(())
393 }
394 }
395
396 struct NoDelay;
397 impl DelayNs for NoDelay {
398 async fn delay_ns(&mut self, _: u32) {}
399 }
400
401 fn init() -> Es8311<Log> {
402 let mut c = Es8311::new(Log::default(), ADDRESS_CE_LOW);
403 block_on(c.init(&mut NoDelay)).unwrap();
404 c
405 }
406
407 #[test]
408 fn init_ends_silent_and_powered_down() {
409 let log = init().release();
410 assert_eq!(log.last(reg::DAC_31), Some(val::DAC_MUTE));
411 assert_eq!(log.last(reg::DAC_32), Some(0x00));
412 assert_eq!(log.last(reg::SYSTEM_12), Some(val::DAC_OFF));
413 assert_eq!(log.last(reg::SYSTEM_13), Some(val::OUTPUT_RESET));
414 assert_eq!(log.last(reg::SYSTEM_0D), Some(val::ANALOG_OFF));
415 assert!(log.position(reg::DAC_32, 0x00) < log.position(reg::RESET, val::CSM_ON_SLAVE));
417 }
418
419 #[test]
420 fn record_never_touches_the_output_path() {
421 let mut c = init();
422 let before = c.i2c.0.len();
423 block_on(c.set_mode(Mode::Record)).unwrap();
424 let log = c.release();
425 let writes = &log.0[before..];
426 assert!(!writes.contains(&(reg::SYSTEM_12, val::DAC_ON)));
427 assert!(!writes.contains(&(reg::SYSTEM_13, val::HP_DRIVE)));
428 assert_eq!(log.last(reg::SYSTEM_0E), Some(val::ADC_ON));
429 }
430
431 #[test]
432 fn clock_bits_match_m5unified_per_mode() {
433 for (mode, clocks) in [
434 (Mode::Playback, 0xB5),
435 (Mode::Record, 0xBA),
436 (Mode::Duplex, 0xBF),
437 ] {
438 let mut c = init();
439 block_on(c.set_mode(mode)).unwrap();
440 assert_eq!(
441 c.release().last(reg::CLK_MANAGER_01),
442 Some(clocks),
443 "{mode:?}"
444 );
445 }
446 }
447
448 #[test]
449 fn gains_and_volumes() {
450 assert_eq!(MicGain::from_db(31), MicGain::DB30);
451 assert_eq!(MicGain::from_db(7).db(), 6);
452 assert_eq!(Volume::from_half_db(0), Volume::UNITY);
453 assert_eq!(Volume::from_half_db(-1000), Volume::MIN);
454 assert_eq!(Volume::from_half_db(-12).0, 0xB3); }
456}