use embassy_stm32 as hal;
use hal::peripherals::*;
use defmt::{info, unwrap};
use embassy_time::Timer;
use crate::audio::Fs;
pub struct Codec {}
impl Codec {
pub async fn setup_wm8731(i2c: &mut hal::i2c::I2c<'_, hal::mode::Blocking>, fs: Fs) {
use wm8731::WM8731;
info!("setup wm8731 from I2C");
Timer::after_micros(10).await;
Self::write_wm8731_reg(i2c, WM8731::reset());
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::power_down(|w| {
Self::final_power_settings(w);
w.output().power_off();
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::left_line_in(|w| {
w.both().enable();
w.mute().disable();
w.volume().nearest_dB(0);
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::analog_audio_path(|w| {
w.sidetone().disable();
w.dac_select().select();
w.bypass().disable();
w.input_select().line_input();
w.mute_mic().enable();
w.mic_boost().disable();
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::digital_audio_path(|w| {
w.dac_mut().disable();
w.deemphasis().frequency_48();
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::digital_audio_interface_format(|w| {
w.bit_clock_invert().no_invert();
w.master_slave().slave();
w.left_right_dac_clock_swap().right_channel_dac_data_right();
w.left_right_phase().data_when_daclrc_low();
w.bit_length().bits_24();
w.format().left_justified();
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(
i2c,
WM8731::sampling(|w| {
w.core_clock_divider_select().normal();
w.base_oversampling_rate().normal_256();
match fs {
Fs::Fs8000 => {
w.sample_rate().adc_8();
}
Fs::Fs32000 => {
w.sample_rate().adc_32();
}
Fs::Fs44100 => {
w.sample_rate().adc_441();
}
Fs::Fs48000 => {
w.sample_rate().adc_48();
}
Fs::Fs88200 => {
w.sample_rate().adc_882();
}
Fs::Fs96000 => {
w.sample_rate().adc_96();
}
}
w.usb_normal().normal();
}),
);
Timer::after_micros(10).await;
Self::write_wm8731_reg(i2c, WM8731::active().active());
Timer::after_micros(10).await;
}
pub fn write_wm8731_reg(i2c: &mut hal::i2c::I2c<'_, hal::mode::Blocking>, r: wm8731::Register) {
const AD: u8 = 0x1a;
let byte1: u8 = ((r.address << 1) & 0b1111_1110) | (((r.value >> 8) & 0b0000_0001) as u8);
let byte2: u8 = (r.value & 0b1111_1111) as u8;
unwrap!(i2c.blocking_write(AD, &[byte1, byte2]));
}
pub fn final_power_settings(w: &mut wm8731::power_down::PowerDown) {
w.power_off().power_on();
w.clock_output().power_off();
w.oscillator().power_off();
w.output().power_on();
w.dac().power_on();
w.adc().power_on();
w.mic().power_off();
w.line_input().power_on();
}
}
#[allow(non_snake_case)]
pub struct Pins {
pub SCL: PH4, pub SDA: PB11, pub MCLK_A: PE2, pub SCK_A: PE5, pub FS_A: PE4, pub SD_A: PE6, pub SD_B: PE3, }