use super::{Event, FTimer, Instance, OnePulseMode, Timer};
use core::ops::{Deref, DerefMut};
use cortex_m::peripheral::SYST;
use fugit::{MicrosDurationU32, TimerDurationU32};
pub struct SysDelay(Timer<SYST>);
impl Deref for SysDelay {
type Target = Timer<SYST>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for SysDelay {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl SysDelay {
pub fn release(self) -> Timer<SYST> {
self.0
}
}
impl Timer<SYST> {
pub fn delay(self) -> SysDelay {
SysDelay(self)
}
}
impl SysDelay {
pub fn delay(&mut self, us: MicrosDurationU32) {
const MAX_RVR: u32 = 0x00FF_FFFF;
let mut total_rvr = us.ticks() * (self.clk.raw() / 1_000_000);
while total_rvr != 0 {
let current_rvr = total_rvr.min(MAX_RVR);
self.tim.set_reload(current_rvr);
self.tim.clear_current();
self.tim.enable_counter();
total_rvr -= current_rvr;
while !self.tim.has_wrapped() {}
self.tim.disable_counter();
}
}
}
pub struct Delay<TIM, const FREQ: u32>(pub(super) FTimer<TIM, FREQ>);
impl<T, const FREQ: u32> Deref for Delay<T, FREQ> {
type Target = FTimer<T, FREQ>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, const FREQ: u32> DerefMut for Delay<T, FREQ> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub type DelayUs<TIM> = Delay<TIM, 1_000_000>;
pub type DelayMs<TIM> = Delay<TIM, 1_000>;
impl<TIM: Instance, const FREQ: u32> Delay<TIM, FREQ> {
pub fn delay(&mut self, time: TimerDurationU32<FREQ>) {
let mut ticks = time.ticks().max(1) - 1;
while ticks != 0 {
let reload = ticks.min(TIM::max_auto_reload());
unsafe {
self.tim.set_auto_reload_unchecked(reload);
}
self.tim.trigger_update();
self.tim.enable_counter();
ticks -= reload;
while self.tim.get_interrupt_flag() != Event::Update { }
self.tim.disable_counter();
}
}
pub fn max_delay(&self) -> TimerDurationU32<FREQ> {
TimerDurationU32::from_ticks(TIM::max_auto_reload())
}
pub fn release(mut self) -> FTimer<TIM, FREQ> {
self.tim.cr1_reset();
self.0
}
}
pub struct OpmDelay<TIM, const FREQ: u32>(pub(super) FTimer<TIM, FREQ>);
impl<T, const FREQ: u32> Deref for OpmDelay<T, FREQ> {
type Target = FTimer<T, FREQ>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T, const FREQ: u32> DerefMut for OpmDelay<T, FREQ> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub type OpmDelayUs<TIM> = OpmDelay<TIM, 1_000_000>;
pub type OpmDelayMs<TIM> = OpmDelay<TIM, 1_000>;
impl<TIM: Instance + OnePulseMode, const FREQ: u32> OpmDelay<TIM, FREQ> {
fn delay(&mut self, time: TimerDurationU32<FREQ>) {
let mut ticks = time.ticks().max(1) - 1;
while ticks != 0 {
let reload = ticks.min(TIM::max_auto_reload());
unsafe {
self.tim.set_auto_reload_unchecked(reload);
}
self.tim.trigger_update();
self.tim.start_one_pulse();
ticks -= reload;
while self.tim.is_counter_enabled() { }
}
}
pub fn max_delay(&self) -> TimerDurationU32<FREQ> {
TimerDurationU32::from_ticks(TIM::max_auto_reload())
}
pub fn release(mut self) -> FTimer<TIM, FREQ> {
self.tim.cr1_reset();
self.0
}
}
impl<TIM: Instance, const FREQ: u32> fugit_timer::Delay<FREQ> for Delay<TIM, FREQ> {
type Error = core::convert::Infallible;
fn delay(&mut self, duration: TimerDurationU32<FREQ>) -> Result<(), Self::Error> {
self.delay(duration);
Ok(())
}
}
impl<TIM: Instance + OnePulseMode, const FREQ: u32> fugit_timer::Delay<FREQ>
for OpmDelay<TIM, FREQ>
{
type Error = core::convert::Infallible;
fn delay(&mut self, duration: TimerDurationU32<FREQ>) -> Result<(), Self::Error> {
self.delay(duration);
Ok(())
}
}
impl fugit_timer::Delay<1_000_000> for SysDelay {
type Error = core::convert::Infallible;
fn delay(&mut self, duration: MicrosDurationU32) -> Result<(), Self::Error> {
self.delay(duration);
Ok(())
}
}