use super::SleepKind;
use crate::{
peripherals::{BB, DPORT, I2S0, LPWR, NRX},
rtc_cntl::{Rtc, WakeupSource},
};
pub const RTC_CNTL_DBIAS_0V90: u8 = 0;
pub const RTC_CNTL_DBIAS_0V95: u8 = 1;
pub const RTC_CNTL_DBIAS_1V00: u8 = 2;
pub const RTC_CNTL_DBIAS_1V05: u8 = 3;
pub const RTC_CNTL_DBIAS_1V10: u8 = 4;
pub const RTC_CNTL_DBIAS_1V15: u8 = 5;
pub const RTC_CNTL_DBIAS_1V20: u8 = 6;
pub const RTC_CNTL_DBIAS_1V25: u8 = 7;
pub const RTC_CNTL_XTL_BUF_WAIT_SLP_US: u32 = 1000;
pub const RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES: u8 = 1;
pub const RTC_CNTL_CK8M_WAIT_SLP_CYCLES: u8 = 4;
pub const RTC_CNTL_WAKEUP_DELAY_CYCLES: u8 = 7;
pub const RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES: u8 = 1;
pub const RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES: u16 = 1;
pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 128;
pub const RTC_CNTL_DBG_ATTEN_DEFAULT: u8 = 3;
pub const RTC_MEM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
pub const RTC_MEM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
pub const ROM_RAM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
pub const ROM_RAM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
pub const WIFI_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
pub const WIFI_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
pub const RTC_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
pub const RTC_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
pub const DG_WRAP_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
pub const DG_WRAP_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
bitfield::bitfield! {
#[derive(Clone, Copy)]
pub struct RtcSleepConfig(u32);
impl Debug;
pub lslp_mem_inf_fpu, set_lslp_mem_inf_fpu: 0;
pub rtc_mem_inf_fpu, set_rtc_mem_inf_fpu: 1;
pub rtc_mem_inf_follow_cpu, set_rtc_mem_inf_follow_cpu: 2;
pub rtc_fastmem_pd_en, set_rtc_fastmem_pd_en: 3;
pub rtc_slowmem_pd_en, set_rtc_slowmem_pd_en: 4;
pub rtc_peri_pd_en, set_rtc_peri_pd_en: 5;
pub wifi_pd_en, set_wifi_pd_en: 6;
pub int_8m_pd_en, set_int_8m_pd_en: 7;
pub rom_mem_pd_en, set_rom_mem_pd_en: 8;
pub deep_slp, set_deep_slp: 9;
pub wdt_flashboot_mod_en, set_wdt_flashboot_mod_en: 10;
pub u8, dig_dbias_wak, set_dig_dbias_wak: 13, 11;
pub u8, dig_dbias_slp, set_dig_dbias_slp: 16, 14;
pub u8, rtc_dbias_wak, set_rtc_dbias_wak: 19, 17;
pub u8, rtc_dbias_slp, set_rtc_dbias_slp: 22, 20;
pub lslp_meminf_pd, set_lslp_meminf_pd: 23;
pub vddsdio_pd_en, set_vddsdio_pd_en: 24;
pub xtal_fpu, set_xtal_fpu: 25;
pub deep_slp_reject, set_deep_slp_reject: 26;
pub light_slp_reject, set_light_slp_reject: 27;
}
impl Default for RtcSleepConfig {
fn default() -> Self {
let mut cfg = Self(Default::default());
cfg.set_lslp_meminf_pd(true);
cfg.set_deep_slp_reject(true);
cfg.set_light_slp_reject(true);
cfg.set_dig_dbias_wak(RTC_CNTL_DBIAS_1V10);
cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_1V10);
cfg.set_rtc_dbias_wak(RTC_CNTL_DBIAS_1V10);
cfg.set_rtc_dbias_slp(RTC_CNTL_DBIAS_1V10);
cfg
}
}
impl RtcSleepConfig {
pub fn deep() -> Self {
let mut cfg = Self::default();
cfg.set_deep_slp(true);
cfg.set_dig_dbias_slp(RTC_CNTL_DBIAS_0V90);
cfg.set_vddsdio_pd_en(true);
cfg.set_int_8m_pd_en(true);
cfg.set_xtal_fpu(false);
cfg.set_wifi_pd_en(true);
cfg.set_rom_mem_pd_en(true);
cfg.set_rtc_peri_pd_en(true);
cfg.set_rtc_fastmem_pd_en(true);
cfg.set_rtc_slowmem_pd_en(true);
cfg
}
pub(crate) fn is_deep_sleep(&self) -> bool {
self.deep_slp()
}
pub(crate) fn set_sleep_kind(&mut self, kind: SleepKind) {
self.set_deep_slp(kind == SleepKind::Deep);
}
pub(crate) fn base_settings(_rtc: &Rtc<'_>) {
let rtc_cntl = LPWR::regs();
rtc_cntl.options0().modify(|_, w| {
w.bias_core_force_pu()
.clear_bit()
.bias_core_folw_8m()
.set_bit()
.bias_i2c_force_pu()
.clear_bit()
.bias_i2c_folw_8m()
.set_bit()
.bias_force_nosleep()
.clear_bit()
.bias_sleep_folw_8m()
.set_bit()
.xtl_force_pu()
.clear_bit()
});
rtc_cntl.reg().modify(|_, w| {
w.force_pu()
.clear_bit()
.dboost_force_pu()
.clear_bit()
.dboost_force_pd()
.set_bit()
});
rtc_cntl.pwc().modify(|_, w| {
w.slowmem_force_pu()
.clear_bit()
.fastmem_force_pu()
.clear_bit()
.force_noiso()
.clear_bit()
.slowmem_force_noiso()
.clear_bit()
.fastmem_force_noiso()
.clear_bit()
});
rtc_cntl.dig_pwc().modify(|_, w| {
w.dg_wrap_force_pu()
.clear_bit()
.wifi_force_pu()
.clear_bit()
.wifi_force_pd()
.set_bit()
.inter_ram4_force_pu()
.clear_bit()
.inter_ram3_force_pu()
.clear_bit()
.inter_ram2_force_pu()
.clear_bit()
.inter_ram1_force_pu()
.clear_bit()
.inter_ram0_force_pu()
.clear_bit()
.rom0_force_pu()
.clear_bit()
.lslp_mem_force_pu()
.clear_bit()
});
rtc_cntl.dig_iso().modify(|_, w| {
w.dg_wrap_force_noiso()
.clear_bit()
.wifi_force_noiso()
.clear_bit()
.wifi_force_iso()
.set_bit()
.inter_ram4_force_noiso()
.clear_bit()
.inter_ram3_force_noiso()
.clear_bit()
.inter_ram2_force_noiso()
.clear_bit()
.inter_ram1_force_noiso()
.clear_bit()
.inter_ram0_force_noiso()
.clear_bit()
.rom0_force_noiso()
.clear_bit()
.dg_pad_force_unhold()
.clear_bit()
.dg_pad_force_noiso()
.clear_bit()
});
rtc_cntl.int_ena().modify(|_, w| w.brown_out().set_bit());
}
pub(crate) fn apply(&self) {
unsafe {
let rtc_cntl = LPWR::regs();
rtc_cntl.timer5().modify(|_, w| {
w.min_slp_val()
.bits(RTC_CNTL_MIN_SLP_VAL_MIN)
.rtcmem_powerup_timer()
.bits(RTC_MEM_POWERUP_CYCLES)
.rtcmem_wait_timer()
.bits(RTC_MEM_WAIT_CYCLES)
});
rtc_cntl.timer3().modify(|_, w| {
w
.rom_ram_powerup_timer()
.bits(ROM_RAM_POWERUP_CYCLES)
.rom_ram_wait_timer()
.bits(ROM_RAM_WAIT_CYCLES)
.wifi_powerup_timer()
.bits(WIFI_POWERUP_CYCLES)
.wifi_wait_timer()
.bits(WIFI_WAIT_CYCLES)
});
rtc_cntl.timer4().modify(|_, w| {
w
.powerup_timer()
.bits(RTC_POWERUP_CYCLES)
.wait_timer()
.bits(RTC_WAIT_CYCLES)
.dg_wrap_powerup_timer()
.bits(DG_WRAP_POWERUP_CYCLES)
.dg_wrap_wait_timer()
.bits(DG_WRAP_WAIT_CYCLES)
});
rtc_cntl
.dig_pwc()
.modify(|_, w| w.lslp_mem_force_pu().bit(self.lslp_mem_inf_fpu()));
if self.lslp_meminf_pd() {
rtc_cntl
.dig_pwc()
.modify(|_, w| w.lslp_mem_force_pu().clear_bit());
rtc_cntl.pwc().modify(|_, w| {
w.slowmem_force_pu()
.clear_bit()
.fastmem_force_pu()
.clear_bit()
});
DPORT::regs()
.mem_pd_mask()
.modify(|_, w| w.lslp_mem_pd_mask().clear_bit());
I2S0::regs()
.pd_conf()
.modify(|_, w| w.plc_mem_force_pu().clear_bit().fifo_force_pu().clear_bit());
BB::regs()
.bbpd_ctrl()
.modify(|_, w| w.fft_force_pu().clear_bit().dc_est_force_pu().clear_bit());
NRX::regs().nrxpd_ctrl().modify(|_, w| {
w.rx_rot_force_pu()
.clear_bit()
.vit_force_pu()
.clear_bit()
.demap_force_pu()
.clear_bit()
});
}
rtc_cntl.pwc().modify(|_, w| {
w.slowmem_folw_cpu().bit(self.rtc_mem_inf_follow_cpu());
w.fastmem_folw_cpu().bit(self.rtc_mem_inf_follow_cpu());
w.fastmem_force_pu().bit(!self.rtc_fastmem_pd_en());
w.fastmem_force_lpu().bit(!self.rtc_fastmem_pd_en());
w.fastmem_force_noiso().bit(!self.rtc_fastmem_pd_en());
w.slowmem_pd_en().bit(self.rtc_slowmem_pd_en());
w.slowmem_force_pu().bit(!self.rtc_slowmem_pd_en());
w.slowmem_force_noiso().bit(!self.rtc_slowmem_pd_en());
w.slowmem_force_lpu().bit(!self.rtc_slowmem_pd_en());
w.pd_en().bit(self.rtc_peri_pd_en())
});
if self.deep_slp() {
rtc_cntl.dig_iso().modify(|_, w| {
w.dg_wrap_force_noiso()
.clear_bit()
.wifi_force_noiso()
.clear_bit()
.dg_pad_force_iso()
.clear_bit()
.dg_pad_force_noiso()
.clear_bit()
});
rtc_cntl.dig_pwc().modify(|_, w| {
w.dg_wrap_pd_en()
.set_bit()
.dg_wrap_force_pu()
.clear_bit()
.dg_wrap_force_pd()
.clear_bit()
});
rtc_cntl.options0().modify(|_, w| {
w.bias_force_nosleep()
.clear_bit()
.bb_i2c_force_pu()
.clear_bit()
});
rtc_cntl.ana_conf().modify(|_, w| {
w.ckgen_i2c_pu()
.clear_bit()
.pll_i2c_pu()
.clear_bit()
.rfrx_pbus_pu()
.clear_bit()
.txrf_i2c_pu()
.clear_bit()
});
} else {
rtc_cntl
.dig_pwc()
.modify(|_, w| w.dg_wrap_pd_en().clear_bit());
rtc_cntl.bias_conf().modify(|_, w| w.dbg_atten().bits(0));
}
rtc_cntl
.options0()
.modify(|_, w| w.xtl_force_pu().bit(self.xtal_fpu()));
rtc_cntl
.clk_conf()
.modify(|_, w| w.ck8m_force_pu().bit(!self.int_8m_pd_en()));
rtc_cntl.sdio_conf().modify(|_, w| {
w.sdio_force()
.clear_bit()
.sdio_pd_en()
.bit(self.vddsdio_pd_en())
});
rtc_cntl.reg().modify(|_, w| {
w.dbias_slp()
.bits(self.rtc_dbias_slp())
.dbias_wak()
.bits(self.rtc_dbias_wak())
.dig_dbias_slp()
.bits(self.dig_dbias_slp())
.dig_dbias_wak()
.bits(self.dig_dbias_wak())
});
rtc_cntl.slp_reject_conf().modify(|_, w| {
w.deep_slp_reject_en()
.bit(self.deep_slp_reject())
.light_slp_reject_en()
.bit(self.light_slp_reject())
});
}
}
pub(crate) fn start_sleep(&self, wakeup_mask: u32, reject_mask: u32) {
LPWR::regs()
.reset_state()
.modify(|_, w| w.procpu_stat_vector_sel().set_bit());
LPWR::regs()
.wakeup_state()
.modify(|_, w| unsafe { w.wakeup_ena().bits(wakeup_mask as u16) });
let rejects = enumset::EnumSet::<WakeupSource>::from_u32_truncated(reject_mask);
LPWR::regs().slp_reject_conf().modify(|_, w| {
w.gpio_reject_en().bit(rejects.contains(WakeupSource::Gpio));
w.sdio_reject_en().bit(rejects.contains(WakeupSource::Sdio))
});
LPWR::regs().state0().modify(|_, w| w.sleep_en().set_bit());
}
pub(crate) fn finish_sleep(&self) {
LPWR::regs().int_clr().write(|w| {
w.slp_reject()
.clear_bit_by_one()
.slp_wakeup()
.clear_bit_by_one()
});
LPWR::regs()
.bias_conf()
.modify(|_, w| unsafe { w.dbg_atten().bits(RTC_CNTL_DBG_ATTEN_DEFAULT) });
}
}