stm32: generify timer::one_pulse and timer::qei pin constructors

This commit is contained in:
melvdl 2025-06-26 22:55:12 +02:00
parent 3e78f8a108
commit 1623d4e639
2 changed files with 91 additions and 49 deletions

View File

@ -7,7 +7,7 @@ use core::pin::Pin;
use core::task::{Context, Poll};
use super::low_level::{
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource,
CountingMode, FilterValue, InputCaptureMode, InputTISelection, SlaveMode, Timer, TriggerSource as Ts,
};
use super::{CaptureCompareInterruptHandler, ExternalTriggerPin, GeneralInstance4Channel, TimerChannel, TimerPin};
pub use super::{Ch1, Ch2};
@ -46,33 +46,71 @@ pub struct TriggerPin<'d, T, C> {
phantom: PhantomData<(T, C)>,
}
// TODO: Generify trigger inputs
trait SealedTriggerSource {}
impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch1> {
/// Marker trait for a trigger source.
#[expect(private_bounds)]
pub trait TriggerSource: SealedTriggerSource {}
impl TriggerSource for Ch1 {}
impl TriggerSource for Ch2 {}
impl TriggerSource for Ext {}
impl SealedTriggerSource for Ch1 {}
impl SealedTriggerSource for Ch2 {}
impl SealedTriggerSource for Ext {}
trait SealedTimerTriggerPin<T, S>: crate::gpio::Pin {}
/// Marker trait for a trigger pin.
#[expect(private_bounds)]
// TODO: find better naming scheme than prefixing all pin traits with "Timer".
// The trait name cannot conflict with the corresponding type's name.
// Applies to other timer submodules as well.
pub trait TimerTriggerPin<T, S>: SealedTimerTriggerPin<T, S> {
/// Get the AF number needed to use this pin as a trigger source.
fn af_num(&self) -> u8;
}
impl<T, P, C> TimerTriggerPin<T, C> for P
where
T: GeneralInstance4Channel,
P: TimerPin<T, C>,
C: super::Channel + TriggerSource,
{
fn af_num(&self) -> u8 {
TimerPin::af_num(self)
}
}
impl<T, P> TimerTriggerPin<T, Ext> for P
where
T: GeneralInstance4Channel,
P: ExternalTriggerPin<T>,
{
fn af_num(&self) -> u8 {
ExternalTriggerPin::af_num(self)
}
}
impl<T, P, C> SealedTimerTriggerPin<T, C> for P
where
T: GeneralInstance4Channel,
P: TimerPin<T, C>,
C: super::Channel + TriggerSource,
{
}
impl<T, P> SealedTimerTriggerPin<T, Ext> for P
where
T: GeneralInstance4Channel,
P: ExternalTriggerPin<T>,
{
}
impl<'d, T: GeneralInstance4Channel, C: TriggerSource> TriggerPin<'d, T, C> {
/// "Create a new Ch1 trigger pin instance.
pub fn new_ch1(pin: Peri<'d, impl TimerPin<T, Ch1>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
TriggerPin {
_pin: pin.into(),
phantom: PhantomData,
}
}
}
impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ch2> {
/// "Create a new Ch2 trigger pin instance.
pub fn new_ch2(pin: Peri<'d, impl TimerPin<T, Ch2>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
TriggerPin {
_pin: pin.into(),
phantom: PhantomData,
}
}
}
impl<'d, T: GeneralInstance4Channel> TriggerPin<'d, T, Ext> {
/// "Create a new EXT trigger pin instance.
pub fn new_ext(pin: Peri<'d, impl ExternalTriggerPin<T>>, pull: Pull) -> Self {
pub fn new(pin: Peri<'d, impl TimerTriggerPin<T, C>>, pull: Pull) -> Self {
pin.set_as_af(pin.af_num(), AfType::input(pull));
TriggerPin {
_pin: pin.into(),
@ -103,7 +141,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
) -> Self {
let mut this = Self { inner: Timer::new(tim) };
this.inner.set_trigger_source(TriggerSource::TI1F_ED);
this.inner.set_trigger_source(Ts::TI1F_ED);
this.inner
.set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
this.inner
@ -128,7 +166,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
) -> Self {
let mut this = Self { inner: Timer::new(tim) };
this.inner.set_trigger_source(TriggerSource::TI1FP1);
this.inner.set_trigger_source(Ts::TI1FP1);
this.inner
.set_input_ti_selection(TimerChannel::Ch1, InputTISelection::Normal);
this.inner
@ -154,7 +192,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
) -> Self {
let mut this = Self { inner: Timer::new(tim) };
this.inner.set_trigger_source(TriggerSource::TI2FP2);
this.inner.set_trigger_source(Ts::TI2FP2);
this.inner
.set_input_ti_selection(TimerChannel::Ch2, InputTISelection::Normal);
this.inner
@ -186,7 +224,7 @@ impl<'d, T: GeneralInstance4Channel> OnePulse<'d, T> {
// No filtering
r.set_etf(FilterValue::NO_FILTER);
});
this.inner.set_trigger_source(TriggerSource::ETRF);
this.inner.set_trigger_source(Ts::ETRF);
this.new_inner(freq, pulse_end, counting_mode);
this

View File

@ -8,6 +8,7 @@ use super::low_level::Timer;
pub use super::{Ch1, Ch2};
use super::{GeneralInstance4Channel, TimerPin};
use crate::gpio::{AfType, AnyPin, Pull};
use crate::timer::Channel;
use crate::Peri;
/// Counting direction
@ -24,28 +25,31 @@ pub struct QeiPin<'d, T, Channel> {
phantom: PhantomData<(T, Channel)>,
}
// TODO: generify QEI channels
macro_rules! channel_impl {
($new_chx:ident, $channel:ident, $pin_trait:ident) => {
impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> {
#[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")]
pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T, $channel>>) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
});
QeiPin {
_pin: pin.into(),
phantom: PhantomData,
}
}
impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
/// Create a new QEI pin instance.
pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
critical_section::with(|_| {
pin.set_low();
pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
});
QeiPin {
_pin: pin.into(),
phantom: PhantomData,
}
};
}
}
channel_impl!(new_ch1, Ch1, TimerPin);
channel_impl!(new_ch2, Ch2, TimerPin);
trait SealedQeiChannel: Channel {}
/// Marker trait for a timer channel eligible for use with QEI.
#[expect(private_bounds)]
pub trait QeiChannel: SealedQeiChannel {}
impl QeiChannel for Ch1 {}
impl QeiChannel for Ch2 {}
impl SealedQeiChannel for Ch1 {}
impl SealedQeiChannel for Ch2 {}
/// Quadrature decoder driver.
pub struct Qei<'d, T: GeneralInstance4Channel> {