aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/saadc.rs93
1 files changed, 47 insertions, 46 deletions
diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs
index 03f21d829..edb8aa21f 100644
--- a/embassy-nrf/src/saadc.rs
+++ b/embassy-nrf/src/saadc.rs
@@ -32,7 +32,7 @@ pub enum Error {}
32/// One-shot saadc. Continuous sample mode TODO. 32/// One-shot saadc. Continuous sample mode TODO.
33pub struct OneShot<'d> { 33pub struct OneShot<'d> {
34 irq: interrupt::SAADC, 34 irq: interrupt::SAADC,
35 phantom: PhantomData<(&'d mut peripherals::SAADC)>, 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.
@@ -117,6 +117,49 @@ impl<'d> OneShot<'d> {
117 fn regs(&self) -> &saadc::RegisterBlock { 117 fn regs(&self) -> &saadc::RegisterBlock {
118 unsafe { &*SAADC::ptr() } 118 unsafe { &*SAADC::ptr() }
119 } 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 }
120} 163}
121 164
122impl<'d> Drop for OneShot<'d> { 165impl<'d> Drop for OneShot<'d> {
@@ -131,57 +174,15 @@ pub trait Sample {
131 where 174 where
132 Self: 'a; 175 Self: 'a;
133 176
134 fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a>; 177 fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a>;
135} 178}
136 179
137impl<'d> Sample for OneShot<'d> { 180impl<'d> Sample for OneShot<'d> {
138 #[rustfmt::skip] 181 #[rustfmt::skip]
139 type SampleFuture<'a> where Self: 'a = impl Future<Output = i16> + 'a; 182 type SampleFuture<'a> where Self: 'a = impl Future<Output = i16> + 'a;
140 183
141 fn sample<'a>(&'a mut self, pin: &mut dyn PositivePin) -> Self::SampleFuture<'a> { 184 fn sample<'a, T: PositivePin>(&'a mut self, pin: &mut T) -> Self::SampleFuture<'a> {
142 let channel = pin.channel(); 185 self.sample_inner(pin.channel())
143 async move {
144 let r = self.regs();
145
146 // Set positive channel
147 r.ch[0].pselp.write(|w| w.pselp().variant(channel));
148
149 // Set up the DMA
150 let mut val: i16 = 0;
151 r.result
152 .ptr
153 .write(|w| unsafe { w.ptr().bits(((&mut val) as *mut _) as u32) });
154 r.result.maxcnt.write(|w| unsafe { w.maxcnt().bits(1) });
155
156 // Reset and enable the end event
157 r.events_end.reset();
158 r.intenset.write(|w| w.end().set());
159
160 // Don't reorder the ADC start event before the previous writes. Hopefully self
161 // wouldn't happen anyway.
162 compiler_fence(Ordering::SeqCst);
163
164 r.tasks_start.write(|w| unsafe { w.bits(1) });
165 r.tasks_sample.write(|w| unsafe { w.bits(1) });
166
167 // Wait for 'end' event.
168 poll_fn(|cx| {
169 let r = self.regs();
170
171 if r.events_end.read().bits() != 0 {
172 r.events_end.reset();
173 return Poll::Ready(());
174 }
175
176 wake_on_interrupt(&mut self.irq, cx.waker());
177
178 Poll::Pending
179 })
180 .await;
181
182 // The DMA wrote the sampled value to `val`.
183 val
184 }
185 } 186 }
186} 187}
187 188