use core::marker::PhantomData;
use embassy_hal_internal::Peripheral;
use embassy_sync::waitqueue::AtomicWaker;
#[cfg(not(stm32l0))]
pub mod complementary_pwm;
pub mod input_capture;
pub mod low_level;
pub mod pwm_input;
pub mod qei;
pub mod simple_pwm;
use crate::interrupt;
use crate::rcc::RccPeripheral;
#[derive(Clone, Copy)]
pub enum Channel {
Ch1,
Ch2,
Ch3,
Ch4,
}
impl Channel {
pub fn index(&self) -> usize {
match self {
Channel::Ch1 => 0,
Channel::Ch2 => 1,
Channel::Ch3 => 2,
Channel::Ch4 => 3,
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TimerBits {
Bits16,
#[cfg(not(stm32l0))]
Bits32,
}
struct State {
up_waker: AtomicWaker,
cc_waker: [AtomicWaker; 4],
}
impl State {
const fn new() -> Self {
Self {
up_waker: AtomicWaker::new(),
cc_waker: [const { AtomicWaker::new() }; 4],
}
}
}
trait SealedInstance: RccPeripheral + Peripheral<P = Self> {
fn state() -> &'static State;
}
#[allow(private_bounds)]
pub trait CoreInstance: SealedInstance + 'static {
type UpdateInterrupt: interrupt::typelevel::Interrupt;
const BITS: TimerBits;
fn regs() -> *mut ();
}
pub trait BasicNoCr2Instance: CoreInstance {}
pub trait BasicInstance: BasicNoCr2Instance {}
pub trait GeneralInstance1Channel: CoreInstance {
type CaptureCompareInterrupt: interrupt::typelevel::Interrupt;
}
pub trait GeneralInstance2Channel: GeneralInstance1Channel {
type TriggerInterrupt: interrupt::typelevel::Interrupt;
}
trait General4ChBlankSealed {
fn enable_outputs(&self) {}
}
#[allow(private_bounds)]
pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel + General4ChBlankSealed {}
pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {}
pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel {
type CommunicationInterrupt: interrupt::typelevel::Interrupt;
type BreakInputInterrupt: interrupt::typelevel::Interrupt;
}
pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {}
pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {}
pin_trait!(Channel1Pin, GeneralInstance4Channel);
pin_trait!(Channel2Pin, GeneralInstance4Channel);
pin_trait!(Channel3Pin, GeneralInstance4Channel);
pin_trait!(Channel4Pin, GeneralInstance4Channel);
pin_trait!(ExternalTriggerPin, GeneralInstance4Channel);
pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel);
pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel);
pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel);
pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel);
pin_trait!(BreakInputPin, AdvancedInstance4Channel);
pin_trait!(BreakInput2Pin, AdvancedInstance4Channel);
pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel);
pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel);
pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel);
pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel);
dma_trait!(UpDma, BasicInstance);
dma_trait!(Ch1Dma, GeneralInstance4Channel);
dma_trait!(Ch2Dma, GeneralInstance4Channel);
dma_trait!(Ch3Dma, GeneralInstance4Channel);
dma_trait!(Ch4Dma, GeneralInstance4Channel);
#[allow(unused)]
macro_rules! impl_core_timer {
($inst:ident, $bits:expr) => {
impl SealedInstance for crate::peripherals::$inst {
fn state() -> &'static State {
static STATE: State = State::new();
&STATE
}
}
impl CoreInstance for crate::peripherals::$inst {
type UpdateInterrupt = crate::_generated::peripheral_interrupts::$inst::UP;
const BITS: TimerBits = $bits;
fn regs() -> *mut () {
crate::pac::$inst.as_ptr()
}
}
};
}
#[allow(unused)]
macro_rules! impl_general_1ch {
($inst:ident) => {
impl GeneralInstance1Channel for crate::peripherals::$inst {
type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC;
}
};
}
#[allow(unused)]
macro_rules! impl_general_2ch {
($inst:ident) => {
impl GeneralInstance2Channel for crate::peripherals::$inst {
type TriggerInterrupt = crate::_generated::peripheral_interrupts::$inst::TRG;
}
};
}
#[allow(unused)]
macro_rules! impl_advanced_1ch {
($inst:ident) => {
impl AdvancedInstance1Channel for crate::peripherals::$inst {
type CommunicationInterrupt = crate::_generated::peripheral_interrupts::$inst::COM;
type BreakInputInterrupt = crate::_generated::peripheral_interrupts::$inst::BRK;
}
};
}
#[allow(unused)]
macro_rules! impl_general_4ch_blank_sealed {
($inst:ident) => {
impl General4ChBlankSealed for crate::peripherals::$inst {
fn enable_outputs(&self) {
unsafe { crate::pac::timer::Tim1chCmp::from_ptr(Self::regs()) }
.bdtr()
.modify(|w| w.set_moe(true));
}
}
};
}
foreach_interrupt! {
($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_1CH, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_2CH, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_GP16, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_GP32, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits32);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl GeneralInstance32bit4Channel for crate::peripherals::$inst {}
impl General4ChBlankSealed for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {}
};
($inst:ident, timer, TIM_ADV, UP, $irq:ident) => {
impl_core_timer!($inst, TimerBits::Bits16);
impl BasicNoCr2Instance for crate::peripherals::$inst {}
impl BasicInstance for crate::peripherals::$inst {}
impl_general_1ch!($inst);
impl_general_2ch!($inst);
impl GeneralInstance4Channel for crate::peripherals::$inst {}
impl_general_4ch_blank_sealed!($inst);
impl_advanced_1ch!($inst);
impl AdvancedInstance2Channel for crate::peripherals::$inst {}
impl AdvancedInstance4Channel for crate::peripherals::$inst {}
};
}
pub struct UpdateInterruptHandler<T: CoreInstance> {
_phantom: PhantomData<T>,
}
impl<T: CoreInstance> interrupt::typelevel::Handler<T::UpdateInterrupt> for UpdateInterruptHandler<T> {
unsafe fn on_interrupt() {
#[cfg(feature = "low-power")]
crate::low_power::on_wakeup_irq();
let regs = crate::pac::timer::TimCore::from_ptr(T::regs());
let sr = regs.sr().read();
let bits = sr.0 & 0x00000001;
regs.dier().modify(|w| w.0 &= !bits);
if sr.uif() {
T::state().up_waker.wake();
}
}
}
pub struct CaptureCompareInterruptHandler<T: GeneralInstance1Channel> {
_phantom: PhantomData<T>,
}
impl<T: GeneralInstance1Channel> interrupt::typelevel::Handler<T::CaptureCompareInterrupt>
for CaptureCompareInterruptHandler<T>
{
unsafe fn on_interrupt() {
#[cfg(feature = "low-power")]
crate::low_power::on_wakeup_irq();
let regs = crate::pac::timer::TimGp16::from_ptr(T::regs());
let sr = regs.sr().read();
let bits = sr.0 & 0x0000001E;
regs.dier().modify(|w| w.0 &= !bits);
for ch in 0..4 {
if sr.ccif(ch) {
T::state().cc_waker[ch].wake();
}
}
}
}