pub mod es7210;
pub mod es7243e;
pub mod es8156;
pub mod es8311;
pub mod es8388;
use embedded_hal::i2c::I2c;
use rusty_esp_core::error::{Error, Result};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Register {
pub addr: u8,
pub value: u8,
}
impl Register {
#[must_use]
pub const fn new(addr: u8, value: u8) -> Self {
Register { addr, value }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RegOp {
Write {
addr: u8,
value: u8,
},
Update {
addr: u8,
mask: u8,
value: u8,
},
DelayMs(u16),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Module {
Adc,
Dac,
AdcDac,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Mode {
Master,
Slave,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum I2sFormat {
Standard,
LeftJustified,
Dsp,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Bits {
B16,
B24,
B32,
}
#[derive(Debug)]
pub struct I2cRegs<I> {
i2c: I,
addr: u8,
}
impl<I: I2c> I2cRegs<I> {
pub fn new(i2c: I, addr: u8) -> Self {
I2cRegs { i2c, addr }
}
#[must_use]
pub fn addr(&self) -> u8 {
self.addr
}
pub fn release(self) -> I {
self.i2c
}
pub fn bus(&self) -> &I {
&self.i2c
}
pub fn bus_mut(&mut self) -> &mut I {
&mut self.i2c
}
pub fn write(&mut self, reg: u8, value: u8) -> Result<()> {
self.i2c
.write(self.addr, &[reg, value])
.map_err(|_| Error::Hardware)
}
pub fn read(&mut self, reg: u8) -> Result<u8> {
let mut v = [0u8; 1];
self.i2c
.write_read(self.addr, &[reg], &mut v)
.map_err(|_| Error::Hardware)?;
Ok(v[0])
}
pub fn update(&mut self, reg: u8, mask: u8, value: u8) -> Result<()> {
let old = self.read(reg)?;
self.write(reg, (old & !mask) | (value & mask))
}
pub fn apply(&mut self, table: &[RegOp], mut delay_ms: impl FnMut(u16)) -> Result<usize> {
let mut written = 0;
for op in table {
match *op {
RegOp::Write { addr, value } => {
self.write(addr, value)?;
written += 1;
}
RegOp::Update { addr, mask, value } => {
self.update(addr, mask, value)?;
written += 1;
}
RegOp::DelayMs(ms) => delay_ms(ms),
}
}
Ok(written)
}
}
pub trait CodecChip {
fn set_sample_rate(&mut self, sample_rate_hz: u32, mclk_hz: u32) -> Result<()>;
fn set_format(&mut self, fmt: I2sFormat, bits: Bits) -> Result<()>;
fn start(&mut self, module: Module) -> Result<()>;
fn stop(&mut self) -> Result<()>;
fn set_mute(&mut self, mute: bool) -> Result<()>;
}
#[cfg(test)]
pub(crate) mod fake {
use core::convert::Infallible;
use embedded_hal::i2c::{ErrorType, I2c, Operation, SevenBitAddress};
#[derive(Debug, Default)]
pub struct FakeCodec {
pub addr_seen: Option<u8>,
pub regs: std::collections::BTreeMap<u8, u8>,
pub writes: std::vec::Vec<(u8, u8)>,
last_reg: u8,
}
impl FakeCodec {
pub fn with_defaults(defaults: &[(u8, u8)]) -> Self {
let mut f = FakeCodec::default();
for &(r, v) in defaults {
f.regs.insert(r, v);
}
f
}
pub fn reg(&self, r: u8) -> u8 {
*self.regs.get(&r).unwrap_or(&0)
}
pub fn history(&self, r: u8) -> std::vec::Vec<u8> {
self.writes
.iter()
.filter(|(a, _)| *a == r)
.map(|(_, v)| *v)
.collect()
}
}
impl ErrorType for FakeCodec {
type Error = Infallible;
}
impl I2c<SevenBitAddress> for FakeCodec {
fn transaction(
&mut self,
address: SevenBitAddress,
operations: &mut [Operation<'_>],
) -> Result<(), Infallible> {
self.addr_seen = Some(address);
for op in operations {
match op {
Operation::Write(bytes) => {
self.last_reg = bytes[0];
if let Some(&v) = bytes.get(1) {
self.regs.insert(bytes[0], v);
self.writes.push((bytes[0], v));
}
}
Operation::Read(buf) => {
for (i, b) in buf.iter_mut().enumerate() {
*b = self.reg(self.last_reg.wrapping_add(i as u8));
}
}
}
}
Ok(())
}
}
}
#[cfg(test)]
mod tests {
use super::fake::FakeCodec;
use super::*;
#[test]
fn write_read_update_apply() {
let mut regs = I2cRegs::new(FakeCodec::default(), 0x18);
assert_eq!(regs.addr(), 0x18);
regs.write(0x10, 0xA5).unwrap();
assert_eq!(regs.read(0x10).unwrap(), 0xA5);
regs.update(0x10, 0x0F, 0x03).unwrap();
assert_eq!(regs.read(0x10).unwrap(), 0xA3);
let mut delays = 0;
let n = regs
.apply(
&[
RegOp::Write {
addr: 0x11,
value: 1,
},
RegOp::DelayMs(2),
RegOp::Update {
addr: 0x11,
mask: 0xF0,
value: 0x20,
},
],
|_| delays += 1,
)
.unwrap();
assert_eq!((n, delays), (2, 1));
let bus = regs.release();
assert_eq!(bus.reg(0x11), 0x21);
assert_eq!(bus.addr_seen, Some(0x18));
assert_eq!(bus.history(0x10), [0xA5, 0xA3]);
}
}