use crate::pac;
use crate::rcu::{Enable, Rcu, Reset};
const TICKS_MAX: u8 = 0x3F;
const ALIVE_BIT: u8 = 1 << 6;
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[allow(missing_docs)]
pub enum WwdgtPsc {
Div1 = 0b00,
Div2 = 0b01,
Div4 = 0b10,
Div8 = 0b11,
}
fn checked_bits(cnt: u8, win: u8) -> (u8, u8) {
assert!(cnt <= TICKS_MAX, "WWDGT period must fit in 6 bits");
assert!(win <= TICKS_MAX, "WWDGT window must fit in 6 bits");
assert!(
win <= cnt,
"WWDGT window must not outlast the period it opens in"
);
(cnt | ALIVE_BIT, win | ALIVE_BIT)
}
pub struct Wwdgt {
wwdgt: pac::Wwdgt,
}
impl Wwdgt {
pub fn start(self, psc: WwdgtPsc, cnt: u8, win: u8) -> WwdgtRunning {
let (cnt, win) = checked_bits(cnt, win);
self.wwdgt
.cfg()
.modify(|_, w| w.psc().bits(psc as u8).win().bits(win));
self.wwdgt
.ctl()
.modify(|_, w| w.cnt().bits(cnt).wdgten().enabled());
WwdgtRunning {
wwdgt: self.wwdgt,
cnt,
}
}
}
#[must_use = "the watchdog keeps running; without this value nothing can feed it"]
pub struct WwdgtRunning {
wwdgt: pac::Wwdgt,
cnt: u8,
}
impl WwdgtRunning {
pub fn feed(&mut self) {
self.wwdgt.ctl().write(|w| w.cnt().bits(self.cnt));
}
pub fn set_period(&mut self, cnt: u8, win: u8) {
let (cnt, win) = checked_bits(cnt, win);
self.wwdgt.cfg().modify(|_, w| w.win().bits(win));
self.cnt = cnt;
}
pub fn listen(&mut self) {
self.wwdgt.cfg().modify(|_, w| w.ewie().enable());
}
pub fn is_listening(&self) -> bool {
self.wwdgt.cfg().read().ewie().bit_is_set()
}
pub fn is_pending(&self) -> bool {
self.wwdgt.stat().read().ewif().is_pending()
}
pub fn clear_interrupt(&mut self) {
self.wwdgt.stat().write(|w| w.ewif().finished());
}
}
pub trait WwdgtExt {
fn constrain(self, rcu: &mut Rcu) -> Wwdgt;
}
impl WwdgtExt for pac::Wwdgt {
fn constrain(self, rcu: &mut Rcu) -> Wwdgt {
<pac::Wwdgt as Enable>::enable(rcu);
<pac::Wwdgt as Reset>::reset(rcu);
Wwdgt { wwdgt: self }
}
}