use core::fmt;
use super::ral::lp::{Core, Srtc as Instance};
const MR_SHIFT: u8 = 17;
const LR_SHIFT: u8 = 15;
pub struct Disabled {
reg: Instance,
}
impl Disabled {
pub(super) fn new(reg: Instance) -> Self {
Self { reg }
}
pub fn enable_and_set(mut self, core: &mut Core, time: u32, ticks: u16) -> Srtc {
disable(core);
set(&mut self.reg, time, ticks);
self.enable(core)
}
pub fn enable(self, core: &mut Core) -> Srtc {
enable(core);
Srtc { reg: self.reg }
}
pub fn try_enable(mut self, core: &mut Core, seconds: u32, ticks: u16) -> EnabledState {
if is_enabled(core) {
let (seconds, ticks) = get(&self.reg);
EnabledState::AlreadyCounting {
srtc: Srtc { reg: self.reg },
seconds,
ticks,
}
} else {
set(&mut self.reg, seconds, ticks);
enable(core);
EnabledState::SetTime(Srtc { reg: self.reg })
}
}
}
#[derive(Debug)]
pub enum EnabledState {
AlreadyCounting {
srtc: Srtc,
seconds: u32,
ticks: u16,
},
SetTime(Srtc),
}
#[inline(always)]
fn is_enabled(snvs: &Core) -> bool {
crate::ral::read_reg!(super::ral::lp::core, snvs, LPCR, SRTC_ENV) != 0
}
const QUARTER_NANOS_PER_TICK: u32 = 122_071;
pub fn micros_to_ticks(micros: u32) -> u16 {
let quarter_nanos = micros * 4000;
(quarter_nanos / QUARTER_NANOS_PER_TICK) as u16
}
fn ticks_to_micros(ticks: u16) -> u32 {
ticks as u32 * QUARTER_NANOS_PER_TICK / 4000
}
fn disable(snvs: &mut Core) {
crate::ral::modify_reg!(super::ral::lp::core, snvs, LPCR, SRTC_ENV: SRTC_ENV_0); while is_enabled(snvs) {
core::hint::spin_loop()
} }
fn set(snvs: &mut Instance, time: u32, ticks: u16) {
let low_time = (time << LR_SHIFT) | (ticks as u32);
crate::ral::modify_reg!(super::ral::lp::srtc, snvs, LPSRTCMR, SRTC: time >> MR_SHIFT);
crate::ral::write_reg!(super::ral::lp::srtc, snvs, LPSRTCLR, low_time);
}
fn enable(snvs: &mut Core) {
crate::ral::modify_reg!(super::ral::lp::core, snvs, LPCR, SRTC_ENV: SRTC_ENV_1); while !is_enabled(snvs) {
core::hint::spin_loop()
} }
fn get(snvs: &Instance) -> (u32, u16) {
let mut msb = 0;
let mut lsb = 0;
for _ in 0..6 {
let msb2 = crate::ral::read_reg!(super::ral::lp::srtc, snvs, LPSRTCMR, SRTC);
let lsb2 = crate::ral::read_reg!(super::ral::lp::srtc, snvs, LPSRTCLR);
if msb == msb2 && lsb == lsb2 {
break;
}
msb = msb2;
lsb = lsb2;
}
let seconds = (msb << MR_SHIFT) | (lsb >> LR_SHIFT);
let ticks = (lsb & 0x7FFF) as u16;
(seconds, ticks)
}
pub struct Srtc {
reg: Instance,
}
impl Srtc {
pub fn get(&self) -> u32 {
self.get_with_ticks().0
}
pub fn get_with_ticks(&self) -> (u32, u16) {
get(&self.reg)
}
pub fn get_with_micros(&self) -> (u32, u32) {
let (seconds, ticks) = self.get_with_ticks();
(seconds, ticks_to_micros(ticks))
}
pub fn set(&mut self, core: &mut Core, time: u32, ticks: u16) {
disable(core);
set(&mut self.reg, time, ticks);
enable(core);
}
}
impl fmt::Debug for Srtc {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SRTC").finish()
}
}