use atsamd_hal_macros::hal_cfg;
use crate::pac::tc0::Count16 as Count16Reg;
use crate::pac::{Mclk, Tc2, Tc3};
#[hal_cfg(all("tc4", "tc5"))]
use crate::pac::{Tc4, Tc5};
#[hal_cfg(all("tc6", "tc7"))]
use crate::pac::{Tc6, Tc7};
use crate::clock;
use crate::time::Hertz;
mod common;
pub use common::Count16;
#[cfg(feature = "async")]
mod async_api;
#[cfg(feature = "async")]
pub use async_api::*;
pub struct TimerCounter<TC> {
freq: Hertz,
tc: TC,
}
impl<TC> TimerCounter<TC>
where
TC: Count16,
{
fn start_timer(&mut self, divider: u16, cycles: u16) {
self.disable();
let count = self.tc.count_16();
count.ctrla().write(|w| w.swrst().set_bit());
while count.syncbusy().read().swrst().bit_is_set() {}
count.ctrlbset().write(|w| {
w.dir().clear_bit();
w.oneshot().clear_bit()
});
count.cc(0).write(|w| unsafe { w.cc().bits(cycles) });
count.wave().modify(|_, w| w.wavegen().mfrq());
count.ctrla().modify(|_, w| {
match divider {
1 => w.prescaler().div1(),
2 => w.prescaler().div2(),
4 => w.prescaler().div4(),
8 => w.prescaler().div8(),
16 => w.prescaler().div16(),
64 => w.prescaler().div64(),
256 => w.prescaler().div256(),
1024 => w.prescaler().div1024(),
_ => unreachable!(),
};
w.enable().set_bit();
w.runstdby().set_bit()
});
}
fn disable(&mut self) {
let count = self.tc.count_16();
count.ctrla().modify(|_, w| w.enable().clear_bit());
while count.syncbusy().read().enable().bit_is_set() {}
}
}
macro_rules! tc {
($($TYPE:ident: ($TC:ident, $mclk:ident, $clock:ident, $apmask:ident),)+) => {
$(
pub type $TYPE = TimerCounter<$TC>;
impl Count16 for $TC {
fn count_16(&self) -> &Count16Reg {
self.count16()
}
}
impl TimerCounter<$TC>
{
pub fn $mclk(clock: &clock::$clock, tc: $TC, mclk: &mut Mclk) -> Self {
mclk.$apmask().modify(|_, w| w.$mclk().set_bit());
{
let count = tc.count16();
count.ctrla().modify(|_, w| w.enable().clear_bit());
while count.syncbusy().read().enable().bit_is_set() {}
}
Self {
freq: clock.freq(),
tc,
}
}
}
)+
}
}
tc! {
TimerCounter2: (Tc2, tc2_, Tc2Tc3Clock, apbbmask),
TimerCounter3: (Tc3, tc3_, Tc2Tc3Clock, apbbmask),
}
#[hal_cfg(all("tc4", "tc5"))]
tc! {
TimerCounter4: (Tc4, tc4_, Tc4Tc5Clock, apbcmask),
TimerCounter5: (Tc5, tc5_, Tc4Tc5Clock, apbcmask),
}
#[hal_cfg(all("tc6", "tc7"))]
tc! {
TimerCounter6: (Tc6, tc6_, Tc6Tc7Clock, apbdmask),
TimerCounter7: (Tc7, tc7_, Tc6Tc7Clock, apbdmask),
}