use core::convert::Infallible;
use fugit::NanosDurationU32;
use crate::ehal::delay::DelayNs;
use crate::ehal_02::timer::{CountDown, Periodic};
use crate::time::Nanoseconds;
use crate::timer_params::TimerParams;
use crate::timer_traits::InterruptDrivenTimer;
use super::{Count16Reg, TimerCounter};
pub trait Count16 {
fn count_16(&self) -> &Count16Reg;
}
impl<TC> InterruptDrivenTimer for TimerCounter<TC>
where
TC: Count16,
{
fn enable_interrupt(&mut self) {
self.tc.count_16().intenset().write(|w| w.ovf().set_bit());
}
fn start<T>(&mut self, timeout: T)
where
T: Into<NanosDurationU32>,
{
let params = TimerParams::new_ns(timeout.into(), self.freq);
self.start_timer(params.divider, params.check_cycles_u16());
}
fn wait(&mut self) -> nb::Result<(), Infallible> {
let count = self.tc.count_16();
if count.intflag().read().ovf().bit_is_set() {
count.intflag().modify(|_, w| w.ovf().set_bit());
Ok(())
} else {
Err(nb::Error::WouldBlock)
}
}
fn disable_interrupt(&mut self) {
self.tc.count_16().intenclr().write(|w| w.ovf().set_bit());
}
}
impl<TC> Periodic for TimerCounter<TC> {}
impl<TC> CountDown for TimerCounter<TC>
where
TC: Count16,
{
type Time = Nanoseconds;
fn start<T>(&mut self, timeout: T)
where
T: Into<Self::Time>,
{
<Self as InterruptDrivenTimer>::start(self, timeout);
}
fn wait(&mut self) -> nb::Result<(), void::Void> {
nb::block! {
<Self as InterruptDrivenTimer>::wait(self)
}
.unwrap(); Ok(())
}
}
impl<TC> DelayNs for TimerCounter<TC>
where
TC: Count16,
{
fn delay_ns(&mut self, ns: u32) {
let ticks: u32 = (ns as u64 * self.freq.to_Hz() as u64 / 1_000_000_000_u64) as u32;
let params = TimerParams::new_from_ticks(ticks);
let mut cycles = params.cycles;
if cycles > u16::MAX as u32 {
self.start_timer(params.divider, u16::MAX);
while cycles > u16::MAX as u32 {
let _ = nb::block!(InterruptDrivenTimer::wait(self));
cycles -= u16::MAX as u32;
}
}
if cycles > 0 {
self.start_timer(params.divider, cycles as u16);
let _ = nb::block!(InterruptDrivenTimer::wait(self));
}
self.disable();
}
}