use super::{FTimer, Instance};
use crate::rcc::Clocks;
use core::ops::{Deref, DerefMut};
pub use fugit::{self, ExtU32};
use rtic_monotonic::Monotonic;
pub struct MonoTimer<TIM, const FREQ: u32> {
timer: FTimer<TIM, FREQ>,
ovf: u32,
}
impl<TIM, const FREQ: u32> Deref for MonoTimer<TIM, FREQ> {
type Target = FTimer<TIM, FREQ>;
fn deref(&self) -> &Self::Target {
&self.timer
}
}
impl<TIM, const FREQ: u32> DerefMut for MonoTimer<TIM, FREQ> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.timer
}
}
pub type MonoTimerUs<TIM> = MonoTimer<TIM, 1_000_000>;
impl<TIM: Instance, const FREQ: u32> MonoTimer<TIM, FREQ> {
pub fn release(mut self) -> FTimer<TIM, FREQ> {
self.tim.cr1_reset();
self.timer
}
}
pub trait MonoTimerExt: Sized {
fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer<Self, FREQ>;
fn monotonic_us(self, clocks: &Clocks) -> MonoTimer<Self, 1_000_000> {
self.monotonic::<1_000_000>(clocks)
}
}
macro_rules! mono {
($TIM:ty) => {
impl MonoTimerExt for $TIM {
fn monotonic<const FREQ: u32>(self, clocks: &Clocks) -> MonoTimer<Self, FREQ> {
FTimer::new(self, clocks).monotonic()
}
}
impl<const FREQ: u32> FTimer<$TIM, FREQ> {
pub fn monotonic(self) -> MonoTimer<$TIM, FREQ> {
MonoTimer::<$TIM, FREQ>::_new(self)
}
}
impl<const FREQ: u32> MonoTimer<$TIM, FREQ> {
fn _new(timer: FTimer<$TIM, FREQ>) -> Self {
timer.tim.arr.write(|w| unsafe { w.arr().bits(u16::MAX) });
timer.tim.egr.write(|w| w.ug().set_bit());
timer.tim.sr.modify(|_, w| w.uif().clear_bit());
timer.tim.cr1.modify(|_, w| {
w.cen().set_bit();
w.udis().clear_bit();
w.urs().set_bit()
});
Self { timer, ovf: 0 }
}
}
impl<const FREQ: u32> Monotonic for MonoTimer<$TIM, FREQ> {
type Instant = fugit::TimerInstantU32<FREQ>;
type Duration = fugit::TimerDurationU32<FREQ>;
unsafe fn reset(&mut self) {
self.tim.dier.modify(|_, w| w.cc1ie().set_bit());
}
#[inline(always)]
fn now(&mut self) -> Self::Instant {
let cnt = self.tim.cnt.read().cnt().bits() as u32;
let ovf = if self.tim.sr.read().uif().bit_is_set() {
0x10000
} else {
0
};
Self::Instant::from_ticks(cnt.wrapping_add(ovf).wrapping_add(self.ovf))
}
fn set_compare(&mut self, instant: Self::Instant) {
let now = self.now();
let cnt = self.tim.cnt.read().cnt().bits();
let val = match instant.checked_duration_since(now) {
None => cnt.wrapping_add(0xffff), Some(x) if x.ticks() <= 0xffff => instant.duration_since_epoch().ticks() as u16, Some(_) => cnt.wrapping_add(0xffff), };
self.tim.ccr1.write(|w| unsafe { w.ccr().bits(val) });
}
fn clear_compare_flag(&mut self) {
self.tim.sr.modify(|_, w| w.cc1if().clear_bit());
}
fn on_interrupt(&mut self) {
if self.tim.sr.read().uif().bit_is_set() {
self.tim.sr.modify(|_, w| w.uif().clear_bit());
self.ovf += 0x10000;
}
}
#[inline(always)]
fn zero() -> Self::Instant {
Self::Instant::from_ticks(0)
}
}
};
}
mono!(crate::pac::TIM1);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
mono!(crate::pac::TIM3);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
mono!(crate::pac::TIM17);
#[cfg(any(feature = "py32f030", feature = "py32f003"))]
mono!(crate::pac::TIM16);
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002b"))]
mono!(crate::pac::TIM14);