diff options
Diffstat (limited to 'embassy-stm32/src/timer/qei.rs')
| -rw-r--r-- | embassy-stm32/src/timer/qei.rs | 56 |
1 files changed, 34 insertions, 22 deletions
diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index f3c81667c..82b5968b0 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs | |||
| @@ -6,8 +6,9 @@ use stm32_metapac::timer::vals; | |||
| 6 | 6 | ||
| 7 | use super::low_level::Timer; | 7 | use super::low_level::Timer; |
| 8 | pub use super::{Ch1, Ch2}; | 8 | pub use super::{Ch1, Ch2}; |
| 9 | use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; | 9 | use super::{GeneralInstance4Channel, TimerPin}; |
| 10 | use crate::gpio::{AfType, AnyPin, Pull}; | 10 | use crate::gpio::{AfType, AnyPin, Pull}; |
| 11 | use crate::timer::TimerChannel; | ||
| 11 | use crate::Peri; | 12 | use crate::Peri; |
| 12 | 13 | ||
| 13 | /// Counting direction | 14 | /// Counting direction |
| @@ -19,31 +20,37 @@ pub enum Direction { | |||
| 19 | } | 20 | } |
| 20 | 21 | ||
| 21 | /// Wrapper for using a pin with QEI. | 22 | /// Wrapper for using a pin with QEI. |
| 22 | pub struct QeiPin<'d, T, Channel> { | 23 | pub struct QeiPin<'d, T, Channel, #[cfg(afio)] A> { |
| 23 | _pin: Peri<'d, AnyPin>, | 24 | #[allow(unused)] |
| 24 | phantom: PhantomData<(T, Channel)>, | 25 | pin: Peri<'d, AnyPin>, |
| 26 | phantom: PhantomData<if_afio!((T, Channel, A))>, | ||
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | macro_rules! channel_impl { | 29 | impl<'d, T: GeneralInstance4Channel, C: QeiChannel, #[cfg(afio)] A> if_afio!(QeiPin<'d, T, C, A>) { |
| 28 | ($new_chx:ident, $channel:ident, $pin_trait:ident) => { | 30 | /// Create a new QEI pin instance. |
| 29 | impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { | 31 | pub fn new(pin: Peri<'d, if_afio!(impl TimerPin<T, C, A>)>) -> Self { |
| 30 | #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] | 32 | critical_section::with(|_| { |
| 31 | pub fn $new_chx(pin: Peri<'d, impl $pin_trait<T>>) -> Self { | 33 | pin.set_low(); |
| 32 | critical_section::with(|_| { | 34 | set_as_af!(pin, AfType::input(Pull::None)); |
| 33 | pin.set_low(); | 35 | }); |
| 34 | pin.set_as_af(pin.af_num(), AfType::input(Pull::None)); | 36 | QeiPin { |
| 35 | }); | 37 | pin: pin.into(), |
| 36 | QeiPin { | 38 | phantom: PhantomData, |
| 37 | _pin: pin.into(), | ||
| 38 | phantom: PhantomData, | ||
| 39 | } | ||
| 40 | } | ||
| 41 | } | 39 | } |
| 42 | }; | 40 | } |
| 43 | } | 41 | } |
| 44 | 42 | ||
| 45 | channel_impl!(new_ch1, Ch1, Channel1Pin); | 43 | trait SealedQeiChannel: TimerChannel {} |
| 46 | channel_impl!(new_ch2, Ch2, Channel2Pin); | 44 | |
| 45 | /// Marker trait for a timer channel eligible for use with QEI. | ||
| 46 | #[expect(private_bounds)] | ||
| 47 | pub trait QeiChannel: SealedQeiChannel {} | ||
| 48 | |||
| 49 | impl QeiChannel for Ch1 {} | ||
| 50 | impl QeiChannel for Ch2 {} | ||
| 51 | |||
| 52 | impl SealedQeiChannel for Ch1 {} | ||
| 53 | impl SealedQeiChannel for Ch2 {} | ||
| 47 | 54 | ||
| 48 | /// Quadrature decoder driver. | 55 | /// Quadrature decoder driver. |
| 49 | pub struct Qei<'d, T: GeneralInstance4Channel> { | 56 | pub struct Qei<'d, T: GeneralInstance4Channel> { |
| @@ -52,7 +59,12 @@ pub struct Qei<'d, T: GeneralInstance4Channel> { | |||
| 52 | 59 | ||
| 53 | impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { | 60 | impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { |
| 54 | /// Create a new quadrature decoder driver. | 61 | /// Create a new quadrature decoder driver. |
| 55 | pub fn new(tim: Peri<'d, T>, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { | 62 | #[allow(unused)] |
| 63 | pub fn new<#[cfg(afio)] A>( | ||
| 64 | tim: Peri<'d, T>, | ||
| 65 | ch1: if_afio!(QeiPin<'d, T, Ch1, A>), | ||
| 66 | ch2: if_afio!(QeiPin<'d, T, Ch2, A>), | ||
| 67 | ) -> Self { | ||
| 56 | Self::new_inner(tim) | 68 | Self::new_inner(tim) |
| 57 | } | 69 | } |
| 58 | 70 | ||
