refactor dac into a trait, add volume support

This commit is contained in:
2026-05-08 16:09:10 -07:00
parent 7d3e58c9ad
commit 138861fc07
4 changed files with 127 additions and 81 deletions
+72
View File
@@ -0,0 +1,72 @@
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<T> {
i2c: T,
pins: CodecPins, // this dependency is unfortunate, but non trivial to generalize
}
impl<T> Ak4490Dac<T>
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<T> Dac<T> for Ak4490Dac<T>
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);
}
}