use cortex_m::prelude::{_embedded_hal_blocking_i2c_Write, _embedded_hal_blocking_i2c_WriteRead}; use crate::CodecPins; use crate::hal::prelude::*; use crate::traits::Dac; const AK4490_I2C_ADDRESS: u8 = 0x10; #[repr(u8)] #[allow(dead_code)] enum RegisterAddress { Control1 = 0x00, Control2 = 0x01, Control3 = 0x02, LeftAtt = 0x03, RightAtt = 0x04, Control4 = 0x05, Control5 = 0x06, Control6 = 0x07, Control7 = 0x08, Control8 = 0x09, } pub struct Ak4490Dac { i2c: T, pins: CodecPins, // this dependency is unfortunate, but non trivial to generalize } impl Ak4490Dac where T: _embedded_hal_blocking_i2c_WriteRead + _embedded_hal_blocking_i2c_Write, { #[inline] fn write_reg(&mut self, reg: RegisterAddress, val: u8) { self.i2c.write(AK4490_I2C_ADDRESS, &[reg as u8, val]).ok(); } fn dfs_for_rate(&self, rate: u32) -> u8 { match rate { r if r < 54000 => 0, r if r < 108000 => 1, r if r < 216000 => 2, r if r <= 384000 => 4, _ => 5, } } } impl Dac for Ak4490Dac where T: _embedded_hal_blocking_i2c_WriteRead + _embedded_hal_blocking_i2c_Write, { fn new(i2c: T, pins: CodecPins) -> Self { Self { i2c, pins } } fn init(&mut self) { // bring out of reset self.pins.reset.set_high(); self.write_reg(RegisterAddress::Control1, (1 << 7) | 0x0e | (1 << 0)); // ACKS | I2S-32 | RSTN let dfs = 0; // start in 48k mode, change_rate will be called after init self.write_reg(RegisterAddress::Control2, 0x22 | ((dfs & 0x3) << 3)); self.write_reg(RegisterAddress::Control4, (dfs & 0x4) >> 1); } fn change_rate(&mut self, new_rate: u32) { let dfs = self.dfs_for_rate(new_rate); self.write_reg(RegisterAddress::Control2, 0x22 | ((dfs & 0x3) << 3)); self.write_reg(RegisterAddress::Control4, (dfs & 0x4) >> 1); } fn set_volume(&mut self, left: u8, right: u8) { self.write_reg(RegisterAddress::LeftAtt, left); self.write_reg(RegisterAddress::RightAtt, right); } }