aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32f4/src/lib.rs1
-rw-r--r--embassy-stm32f4/src/qei.rs95
-rw-r--r--embassy-traits/Cargo.toml1
-rw-r--r--embassy-traits/src/lib.rs1
-rw-r--r--embassy-traits/src/qei.rs22
5 files changed, 120 insertions, 0 deletions
diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs
index aa31951d3..aa99068c2 100644
--- a/embassy-stm32f4/src/lib.rs
+++ b/embassy-stm32f4/src/lib.rs
@@ -313,5 +313,6 @@ pub(crate) mod fmt;
313 313
314pub mod exti; 314pub mod exti;
315pub mod interrupt; 315pub mod interrupt;
316pub mod qei;
316pub mod rtc; 317pub mod rtc;
317pub mod serial; 318pub mod serial;
diff --git a/embassy-stm32f4/src/qei.rs b/embassy-stm32f4/src/qei.rs
new file mode 100644
index 000000000..1d4689e19
--- /dev/null
+++ b/embassy-stm32f4/src/qei.rs
@@ -0,0 +1,95 @@
1use crate::interrupt;
2use core::future::Future;
3use core::pin::Pin;
4use embassy::interrupt::Interrupt;
5use embassy::traits::qei::WaitForRotate;
6use embedded_hal::Direction;
7use embedded_hal::Qei as THQei;
8use stm32f4xx_hal::pac::TIM2;
9use stm32f4xx_hal::qei::{Pins, Qei as HalQei};
10
11pub struct Qei<T: Instance, PINS> {
12 qei: HalQei<T, PINS>,
13 int: T::Interrupt,
14}
15
16impl<PINS: Pins<TIM2>> Qei<TIM2, PINS> {
17 pub fn tim2(tim: TIM2, pins: PINS, interrupt: interrupt::TIM2) -> Self {
18 let qei = HalQei::tim2(tim, pins);
19
20 let tim = unsafe {
21 &mut *(stm32f4xx_hal::stm32::TIM2::ptr()
22 as *mut stm32f4xx_hal::stm32::tim2::RegisterBlock)
23 };
24 /*
25 enable qei interrupt
26 */
27 tim.dier.write(|w| w.uie().set_bit());
28
29 Qei {
30 qei: qei,
31 int: interrupt,
32 }
33 }
34}
35
36impl<PINS: Pins<TIM2> + 'static> WaitForRotate for Qei<TIM2, PINS> {
37 type RotateFuture<'a> = impl Future<Output = Direction> + 'a;
38
39 fn wait_for_rotate<'a>(
40 self: Pin<&'a mut Self>,
41 count_down: u16,
42 count_up: u16,
43 ) -> Self::RotateFuture<'a> {
44 let s = unsafe { self.get_unchecked_mut() };
45
46 let tim = unsafe {
47 &mut *(stm32f4xx_hal::stm32::TIM2::ptr()
48 as *mut stm32f4xx_hal::stm32::tim2::RegisterBlock)
49 };
50
51 /*
52 the interrupt will be reached at zero or the max count
53 write the total range to the qei.
54 */
55 tim.arr
56 .write(|w| unsafe { w.bits((count_down + count_up) as u32) });
57
58 /*
59 set timer to the correct value in the range
60 */
61 tim.cnt.write(|w| unsafe { w.bits(count_down as u32) });
62
63 /*
64 clear interrupt flag
65 */
66 tim.sr.write(|w| w.uif().clear_bit());
67
68 async move {
69 embassy::util::InterruptFuture::new(&mut s.int).await;
70
71 if tim.cnt.read().bits() == 0 {
72 Direction::Downcounting
73 } else if tim.cnt.read() == count_down + count_up {
74 Direction::Upcounting
75 } else {
76 panic!("unexpected value")
77 }
78 }
79 }
80}
81
82mod sealed {
83 pub trait Sealed {}
84}
85
86pub trait Instance: sealed::Sealed {
87 type Interrupt: interrupt::Interrupt;
88}
89
90#[cfg(feature = "stm32f405")]
91impl sealed::Sealed for TIM2 {}
92#[cfg(feature = "stm32f405")]
93impl Instance for TIM2 {
94 type Interrupt = interrupt::TIM2;
95}
diff --git a/embassy-traits/Cargo.toml b/embassy-traits/Cargo.toml
index 626bf9f3a..737f91181 100644
--- a/embassy-traits/Cargo.toml
+++ b/embassy-traits/Cargo.toml
@@ -9,3 +9,4 @@ std = []
9 9
10[dependencies] 10[dependencies]
11defmt = { version = "0.2.0", optional = true } 11defmt = { version = "0.2.0", optional = true }
12embedded-hal = { version = "0.2.3", features = ["unproven"] }
diff --git a/embassy-traits/src/lib.rs b/embassy-traits/src/lib.rs
index 10d44d9de..d8b06a091 100644
--- a/embassy-traits/src/lib.rs
+++ b/embassy-traits/src/lib.rs
@@ -9,5 +9,6 @@
9pub mod delay; 9pub mod delay;
10pub mod flash; 10pub mod flash;
11pub mod gpio; 11pub mod gpio;
12pub mod qei;
12pub mod i2c; 13pub mod i2c;
13pub mod uart; 14pub mod uart;
diff --git a/embassy-traits/src/qei.rs b/embassy-traits/src/qei.rs
new file mode 100644
index 000000000..73581256d
--- /dev/null
+++ b/embassy-traits/src/qei.rs
@@ -0,0 +1,22 @@
1use core::future::Future;
2use core::pin::Pin;
3use embedded_hal::Direction;
4
5// Wait for a specified number of rotations either up or down
6pub trait WaitForRotate {
7 type RotateFuture<'a>: Future<Output = Direction> + 'a;
8
9 /// Wait for a specified number of rotations, in ticks, either up or down.
10 ///
11 /// Return Direction::Upcounting if the high bound is reached.
12 /// Return Direction::Downcounting if the low bound is reached.
13 ///
14 /// Number of ticks is encoder dependent. As an example, if we connect
15 /// the Bourns PEC11H-4120F-S0020, we have 20 ticks per full rotation.
16 /// Other encoders may vary.
17 fn wait_for_rotate<'a>(
18 self: Pin<&'a mut Self>,
19 count_down: u16,
20 count_up: u16,
21 ) -> Self::RotateFuture<'a>;
22}