use crate::ral;
type AnyPitInstance = crate::AnyInstance<ral::pit::RegisterBlock>;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[repr(usize)]
pub enum Channel {
Chan0 = 0,
Chan1 = 1,
Chan2 = 2,
Chan3 = 3,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CannotChainError(());
pub struct Pit {
pit: AnyPitInstance,
}
impl Pit {
pub fn new<const N: u8>(pit: ral::pit::Instance<N>) -> Self {
new(crate::into_any(pit))
}
fn timer(&self, channel: Channel) -> &ral::pit::timer::RegisterBlock {
&self.pit.TIMER[channel as usize]
}
pub fn set_interrupt_enable(&mut self, channel: Channel, enable: bool) {
ral::modify_reg!(ral::pit::timer, self.timer(channel), TCTRL, TIE: enable as u32);
}
pub fn is_interrupt_enabled(&self, channel: Channel) -> bool {
ral::read_reg!(ral::pit::timer, self.timer(channel), TCTRL, TIE == 1)
}
pub fn current_timer_value(&self, channel: Channel) -> u32 {
if self.is_enabled(channel) {
ral::read_reg!(ral::pit::timer, self.timer(channel), CVAL)
} else {
0
}
}
pub fn set_load_timer_value(&self, channel: Channel, ticks: u32) {
ral::write_reg!(
ral::pit::timer,
self.timer(channel),
LDVAL,
ticks.saturating_sub(1)
);
}
pub fn load_timer_value(&self, channel: Channel) -> u32 {
ral::read_reg!(ral::pit::timer, self.timer(channel), LDVAL).saturating_add(1)
}
pub fn enable(&mut self, channel: Channel) {
ral::modify_reg!(ral::pit::timer, self.timer(channel), TCTRL, TEN: 1);
}
pub fn disable(&mut self, channel: Channel) {
ral::modify_reg!(ral::pit::timer, self.timer(channel), TCTRL, TEN: 0);
}
pub fn is_enabled(&self, channel: Channel) -> bool {
ral::read_reg!(ral::pit::timer, self.timer(channel), TCTRL, TEN == 1)
}
pub fn is_elapsed(&self, channel: Channel) -> bool {
ral::read_reg!(ral::pit::timer, self.timer(channel), TFLG, TIF == 1)
}
pub fn clear_elapsed(&self, channel: Channel) {
ral::write_reg!(ral::pit::timer, self.timer(channel), TFLG, TIF: 1);
}
pub fn enable_chaining(&mut self, channel: Channel) -> Result<(), CannotChainError> {
if channel == Channel::Chan0 {
return Err(CannotChainError(()));
}
ral::modify_reg!(ral::pit::timer, self.timer(channel), TCTRL, CHN: 1);
Ok(())
}
pub fn disable_chaining(&mut self, channel: Channel) -> Result<(), CannotChainError> {
if channel == Channel::Chan0 {
return Err(CannotChainError(()));
}
ral::modify_reg!(ral::pit::timer, self.timer(channel), TCTRL, CHN: 0);
Ok(())
}
pub fn is_chained(&self, channel: Channel) -> bool {
if channel == Channel::Chan0 {
return false;
}
ral::read_reg!(ral::pit::timer, self.timer(channel), TCTRL, CHN == 1)
}
pub fn lifetime_value(&self) -> u64 {
let mut high = self.pit.LTMR64H.read();
let mut low = self.pit.LTMR64L.read();
let ldval0 = self.pit.TIMER[0].LDVAL.read();
if low == ldval0 {
high = self.pit.LTMR64H.read();
low = self.pit.LTMR64L.read();
}
(u64::from(high) << 32) + u64::from(low)
}
}
fn new(pit: AnyPitInstance) -> Pit {
ral::modify_reg!(ral::pit, pit, MCR, MDIS: MDIS_0);
ral::write_reg!(ral::pit::timer, &pit.TIMER[0], TCTRL, 0);
ral::write_reg!(ral::pit::timer, &pit.TIMER[1], TCTRL, 0);
ral::write_reg!(ral::pit::timer, &pit.TIMER[2], TCTRL, 0);
ral::write_reg!(ral::pit::timer, &pit.TIMER[3], TCTRL, 0);
Pit { pit }
}
#[cfg(doctest)]
struct PitNotSync;
#[cfg(doctest)]
struct PitSend;