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 CS4398_I2C_ADDRESS: u8 = 0x4f; #[repr(u8)] #[allow(dead_code)] enum RegisterAddress { ChipId = 0x01, ModeControl = 0x02, VolMixInvControl = 0x03, MuteControl = 0x04, ChAVol = 0x05, ChBVol = 0x06, RampFiltControl = 0x07, MiscControl = 0x08, MiscControl2 = 0x09, } pub struct Cs4398Dac { i2c: T, pins: CodecPins, } impl Cs4398Dac 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(CS4398_I2C_ADDRESS, &[reg as u8, val]).ok(); } fn fm_for_rate(&self, rate: u32) -> u8 { match rate { r if r <= 50000 => 0b00, r if r <= 100000 => 0b01, _ => 0b10, // DSD mode 0b11 is not used } } } impl Dac for Cs4398Dac where T: _embedded_hal_blocking_i2c_WriteRead + _embedded_hal_blocking_i2c_Write, { fn new(i2c: T, pins: CodecPins) -> Self { Cs4398Dac { i2c, pins } } fn init(&mut self) { // reset self.pins.reset.set_low().ok(); self.pins.reset.set_high().ok(); // power up, enable control port self.write_reg(RegisterAddress::MiscControl, 1 << 6); self.mute(); // set audio protocol to I2S, Single rate mode self.write_reg(RegisterAddress::ModeControl, 1 << 4); } fn change_rate(&mut self, new_rate: u32) { let mode_control = (1 << 4) | self.fm_for_rate(new_rate); self.write_reg(RegisterAddress::ModeControl, mode_control); } fn mute(&mut self) { self.write_reg(RegisterAddress::MuteControl, 0xc0 | (0b11 << 3)); } fn unmute(&mut self) { self.write_reg(RegisterAddress::MuteControl, 0xc0); } }