#![no_std]
pub mod registers;
use core::marker::PhantomData;
use embedded_hal::blocking::i2c::{SevenBitAddress};
use embedded_hal::blocking::{delay, i2c};
use registers::*;
#[derive(Debug, Clone, PartialEq)]
pub enum Error<I2cError> {
I2c(I2cError),
}
pub struct Wm8994<I2c, I2cError, Delay> {
config: Config,
i2c: I2c,
delay: Delay,
_i2c_err: PhantomData<I2cError>,
}
pub struct Config {
pub address: SevenBitAddress,
}
impl<I2c, I2cError, Delay> Wm8994<I2c, I2cError, Delay>
where
I2c: i2c::Read<Error = I2cError> + i2c::Write<Error = I2cError> + i2c::WriteRead<Error = I2cError>,
Delay: delay::DelayMs<u32>,
{
pub fn new(config: Config, i2c: I2c, delay: Delay) -> Self {
Self {
config, i2c, delay,
_i2c_err: PhantomData,
}
}
pub fn init_headphone(&mut self) -> Result<(), Error<I2cError>> {
assert_eq!(self.get_family()?, FAMILY_ID, "Incorrect family ID");
self.write_reg(0x102, 0x0003)?;
self.write_reg(0x817, 0x0000)?;
self.write_reg(0x102, 0x0000)?;
self.write_reg(ANTIPOP2, 0x006C)?;
self.write_reg(PWR_MANAGEMENT_1, 0x0013)?;
self.delay.delay_ms(50);
self.write_reg(PWR_MANAGEMENT_5, 0x0303)?;
self.write_reg(AIF1_DAC1_LMR, 0x0001)?;
self.write_reg(AIF1_DAC1_RMR, 0x0001)?;
self.write_reg(AIF1_DAC2_LMR, 0x0000)?;
self.write_reg(AIF1_DAC2_RMR, 0x0000)?;
self.write_reg(AIF1_RATE, 0x0083)?;
self.aif1_control1_wl(0)?;
self.write_reg(AIF1_MASTER_SLAVE, 0x0000)?;
self.write_reg(CLOCKING1, 0x000A)?;
self.write_reg(AIF1_CLOCKING1, 0x0001)?;
self.write_reg(OUTPUT_MIXER_1, 0x0100)?;
self.write_reg(OUTPUT_MIXER_2, 0x0100)?;
self.write_reg(WRITE_SEQ_CTRL1, 0x8100)?;
assert_ne!(0, self.read_reg(WRITE_SEQ_CTRL2)?, "Sequencer not running");
self.delay.delay_ms(325); assert_eq!(0, self.read_reg(WRITE_SEQ_CTRL2)?, "Sequencer not finished");
self.write_reg(AIF1_DAC1_FILTER1, 0x0000)?;
self.write_reg(DAC1_LEFT_VOL, 0x00C0)?;
self.write_reg(DAC1_RIGHT_VOL, 0x00C0)?;
self.write_reg(AIF1_DAC1_FILTER1, 0x0010)?;
self.write_reg(DAC2_LEFT_VOL, 0x00C0)?;
self.write_reg(DAC2_RIGHT_VOL, 0x00C0)?;
self.write_reg(AIF1_DAC2_FILTER1, 0x0010)?;
self.set_output_volume(u8::MAX)?;
Ok(())
}
pub fn aif1_control1_wl(&mut self, value: u16) -> Result<(), Error<I2cError>> {
let mut tmp = self.read_reg(AIF1_CONTROL1)?;
tmp &= !AIF1_CONTROL1_WL_MASK;
tmp |= value << AIF1_CONTROL1_WL_POSITION;
self.write_reg(AIF1_CONTROL1, tmp)?;
Ok(())
}
pub fn set_mute(&mut self, mute_on: bool) -> Result<(), Error<I2cError>> {
match mute_on {
true => {
self.write_reg(AIF1_DAC1_FILTER1, 0x0200)?;
self.write_reg(AIF1_DAC2_FILTER1, 0x0200)?;
}
false => {
self.write_reg(AIF1_DAC1_FILTER1, 0x0010)?;
self.write_reg(AIF1_DAC2_FILTER1, 0x0010)?;
}
}
Ok(())
}
pub fn set_output_volume(&mut self, volume: u8) -> Result<(), Error<I2cError>> {
match volume {
0 => {
self.set_mute(true)?;
},
0..=0x3e => {
self.set_mute(false)?;
let tmp = volume as u16 | 0x140;
self.write_reg(LEFT_OUTPUT_VOL, tmp)?;
self.write_reg(RIGHT_OUTPUT_VOL, tmp)?;
self.write_reg(SPK_LEFT_VOL, tmp)?;
self.write_reg(SPK_RIGHT_VOL, tmp)?;
},
0x3f..=u8::MAX => {
self.set_mute(false)?;
let tmp = 0x3Fu16 | 0x140;
self.write_reg(LEFT_OUTPUT_VOL, tmp)?;
self.write_reg(RIGHT_OUTPUT_VOL, tmp)?;
self.write_reg(SPK_LEFT_VOL, tmp)?;
self.write_reg(SPK_RIGHT_VOL, tmp)?;
}
}
Ok(())
}
pub fn soft_reset(&mut self) -> Result<(), Error<I2cError>> {
self.write_reg(0x0, 0)
}
pub fn get_family(&mut self) -> Result<u16, Error<I2cError>> {
self.read_reg(0x0)
}
pub fn read_reg(&mut self, reg: u16) -> Result<u16, Error<I2cError>> {
let mut buf: [u8; 2] = [0; 2];
self.i2c.write_read(self.config.address, ®.to_be_bytes(), &mut buf).map_err(|err| Error::I2c(err))?;
Ok(u16::from_be_bytes(buf))
}
pub fn write_reg(&mut self, reg: u16, val: u16) -> Result<(), Error<I2cError>> {
let reg = reg.to_be_bytes();
let val = val.to_be_bytes();
let mut buf: [u8; 4] = [0;4];
buf[0] = reg[0];
buf[1] = reg[1];
buf[2] = val[0];
buf[3] = val[1];
self.i2c.write(self.config.address, &buf).map_err(|err| Error::I2c(err))
}
}