aboutsummaryrefslogtreecommitdiff
path: root/embassy-rp/src/adc.rs
diff options
context:
space:
mode:
authorHenrik Alsér <[email protected]>2022-11-15 16:12:07 +0100
committerHenrik Alsér <[email protected]>2022-11-15 16:12:07 +0100
commiteb149a0bd42d7690e78e5f2b37579c1f68be613b (patch)
treef6735a981123d6f8fd478a604db481d836e84ae5 /embassy-rp/src/adc.rs
parentd05979c7085675c33615700f6590b1543ed69323 (diff)
embassy-rp: Add basic ADC module
Diffstat (limited to 'embassy-rp/src/adc.rs')
-rw-r--r--embassy-rp/src/adc.rs178
1 files changed, 178 insertions, 0 deletions
diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
new file mode 100644
index 000000000..acef4deaf
--- /dev/null
+++ b/embassy-rp/src/adc.rs
@@ -0,0 +1,178 @@
1use core::future::poll_fn;
2use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll;
5
6use embassy_hal_common::into_ref;
7use embassy_sync::waitqueue::AtomicWaker;
8use embedded_hal_02::adc::{Channel, OneShot};
9
10use crate::interrupt::{self, InterruptExt};
11use crate::peripherals::ADC;
12use crate::{pac, peripherals, Peripheral};
13static WAKER: AtomicWaker = AtomicWaker::new();
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17#[non_exhaustive]
18pub enum Error {
19 // No errors for now
20}
21
22#[non_exhaustive]
23pub struct Config {}
24
25impl Default for Config {
26 fn default() -> Self {
27 Self {}
28 }
29}
30pub struct Adc<'d> {
31 phantom: PhantomData<&'d ADC>,
32}
33
34impl<'d> Adc<'d> {
35 #[inline]
36 fn regs() -> pac::adc::Adc {
37 pac::ADC
38 }
39
40 #[inline]
41 fn reset() -> pac::resets::regs::Peripherals {
42 let mut ret = pac::resets::regs::Peripherals::default();
43 ret.set_adc(true);
44 ret
45 }
46
47 pub fn new(
48 _inner: impl Peripheral<P = ADC> + 'd,
49 irq: impl Peripheral<P = interrupt::ADC_IRQ_FIFO> + 'd,
50 _config: Config,
51 ) -> Self {
52 into_ref!(irq);
53 unsafe {
54 let reset = Self::reset();
55 crate::reset::reset(reset);
56 crate::reset::unreset_wait(reset);
57 let r = Self::regs();
58 // Enable ADC
59 r.cs().write(|w| w.set_en(true));
60 // Wait for ADC ready
61 while !r.cs().read().ready() {}
62 }
63
64 // Setup IRQ
65 irq.disable();
66 irq.set_handler(|_| unsafe {
67 let r = Self::regs();
68 r.inte().modify(|w| w.set_fifo(false));
69 WAKER.wake();
70 });
71 irq.unpend();
72 irq.enable();
73
74 Self { phantom: PhantomData }
75 }
76
77 async fn wait_for_ready() {
78 let r = Self::regs();
79 unsafe {
80 r.inte().modify(|w| w.set_fifo(true));
81 compiler_fence(Ordering::SeqCst);
82 poll_fn(|cx| {
83 WAKER.register(cx.waker());
84 if r.cs().read().ready() {
85 return Poll::Ready(());
86 }
87 Poll::Pending
88 })
89 .await;
90 }
91 }
92
93 pub async fn read<PIN: Channel<Adc<'d>, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 {
94 let r = Self::regs();
95 unsafe {
96 r.cs().modify(|w| {
97 w.set_ainsel(PIN::channel());
98 w.set_start_once(true)
99 });
100 Self::wait_for_ready().await;
101 r.result().read().result().into()
102 }
103 }
104
105 pub async fn read_temperature(&mut self) -> u16 {
106 let r = Self::regs();
107 unsafe {
108 r.cs().modify(|w| w.set_ts_en(true));
109 if !r.cs().read().ready() {
110 Self::wait_for_ready().await;
111 }
112 r.cs().modify(|w| {
113 w.set_ainsel(4);
114 w.set_start_once(true)
115 });
116 Self::wait_for_ready().await;
117 r.result().read().result().into()
118 }
119 }
120
121 pub fn blocking_read<PIN: Channel<Adc<'d>, ID = u8>>(&mut self, _pin: &mut PIN) -> u16 {
122 let r = Self::regs();
123 let ch = PIN::channel();
124 unsafe {
125 if ch == 4 {
126 r.cs().modify(|w| w.set_ts_en(true))
127 }
128 while !r.cs().read().ready() {}
129 r.cs().modify(|w| {
130 w.set_ainsel(ch);
131 w.set_start_once(true)
132 });
133 while !r.cs().read().ready() {}
134 r.result().read().result().into()
135 }
136 }
137
138 pub fn blocking_read_temperature(&mut self) -> u16 {
139 let r = Self::regs();
140 unsafe {
141 r.cs().modify(|w| w.set_ts_en(true));
142 while !r.cs().read().ready() {}
143 r.cs().modify(|w| {
144 w.set_ainsel(4);
145 w.set_start_once(true)
146 });
147 while !r.cs().read().ready() {}
148 r.result().read().result().into()
149 }
150 }
151}
152
153macro_rules! impl_pin {
154 ($pin:ident, $channel:expr) => {
155 impl Channel<Adc<'static>> for peripherals::$pin {
156 type ID = u8;
157 fn channel() -> u8 {
158 $channel
159 }
160 }
161 };
162}
163
164impl_pin!(PIN_26, 0);
165impl_pin!(PIN_27, 1);
166impl_pin!(PIN_28, 2);
167impl_pin!(PIN_29, 3);
168
169impl<WORD, PIN> OneShot<Adc<'static>, WORD, PIN> for Adc<'static>
170where
171 WORD: From<u16>,
172 PIN: Channel<Adc<'static>, ID = u8>,
173{
174 type Error = ();
175 fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
176 Ok(self.blocking_read(pin).into())
177 }
178}