pub type Pit0 = Pit<0>;
pub type Pit1 = Pit<1>;
pub type Pit2 = Pit<2>;
pub type Pit3 = Pit<3>;
pub type Channels = (Pit0, Pit1, Pit2, Pit3);
pub struct Pit<const CHAN: u8> {
instance: &'static crate::ral::pit::RegisterBlock,
}
pub fn new<const N: u8>(pit: crate::ral::pit::Instance<N>) -> Channels {
crate::ral::modify_reg!(crate::ral::pit, pit, MCR, MDIS: MDIS_0);
crate::ral::write_reg!(crate::ral::pit::timer, &pit.TIMER[0], TCTRL, 0);
crate::ral::write_reg!(crate::ral::pit::timer, &pit.TIMER[1], TCTRL, 0);
crate::ral::write_reg!(crate::ral::pit::timer, &pit.TIMER[2], TCTRL, 0);
crate::ral::write_reg!(crate::ral::pit::timer, &pit.TIMER[3], TCTRL, 0);
unsafe {
(
Pit::new(&pit),
Pit::new(&pit),
Pit::new(&pit),
Pit::new(&pit),
)
}
}
mod private {
#[allow(dead_code)]
pub trait Sealed {}
}
pub trait Valid {}
pub enum Const<const N: u8> {}
impl private::Sealed for Const<0> {}
impl private::Sealed for Const<1> {}
impl private::Sealed for Const<2> {}
impl private::Sealed for Const<3> {}
impl Valid for Const<0> {}
impl Valid for Const<1> {}
impl Valid for Const<2> {}
impl Valid for Const<3> {}
impl<const CHAN: u8> Pit<CHAN> {
pub unsafe fn new<const N: u8>(instance: &crate::ral::pit::Instance<N>) -> Self
where
Const<CHAN>: Valid,
{
let register_block: &'_ crate::ral::pit::RegisterBlock = instance;
let register_block: &'static _ = unsafe { core::mem::transmute(register_block) };
Self {
instance: register_block,
}
}
pub fn set_interrupt_enable(&mut self, enable: bool) {
crate::ral::modify_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TCTRL,
TIE: enable as u32
)
}
pub fn is_interrupt_enabled(&self) -> bool {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TCTRL,
TIE == 1
)
}
pub fn current_timer_value(&self) -> u32 {
if self.is_enabled() {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
CVAL
)
} else {
0
}
}
pub fn set_load_timer_value(&self, ticks: u32) {
crate::ral::write_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
LDVAL,
ticks.saturating_sub(1)
);
}
pub fn load_timer_value(&self) -> u32 {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
LDVAL
)
.saturating_add(1)
}
pub fn enable(&mut self) {
crate::ral::modify_reg!(crate::ral::pit::timer, &self.instance.TIMER[CHAN as usize], TCTRL, TEN: 1);
}
pub fn disable(&mut self) {
crate::ral::modify_reg!(crate::ral::pit::timer, &self.instance.TIMER[CHAN as usize], TCTRL, TEN: 0);
}
pub fn is_enabled(&self) -> bool {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TCTRL,
TEN == 1
)
}
pub fn is_elapsed(&self) -> bool {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TFLG,
TIF == 1
)
}
pub fn clear_elapsed(&self) {
crate::ral::write_reg!(crate::ral::pit::timer, &self.instance.TIMER[CHAN as usize], TFLG, TIF: 1)
}
pub fn set_chained(&mut self, chained: bool) {
crate::ral::modify_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TCTRL,
CHN: chained as u32
);
}
pub fn is_chained(&self) -> bool {
crate::ral::read_reg!(
crate::ral::pit::timer,
&self.instance.TIMER[CHAN as usize],
TCTRL,
CHN == 1
)
}
}
unsafe impl<const CHAN: u8> Send for Pit<CHAN> {}
pub struct Chained<const L: u8, const H: u8> {
low: Pit<L>,
high: Pit<H>,
}
pub type Chained01 = Chained<0, 1>;
pub type Chained12 = Chained<1, 2>;
pub type Chained23 = Chained<2, 3>;
impl Chained<0, 1> {
pub fn new(low: Pit<0>, high: Pit<1>) -> Self {
chain(low, high)
}
pub fn lifetime_value(&self) -> u64 {
if !self.is_enabled() {
return 0;
}
let mut high = self.low.instance.LTMR64H.read();
let mut low = self.low.instance.LTMR64L.read();
let ldval0 = self.low.instance.TIMER[0].LDVAL.read();
if low == ldval0 {
high = self.low.instance.LTMR64H.read();
low = self.low.instance.LTMR64L.read();
}
(u64::from(high) << 32) + u64::from(low)
}
}
impl Chained<1, 2> {
pub fn new(low: Pit<1>, high: Pit<2>) -> Self {
chain(low, high)
}
}
impl Chained<2, 3> {
pub fn new(low: Pit<2>, high: Pit<3>) -> Self {
chain(low, high)
}
}
fn chain<const L: u8, const H: u8>(mut low: Pit<L>, mut high: Pit<H>) -> Chained<L, H> {
low.disable();
high.disable();
low.clear_elapsed();
high.clear_elapsed();
low.set_chained(false);
low.set_interrupt_enable(false);
high.set_chained(true);
Chained { low, high }
}
impl<const L: u8, const H: u8> Chained<L, H> {
pub fn release(mut self) -> (Pit<L>, Pit<H>) {
self.low.disable();
self.high.disable();
self.high.set_chained(false);
self.high.set_interrupt_enable(false);
(self.low, self.high)
}
pub fn set_interrupt_enable(&mut self, enable: bool) {
self.high.set_interrupt_enable(enable);
}
pub fn is_interrupt_enabled(&self) -> bool {
self.high.is_interrupt_enabled()
}
pub fn set_load_timer_value(&mut self, ticks: u64) {
self.low.set_load_timer_value((ticks & 0xFFFF_FFFF) as u32);
self.high.set_load_timer_value((ticks >> 32) as u32);
}
pub fn load_timer_value(&self) -> u64 {
let low = self.low.load_timer_value();
let high = self.high.load_timer_value();
(u64::from(high) << 32) + u64::from(low)
}
pub fn current_timer_value(&self) -> u64 {
if !self.is_enabled() {
return 0;
}
loop {
let tmp = self.high.current_timer_value();
let low = self.low.current_timer_value();
let high = self.high.current_timer_value();
if high == tmp {
return (u64::from(high) << 32) + u64::from(low);
}
}
}
pub fn enable(&mut self) {
self.high.enable();
self.low.enable();
}
pub fn disable(&mut self) {
self.low.disable();
self.high.disable();
}
pub fn is_enabled(&self) -> bool {
self.high.is_enabled()
}
pub fn is_elapsed(&self) -> bool {
self.high.is_elapsed()
}
pub fn clear_elapsed(&mut self) {
self.high.clear_elapsed();
self.low.clear_elapsed(); }
}
#[cfg(doctest)]
struct InvalidChannel;