embassy_stm32/timer/
qei.rs1use core::marker::PhantomData;
4
5use stm32_metapac::timer::vals;
6
7use super::low_level::Timer;
8pub use super::{Ch1, Ch2};
9use super::{GeneralInstance4Channel, TimerPin};
10use crate::gpio::{AfType, AnyPin, Pull};
11use crate::timer::TimerChannel;
12use crate::Peri;
13
14pub enum Direction {
16 Upcounting,
18 Downcounting,
20}
21
22pub struct QeiPin<'d, T, Channel> {
24 _pin: Peri<'d, AnyPin>,
25 phantom: PhantomData<(T, Channel)>,
26}
27
28impl<'d, T: GeneralInstance4Channel, C: QeiChannel> QeiPin<'d, T, C> {
29 pub fn new(pin: Peri<'d, impl TimerPin<T, C>>) -> Self {
31 critical_section::with(|_| {
32 pin.set_low();
33 pin.set_as_af(pin.af_num(), AfType::input(Pull::None));
34 });
35 QeiPin {
36 _pin: pin.into(),
37 phantom: PhantomData,
38 }
39 }
40}
41
42trait SealedQeiChannel: TimerChannel {}
43
44#[expect(private_bounds)]
46pub trait QeiChannel: SealedQeiChannel {}
47
48impl QeiChannel for Ch1 {}
49impl QeiChannel for Ch2 {}
50
51impl SealedQeiChannel for Ch1 {}
52impl SealedQeiChannel for Ch2 {}
53
54pub struct Qei<'d, T: GeneralInstance4Channel> {
56 inner: Timer<'d, T>,
57}
58
59impl<'d, T: GeneralInstance4Channel> Qei<'d, T> {
60 pub fn new(tim: Peri<'d, T>, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
62 Self::new_inner(tim)
63 }
64
65 fn new_inner(tim: Peri<'d, T>) -> Self {
66 let inner = Timer::new(tim);
67 let r = inner.regs_gp16();
68
69 r.ccmr_input(0).modify(|w| {
71 w.set_ccs(0, vals::CcmrInputCcs::TI4);
72 w.set_ccs(1, vals::CcmrInputCcs::TI4);
73 });
74
75 r.ccer().modify(|w| {
77 w.set_cce(0, true);
78 w.set_cce(1, true);
79
80 w.set_ccp(0, false);
81 w.set_ccp(1, false);
82 });
83
84 r.smcr().modify(|w| {
85 w.set_sms(vals::Sms::ENCODER_MODE_3);
86 });
87
88 r.arr().modify(|w| w.set_arr(u16::MAX));
89 r.cr1().modify(|w| w.set_cen(true));
90
91 Self { inner }
92 }
93
94 pub fn read_direction(&self) -> Direction {
96 match self.inner.regs_gp16().cr1().read().dir() {
97 vals::Dir::DOWN => Direction::Downcounting,
98 vals::Dir::UP => Direction::Upcounting,
99 }
100 }
101
102 pub fn count(&self) -> u16 {
104 self.inner.regs_gp16().cnt().read().cnt()
105 }
106}