use crate::{analog::adc::Attenuation, peripherals::EFUSE};
#[cfg_attr(not(feature = "unstable"), allow(dead_code))]
mod fields;
#[instability::unstable]
pub use fields::*;
#[instability::unstable]
pub enum AdcCalibUnit {
ADC1,
}
#[instability::unstable]
pub fn flash_encryption() -> bool {
!super::read_field_le::<u8>(SPI_BOOT_CRYPT_CNT)
.count_ones()
.is_multiple_of(2)
}
#[instability::unstable]
pub fn rwdt_multiplier() -> u8 {
super::read_field_le::<u8>(WDT_DELAY_SEL)
}
#[instability::unstable]
pub fn block_version() -> (u8, u8) {
(
super::read_field_le::<u8>(BLK_VERSION_MAJOR),
super::read_field_le::<u8>(BLK_VERSION_MINOR),
)
}
fn get_signed_val(data: u32, sign_bit: u32) -> i32 {
let sign_mask = 1u32 << sign_bit;
if data & sign_mask != 0 {
-((data & !sign_mask) as i32)
} else {
data as i32
}
}
#[instability::unstable]
pub fn rtc_calib_version() -> u8 {
let (_major, minor) = block_version();
if minor >= 1 { 1 } else { 0 }
}
#[instability::unstable]
pub fn rtc_calib_init_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
let version = rtc_calib_version();
if version != 1 {
return None;
}
let init_code: u16 = super::read_field_le(match atten {
Attenuation::_0dB => ADC1_AVE_INITCODE_ATTEN0,
Attenuation::_2p5dB => ADC1_AVE_INITCODE_ATTEN1,
Attenuation::_6dB => ADC1_AVE_INITCODE_ATTEN2,
Attenuation::_11dB => ADC1_AVE_INITCODE_ATTEN3,
});
Some(init_code + 1600) }
#[instability::unstable]
pub fn rtc_calib_get_chan_compens(
_unit: AdcCalibUnit,
channel: u16,
atten: Attenuation,
) -> Option<i32> {
let chan_diff: u32 = super::read_field_le(match channel {
0 => ADC1_CH0_ATTEN0_INITCODE_DIFF,
1 => ADC1_CH1_ATTEN0_INITCODE_DIFF,
2 => ADC1_CH2_ATTEN0_INITCODE_DIFF,
3 => ADC1_CH3_ATTEN0_INITCODE_DIFF,
4 => ADC1_CH4_ATTEN0_INITCODE_DIFF,
5 => ADC1_CH5_ATTEN0_INITCODE_DIFF,
_ => return None,
});
Some(get_signed_val(chan_diff, 3) * (4 - atten as i32))
}
#[instability::unstable]
pub fn rtc_calib_cal_mv(_unit: AdcCalibUnit, atten: Attenuation) -> u16 {
match atten {
Attenuation::_0dB => 600,
Attenuation::_2p5dB => 800,
Attenuation::_6dB => 1200,
Attenuation::_11dB => 2300,
}
}
#[instability::unstable]
pub fn rtc_calib_cal_code(_unit: AdcCalibUnit, atten: Attenuation) -> Option<u16> {
let version = rtc_calib_version();
if version != 1 {
return None;
}
let cal_vol: u16 = super::read_field_le(match atten {
Attenuation::_0dB => ADC1_HI_DOUT_ATTEN0,
Attenuation::_2p5dB => ADC1_HI_DOUT_ATTEN1,
Attenuation::_6dB => ADC1_HI_DOUT_ATTEN2,
Attenuation::_11dB => ADC1_HI_DOUT_ATTEN3,
});
let chk_offset = match atten {
Attenuation::_0dB | Attenuation::_2p5dB => 2250,
Attenuation::_6dB | Attenuation::_11dB => 2300,
};
let out = chk_offset + get_signed_val(cal_vol as u32, 9);
Some(out as u16)
}
#[instability::unstable]
pub fn major_chip_version() -> u8 {
super::read_field_le(WAFER_VERSION_MAJOR)
}
#[instability::unstable]
pub fn minor_chip_version() -> u8 {
super::read_field_le(WAFER_VERSION_MINOR)
}
#[instability::unstable]
pub fn xtal_frequency_mhz() -> u32 {
let sel = super::read_field_le::<u8>(XTAL_48M_SEL);
if sel.count_ones().is_multiple_of(2) {
40
} else {
48
}
}
#[derive(Debug, Clone, Copy, strum::FromRepr)]
#[repr(u32)]
pub(crate) enum EfuseBlock {
Block0,
Block1,
Block2,
Block3,
Block4,
Block5,
Block6,
Block7,
Block8,
Block9,
Block10,
}
impl EfuseBlock {
pub(crate) fn address(self) -> *const u32 {
let efuse = EFUSE::regs();
match self {
Self::Block0 => efuse.rd_wr_dis0().as_ptr(),
Self::Block1 => efuse.rd_mac_sys0().as_ptr(),
Self::Block2 => efuse.rd_sys_part1_data(0).as_ptr(),
Self::Block3 => efuse.rd_usr_data(0).as_ptr(),
Self::Block4 => efuse.rd_key0_data(0).as_ptr(),
Self::Block5 => efuse.rd_key1_data(0).as_ptr(),
Self::Block6 => efuse.rd_key2_data(0).as_ptr(),
Self::Block7 => efuse.rd_key3_data(0).as_ptr(),
Self::Block8 => efuse.rd_key4_data(0).as_ptr(),
Self::Block9 => efuse.rd_key5_data(0).as_ptr(),
Self::Block10 => efuse.rd_sys_part2_data(0).as_ptr(),
}
}
}