aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-05 21:28:13 +0100
committerDario Nieuwenhuis <[email protected]>2023-03-06 00:17:51 +0100
commitc66b28e759dc42c5f802336385a66eb8a82dab9a (patch)
treeadf46357b1e7bc8f212a760f0007e8a026bac66d
parentf8f1d3bcf09045616f5b63a08a9623cd14acd045 (diff)
nrf/qdec: make available on all chips, use Instance trait, switch to new interrupt binding.
-rw-r--r--embassy-nrf/src/chips/nrf52805.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52820.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs2
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs9
-rw-r--r--embassy-nrf/src/lib.rs2
-rw-r--r--embassy-nrf/src/qdec.rs112
-rw-r--r--examples/nrf52840/src/bin/qdec.rs9
11 files changed, 108 insertions, 38 deletions
diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs
index 3c74a2a63..185cda430 100644
--- a/embassy-nrf/src/chips/nrf52805.rs
+++ b/embassy-nrf/src/chips/nrf52805.rs
@@ -140,6 +140,8 @@ impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0);
140 140
141impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0); 141impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
142 142
143impl_qdec!(QDEC, QDEC, QDEC);
144
143impl_timer!(TIMER0, TIMER0, TIMER0); 145impl_timer!(TIMER0, TIMER0, TIMER0);
144impl_timer!(TIMER1, TIMER1, TIMER1); 146impl_timer!(TIMER1, TIMER1, TIMER1);
145impl_timer!(TIMER2, TIMER2, TIMER2); 147impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index c6ccb6a0e..1e3c054a4 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -150,6 +150,8 @@ impl_pwm!(PWM0, PWM0, PWM0);
150 150
151impl_pdm!(PDM, PDM, PDM); 151impl_pdm!(PDM, PDM, PDM);
152 152
153impl_qdec!(QDEC, QDEC, QDEC);
154
153impl_timer!(TIMER0, TIMER0, TIMER0); 155impl_timer!(TIMER0, TIMER0, TIMER0);
154impl_timer!(TIMER1, TIMER1, TIMER1); 156impl_timer!(TIMER1, TIMER1, TIMER1);
155impl_timer!(TIMER2, TIMER2, TIMER2); 157impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index 7d1bce1c0..3bb44171e 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -152,6 +152,8 @@ impl_pwm!(PWM0, PWM0, PWM0);
152 152
153impl_pdm!(PDM, PDM, PDM); 153impl_pdm!(PDM, PDM, PDM);
154 154
155impl_qdec!(QDEC, QDEC, QDEC);
156
155impl_timer!(TIMER0, TIMER0, TIMER0); 157impl_timer!(TIMER0, TIMER0, TIMER0);
156impl_timer!(TIMER1, TIMER1, TIMER1); 158impl_timer!(TIMER1, TIMER1, TIMER1);
157impl_timer!(TIMER2, TIMER2, TIMER2); 159impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs
index 81b07f32c..b28778f33 100644
--- a/embassy-nrf/src/chips/nrf52820.rs
+++ b/embassy-nrf/src/chips/nrf52820.rs
@@ -153,6 +153,8 @@ impl_timer!(TIMER1, TIMER1, TIMER1);
153impl_timer!(TIMER2, TIMER2, TIMER2); 153impl_timer!(TIMER2, TIMER2, TIMER2);
154impl_timer!(TIMER3, TIMER3, TIMER3, extended); 154impl_timer!(TIMER3, TIMER3, TIMER3, extended);
155 155
156impl_qdec!(QDEC, QDEC, QDEC);
157
156impl_pin!(P0_00, 0, 0); 158impl_pin!(P0_00, 0, 0);
157impl_pin!(P0_01, 0, 1); 159impl_pin!(P0_01, 0, 1);
158impl_pin!(P0_02, 0, 2); 160impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index ce19a18e8..00dc9fd8f 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -173,6 +173,8 @@ impl_pwm!(PWM2, PWM2, PWM2);
173 173
174impl_pdm!(PDM, PDM, PDM); 174impl_pdm!(PDM, PDM, PDM);
175 175
176impl_qdec!(QDEC, QDEC, QDEC);
177
176impl_timer!(TIMER0, TIMER0, TIMER0); 178impl_timer!(TIMER0, TIMER0, TIMER0);
177impl_timer!(TIMER1, TIMER1, TIMER1); 179impl_timer!(TIMER1, TIMER1, TIMER1);
178impl_timer!(TIMER2, TIMER2, TIMER2); 180impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 08b82021d..345608c9d 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -199,6 +199,8 @@ impl_pwm!(PWM3, PWM3, PWM3);
199 199
200impl_pdm!(PDM, PDM, PDM); 200impl_pdm!(PDM, PDM, PDM);
201 201
202impl_qdec!(QDEC, QDEC, QDEC);
203
202impl_timer!(TIMER0, TIMER0, TIMER0); 204impl_timer!(TIMER0, TIMER0, TIMER0);
203impl_timer!(TIMER1, TIMER1, TIMER1); 205impl_timer!(TIMER1, TIMER1, TIMER1);
204impl_timer!(TIMER2, TIMER2, TIMER2); 206impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 4e8b6d9ee..630f01aa9 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -210,6 +210,8 @@ impl_qspi!(QSPI, QSPI, QSPI);
210 210
211impl_pdm!(PDM, PDM, PDM); 211impl_pdm!(PDM, PDM, PDM);
212 212
213impl_qdec!(QDEC, QDEC, QDEC);
214
213impl_pin!(P0_00, 0, 0); 215impl_pin!(P0_00, 0, 0);
214impl_pin!(P0_01, 0, 1); 216impl_pin!(P0_01, 0, 1);
215impl_pin!(P0_02, 0, 2); 217impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 050612b1c..34f96800f 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -37,7 +37,7 @@ pub mod pac {
37 pdm0_ns as pdm, 37 pdm0_ns as pdm,
38 power_ns as power, 38 power_ns as power,
39 pwm0_ns as pwm0, 39 pwm0_ns as pwm0,
40 qdec0_ns as qdec0, 40 qdec0_ns as qdec,
41 qspi_ns as qspi, 41 qspi_ns as qspi,
42 regulators_ns as regulators, 42 regulators_ns as regulators,
43 reset_ns as reset, 43 reset_ns as reset,
@@ -256,6 +256,10 @@ embassy_hal_common::peripherals! {
256 // PDM 256 // PDM
257 PDM0, 257 PDM0,
258 258
259 // QDEC
260 QDEC0,
261 QDEC1,
262
259 // GPIOTE 263 // GPIOTE
260 GPIOTE_CH0, 264 GPIOTE_CH0,
261 GPIOTE_CH1, 265 GPIOTE_CH1,
@@ -403,6 +407,9 @@ impl_qspi!(QSPI, QSPI, QSPI);
403 407
404impl_pdm!(PDM0, PDM0, PDM0); 408impl_pdm!(PDM0, PDM0, PDM0);
405 409
410impl_qdec!(QDEC0, QDEC0, QDEC0);
411impl_qdec!(QDEC1, QDEC1, QDEC1);
412
406impl_pin!(P0_00, 0, 0); 413impl_pin!(P0_00, 0, 0);
407impl_pin!(P0_01, 0, 1); 414impl_pin!(P0_01, 0, 1);
408#[cfg(feature = "nfc-pins-as-gpio")] 415#[cfg(feature = "nfc-pins-as-gpio")]
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 17aa5ad15..feefa2486 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -57,7 +57,7 @@ pub mod pdm;
57pub mod ppi; 57pub mod ppi;
58#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))] 58#[cfg(not(any(feature = "nrf52805", feature = "nrf52820", feature = "_nrf5340-net")))]
59pub mod pwm; 59pub mod pwm;
60#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] 60#[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340-net")))]
61pub mod qdec; 61pub mod qdec;
62#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] 62#[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))]
63pub mod qspi; 63pub mod qspi;
diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs
index c01babca3..4d2a09198 100644
--- a/embassy-nrf/src/qdec.rs
+++ b/embassy-nrf/src/qdec.rs
@@ -1,20 +1,22 @@
1//! Quadrature decoder (QDEC) driver. 1//! Quadrature decoder (QDEC) driver.
2 2
3#![macro_use]
4
3use core::future::poll_fn; 5use core::future::poll_fn;
6use core::marker::PhantomData;
4use core::task::Poll; 7use core::task::Poll;
5 8
9use embassy_cortex_m::interrupt::Interrupt;
6use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker;
8 11
9use crate::gpio::sealed::Pin as _; 12use crate::gpio::sealed::Pin as _;
10use crate::gpio::{AnyPin, Pin as GpioPin}; 13use crate::gpio::{AnyPin, Pin as GpioPin};
11use crate::interrupt::InterruptExt; 14use crate::interrupt::InterruptExt;
12use crate::peripherals::QDEC; 15use crate::{interrupt, Peripheral};
13use crate::{interrupt, pac, Peripheral};
14 16
15/// Quadrature decoder driver. 17/// Quadrature decoder driver.
16pub struct Qdec<'d> { 18pub struct Qdec<'d, T: Instance> {
17 _p: PeripheralRef<'d, QDEC>, 19 _p: PeripheralRef<'d, T>,
18} 20}
19 21
20/// QDEC config 22/// QDEC config
@@ -44,44 +46,52 @@ impl Default for Config {
44 } 46 }
45} 47}
46 48
47static WAKER: AtomicWaker = AtomicWaker::new(); 49/// Interrupt handler.
50pub struct InterruptHandler<T: Instance> {
51 _phantom: PhantomData<T>,
52}
48 53
49impl<'d> Qdec<'d> { 54impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
55 unsafe fn on_interrupt() {
56 T::regs().intenclr.write(|w| w.reportrdy().clear());
57 T::state().waker.wake();
58 }
59}
60
61impl<'d, T: Instance> Qdec<'d, T> {
50 /// Create a new QDEC. 62 /// Create a new QDEC.
51 pub fn new( 63 pub fn new(
52 qdec: impl Peripheral<P = QDEC> + 'd, 64 qdec: impl Peripheral<P = T> + 'd,
53 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 65 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
54 a: impl Peripheral<P = impl GpioPin> + 'd, 66 a: impl Peripheral<P = impl GpioPin> + 'd,
55 b: impl Peripheral<P = impl GpioPin> + 'd, 67 b: impl Peripheral<P = impl GpioPin> + 'd,
56 config: Config, 68 config: Config,
57 ) -> Self { 69 ) -> Self {
58 into_ref!(a, b); 70 into_ref!(qdec, a, b);
59 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), None, config) 71 Self::new_inner(qdec, a.map_into(), b.map_into(), None, config)
60 } 72 }
61 73
62 /// Create a new QDEC, with a pin for LED output. 74 /// Create a new QDEC, with a pin for LED output.
63 pub fn new_with_led( 75 pub fn new_with_led(
64 qdec: impl Peripheral<P = QDEC> + 'd, 76 qdec: impl Peripheral<P = T> + 'd,
65 irq: impl Peripheral<P = interrupt::QDEC> + 'd, 77 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
66 a: impl Peripheral<P = impl GpioPin> + 'd, 78 a: impl Peripheral<P = impl GpioPin> + 'd,
67 b: impl Peripheral<P = impl GpioPin> + 'd, 79 b: impl Peripheral<P = impl GpioPin> + 'd,
68 led: impl Peripheral<P = impl GpioPin> + 'd, 80 led: impl Peripheral<P = impl GpioPin> + 'd,
69 config: Config, 81 config: Config,
70 ) -> Self { 82 ) -> Self {
71 into_ref!(a, b, led); 83 into_ref!(qdec, a, b, led);
72 Self::new_inner(qdec, irq, a.map_into(), b.map_into(), Some(led.map_into()), config) 84 Self::new_inner(qdec, a.map_into(), b.map_into(), Some(led.map_into()), config)
73 } 85 }
74 86
75 fn new_inner( 87 fn new_inner(
76 p: impl Peripheral<P = QDEC> + 'd, 88 p: PeripheralRef<'d, T>,
77 irq: impl Peripheral<P = interrupt::QDEC> + 'd,
78 a: PeripheralRef<'d, AnyPin>, 89 a: PeripheralRef<'d, AnyPin>,
79 b: PeripheralRef<'d, AnyPin>, 90 b: PeripheralRef<'d, AnyPin>,
80 led: Option<PeripheralRef<'d, AnyPin>>, 91 led: Option<PeripheralRef<'d, AnyPin>>,
81 config: Config, 92 config: Config,
82 ) -> Self { 93 ) -> Self {
83 into_ref!(p, irq); 94 let r = T::regs();
84 let r = Self::regs();
85 95
86 // Select pins. 96 // Select pins.
87 a.conf().write(|w| w.input().connect().pull().pullup()); 97 a.conf().write(|w| w.input().connect().pull().pullup());
@@ -124,20 +134,15 @@ impl<'d> Qdec<'d> {
124 SamplePeriod::_131ms => w.sampleper()._131ms(), 134 SamplePeriod::_131ms => w.sampleper()._131ms(),
125 }); 135 });
126 136
137 unsafe { T::Interrupt::steal() }.unpend();
138 unsafe { T::Interrupt::steal() }.enable();
139
127 // Enable peripheral 140 // Enable peripheral
128 r.enable.write(|w| w.enable().set_bit()); 141 r.enable.write(|w| w.enable().set_bit());
129 142
130 // Start sampling 143 // Start sampling
131 unsafe { r.tasks_start.write(|w| w.bits(1)) }; 144 unsafe { r.tasks_start.write(|w| w.bits(1)) };
132 145
133 irq.disable();
134 irq.set_handler(|_| {
135 let r = Self::regs();
136 r.intenclr.write(|w| w.reportrdy().clear());
137 WAKER.wake();
138 });
139 irq.enable();
140
141 Self { _p: p } 146 Self { _p: p }
142 } 147 }
143 148
@@ -155,12 +160,12 @@ impl<'d> Qdec<'d> {
155 /// let delta = q.read().await; 160 /// let delta = q.read().await;
156 /// ``` 161 /// ```
157 pub async fn read(&mut self) -> i16 { 162 pub async fn read(&mut self) -> i16 {
158 let t = Self::regs(); 163 let t = T::regs();
159 t.intenset.write(|w| w.reportrdy().set()); 164 t.intenset.write(|w| w.reportrdy().set());
160 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) }; 165 unsafe { t.tasks_readclracc.write(|w| w.bits(1)) };
161 166
162 let value = poll_fn(|cx| { 167 let value = poll_fn(|cx| {
163 WAKER.register(cx.waker()); 168 T::state().waker.register(cx.waker());
164 if t.events_reportrdy.read().bits() == 0 { 169 if t.events_reportrdy.read().bits() == 0 {
165 return Poll::Pending; 170 return Poll::Pending;
166 } else { 171 } else {
@@ -172,10 +177,6 @@ impl<'d> Qdec<'d> {
172 .await; 177 .await;
173 value 178 value
174 } 179 }
175
176 fn regs() -> &'static pac::qdec::RegisterBlock {
177 unsafe { &*pac::QDEC::ptr() }
178 }
179} 180}
180 181
181/// Sample period 182/// Sample period
@@ -236,3 +237,48 @@ pub enum LedPolarity {
236 /// Active low (a low output turns on the LED). 237 /// Active low (a low output turns on the LED).
237 ActiveLow, 238 ActiveLow,
238} 239}
240
241pub(crate) mod sealed {
242 use embassy_sync::waitqueue::AtomicWaker;
243
244 /// Peripheral static state
245 pub struct State {
246 pub waker: AtomicWaker,
247 }
248
249 impl State {
250 pub const fn new() -> Self {
251 Self {
252 waker: AtomicWaker::new(),
253 }
254 }
255 }
256
257 pub trait Instance {
258 fn regs() -> &'static crate::pac::qdec::RegisterBlock;
259 fn state() -> &'static State;
260 }
261}
262
263/// qdec peripheral instance.
264pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
265 /// Interrupt for this peripheral.
266 type Interrupt: Interrupt;
267}
268
269macro_rules! impl_qdec {
270 ($type:ident, $pac_type:ident, $irq:ident) => {
271 impl crate::qdec::sealed::Instance for peripherals::$type {
272 fn regs() -> &'static crate::pac::qdec::RegisterBlock {
273 unsafe { &*pac::$pac_type::ptr() }
274 }
275 fn state() -> &'static crate::qdec::sealed::State {
276 static STATE: crate::qdec::sealed::State = crate::qdec::sealed::State::new();
277 &STATE
278 }
279 }
280 impl crate::qdec::Instance for peripherals::$type {
281 type Interrupt = crate::interrupt::$irq;
282 }
283 };
284}
diff --git a/examples/nrf52840/src/bin/qdec.rs b/examples/nrf52840/src/bin/qdec.rs
index 600bba07a..59783d312 100644
--- a/examples/nrf52840/src/bin/qdec.rs
+++ b/examples/nrf52840/src/bin/qdec.rs
@@ -4,16 +4,19 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt;
8use embassy_nrf::qdec::{self, Qdec}; 7use embassy_nrf::qdec::{self, Qdec};
8use embassy_nrf::{bind_interrupts, peripherals};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(struct Irqs {
12 QDEC => qdec::InterruptHandler<peripherals::QDEC>;
13});
14
11#[embassy_executor::main] 15#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
13 let p = embassy_nrf::init(Default::default()); 17 let p = embassy_nrf::init(Default::default());
14 let irq = interrupt::take!(QDEC);
15 let config = qdec::Config::default(); 18 let config = qdec::Config::default();
16 let mut rotary_enc = Qdec::new(p.QDEC, irq, p.P0_31, p.P0_30, config); 19 let mut rotary_enc = Qdec::new(p.QDEC, Irqs, p.P0_31, p.P0_30, config);
17 20
18 info!("Turn rotary encoder!"); 21 info!("Turn rotary encoder!");
19 let mut value = 0; 22 let mut value = 0;