aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-05-22 15:50:41 +0200
committerGitHub <[email protected]>2021-05-22 15:50:41 +0200
commit62ad8ebab0919f5f7112a42ce4e93886439923e2 (patch)
treeca956447830c71790f9aaec13341c59483b1eb5d
parent3d520f8abe529cbfbbc4a4b575e15bae297a2dc8 (diff)
parent55c3ba2a5fb2ffddca187c0b04ad353433508426 (diff)
Merge pull request #198 from lulf/saadc-multiple-pins
Makes it possible to use the ADC with different analog pins
-rw-r--r--embassy-nrf/src/saadc.rs107
1 files changed, 53 insertions, 54 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index c1afd00de..edb8aa21f 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -30,9 +30,9 @@ pub use saadc::{
30pub enum Error {} 30pub enum Error {}
31 31
32/// One-shot saadc. Continuous sample mode TODO. 32/// One-shot saadc. Continuous sample mode TODO.
33pub struct OneShot<'d, T: PositivePin> { 33pub struct OneShot<'d> {
34 irq: interrupt::SAADC, 34 irq: interrupt::SAADC,
35 phantom: PhantomData<(&'d mut peripherals::SAADC, &'d mut T)>, 35 phantom: PhantomData<&'d mut peripherals::SAADC>,
36} 36}
37 37
38/// Used to configure the SAADC peripheral. 38/// Used to configure the SAADC peripheral.
@@ -66,14 +66,13 @@ impl Default for Config {
66 } 66 }
67} 67}
68 68
69impl<'d, T: PositivePin> OneShot<'d, T> { 69impl<'d> OneShot<'d> {
70 pub fn new( 70 pub fn new(
71 _saadc: impl Unborrow<Target = peripherals::SAADC> + 'd, 71 _saadc: impl Unborrow<Target = peripherals::SAADC> + 'd,
72 irq: impl Unborrow<Target = interrupt::SAADC> + 'd, 72 irq: impl Unborrow<Target = interrupt::SAADC> + 'd,
73 positive_pin: impl Unborrow<Target = T> + 'd,
74 config: Config, 73 config: Config,
75 ) -> Self { 74 ) -> Self {
76 unborrow!(irq, positive_pin); 75 unborrow!(irq);
77 76
78 let r = unsafe { &*SAADC::ptr() }; 77 let r = unsafe { &*SAADC::ptr() };
79 78
@@ -106,11 +105,6 @@ impl<'d, T: PositivePin> OneShot<'d, T> {
106 w 105 w
107 }); 106 });
108 107
109 // Set positive channel
110 r.ch[0]
111 .pselp
112 .write(|w| w.pselp().variant(positive_pin.channel()));
113
114 // Disable all events interrupts 108 // Disable all events interrupts
115 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) }); 109 r.intenclr.write(|w| unsafe { w.bits(0x003F_FFFF) });
116 110
@@ -123,9 +117,52 @@ impl<'d, T: PositivePin> OneShot<'d, T> {
123 fn regs(&self) -> &saadc::RegisterBlock { 117 fn regs(&self) -> &saadc::RegisterBlock {
124 unsafe { &*SAADC::ptr() } 118 unsafe { &*SAADC::ptr() }
125 } 119 }
120
121 async fn sample_inner(&mut self, pin: PositiveChannel) -> i16 {
122 let r = self.regs();
123
124 // Set positive channel
125 r.ch[0].pselp.write(|w| w.pselp().variant(pin));
126
127 // Set up the DMA
128 let mut val: i16 = 0;
129 r.result
130 .ptr
131 .write(|w| unsafe { w.ptr().bits(((&mut val) as *mut _) as u32) });
132 r.result.maxcnt.write(|w| unsafe { w.maxcnt().bits(1) });
133
134 // Reset and enable the end event
135 r.events_end.reset();
136 r.intenset.write(|w| w.end().set());
137
138 // Don't reorder the ADC start event before the previous writes. Hopefully self
139 // wouldn't happen anyway.
140 compiler_fence(Ordering::SeqCst);
141
142 r.tasks_start.write(|w| unsafe { w.bits(1) });
143 r.tasks_sample.write(|w| unsafe { w.bits(1) });
144
145 // Wait for 'end' event.
146 poll_fn(|cx| {
147 let r = self.regs();
148
149 if r.events_end.read().bits() != 0 {
150 r.events_end.reset();
151 return Poll::Ready(());
152 }
153
154 wake_on_interrupt(&mut self.irq, cx.waker());
155
156 Poll::Pending
157 })
158 .await;
159
160 // The DMA wrote the sampled value to `val`.
161 val
162 }
126} 163}
127 164
128impl<'d, T: PositivePin> Drop for OneShot<'d, T> { 165impl<'d> Drop for OneShot<'d> {
129 fn drop(&mut self) { 166 fn drop(&mut self) {
130 let r = self.regs(); 167 let r = self.regs();
131 r.enable.write(|w| w.enable().disabled()); 168 r.enable.write(|w| w.enable().disabled());
@@ -137,60 +174,22 @@ pub trait Sample {
137 where 174 where
138 Self: 'a; 175 Self: 'a;
139 176
140 fn sample<'a>(&'a mut self) -> Self::SampleFuture<'a>; 177 fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a>;
141} 178}
142 179
143impl<'d, T: PositivePin> Sample for OneShot<'d, T> { 180impl<'d> Sample for OneShot<'d> {
144 #[rustfmt::skip] 181 #[rustfmt::skip]
145 type SampleFuture<'a> where Self: 'a = impl Future<Output = i16> + 'a; 182 type SampleFuture<'a> where Self: 'a = impl Future<Output = i16> + 'a;
146 183
147 fn sample<'a>(&'a mut self) -> Self::SampleFuture<'a> { 184 fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a> {
148 async move { 185 self.sample_inner(pin.channel())
149 let r = self.regs();
150
151 // Set up the DMA
152 let mut val: i16 = 0;
153 r.result
154 .ptr
155 .write(|w| unsafe { w.ptr().bits(((&mut val) as *mut _) as u32) });
156 r.result.maxcnt.write(|w| unsafe { w.maxcnt().bits(1) });
157
158 // Reset and enable the end event
159 r.events_end.reset();
160 r.intenset.write(|w| w.end().set());
161
162 // Don't reorder the ADC start event before the previous writes. Hopefully self
163 // wouldn't happen anyway.
164 compiler_fence(Ordering::SeqCst);
165
166 r.tasks_start.write(|w| unsafe { w.bits(1) });
167 r.tasks_sample.write(|w| unsafe { w.bits(1) });
168
169 // Wait for 'end' event.
170 poll_fn(|cx| {
171 let r = self.regs();
172
173 if r.events_end.read().bits() != 0 {
174 r.events_end.reset();
175 return Poll::Ready(());
176 }
177
178 wake_on_interrupt(&mut self.irq, cx.waker());
179
180 Poll::Pending
181 })
182 .await;
183
184 // The DMA wrote the sampled value to `val`.
185 val
186 }
187 } 186 }
188} 187}
189 188
190/// A pin that can be used as the positive end of a ADC differential in the SAADC periperhal. 189/// A pin that can be used as the positive end of a ADC differential in the SAADC periperhal.
191/// 190///
192/// Currently negative is always shorted to ground (0V). 191/// Currently negative is always shorted to ground (0V).
193pub trait PositivePin: Unborrow<Target = Self> { 192pub trait PositivePin {
194 fn channel(&self) -> PositiveChannel; 193 fn channel(&self) -> PositiveChannel;
195} 194}
196 195