embassy_stm32/adc/
mod.rs

1//! Analog to Digital Converter (ADC)
2
3#![macro_use]
4#![allow(missing_docs)] // TODO
5#![cfg_attr(adc_f3_v2, allow(unused))]
6
7#[cfg(not(any(adc_f3_v2, adc_wba)))]
8#[cfg_attr(adc_f1, path = "f1.rs")]
9#[cfg_attr(adc_f3, path = "f3.rs")]
10#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
11#[cfg_attr(adc_v1, path = "v1.rs")]
12#[cfg_attr(adc_l0, path = "v1.rs")]
13#[cfg_attr(adc_v2, path = "v2.rs")]
14#[cfg_attr(any(adc_v3, adc_g0, adc_h5, adc_h7rs, adc_u0), path = "v3.rs")]
15#[cfg_attr(any(adc_v4, adc_u5), path = "v4.rs")]
16#[cfg_attr(adc_g4, path = "g4.rs")]
17#[cfg_attr(adc_c0, path = "c0.rs")]
18mod _version;
19
20use core::marker::PhantomData;
21
22#[allow(unused)]
23#[cfg(not(any(adc_f3_v2, adc_wba)))]
24pub use _version::*;
25use embassy_hal_internal::{impl_peripheral, PeripheralType};
26#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
27use embassy_sync::waitqueue::AtomicWaker;
28
29#[cfg(any(adc_u5, adc_wba))]
30#[path = "adc4.rs"]
31pub mod adc4;
32
33pub use crate::pac::adc::vals;
34#[cfg(not(any(adc_f1, adc_f3_v2)))]
35pub use crate::pac::adc::vals::Res as Resolution;
36pub use crate::pac::adc::vals::SampleTime;
37use crate::peripherals;
38
39#[cfg(not(adc_wba))]
40dma_trait!(RxDma, Instance);
41#[cfg(adc_u5)]
42dma_trait!(RxDma4, adc4::Instance);
43#[cfg(adc_wba)]
44dma_trait!(RxDma4, adc4::Instance);
45
46/// Analog to Digital driver.
47pub struct Adc<'d, T: Instance> {
48    #[allow(unused)]
49    adc: crate::Peri<'d, T>,
50    #[cfg(not(any(adc_f3_v2, adc_f3_v1_1, adc_wba)))]
51    sample_time: SampleTime,
52}
53
54#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
55pub struct State {
56    pub waker: AtomicWaker,
57}
58
59#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
60impl State {
61    pub const fn new() -> Self {
62        Self {
63            waker: AtomicWaker::new(),
64        }
65    }
66}
67
68trait SealedInstance {
69    #[cfg(not(adc_wba))]
70    #[allow(unused)]
71    fn regs() -> crate::pac::adc::Adc;
72    #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
73    #[allow(unused)]
74    fn common_regs() -> crate::pac::adccommon::AdcCommon;
75    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
76    fn state() -> &'static State;
77}
78
79pub(crate) trait SealedAdcChannel<T> {
80    #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
81    fn setup(&mut self) {}
82
83    #[allow(unused)]
84    fn channel(&self) -> u8;
85}
86
87/// Performs a busy-wait delay for a specified number of microseconds.
88#[allow(unused)]
89pub(crate) fn blocking_delay_us(us: u32) {
90    #[cfg(feature = "time")]
91    embassy_time::block_for(embassy_time::Duration::from_micros(us as u64));
92    #[cfg(not(feature = "time"))]
93    {
94        let freq = unsafe { crate::rcc::get_freqs() }.sys.to_hertz().unwrap().0 as u64;
95        let us = us as u64;
96        let cycles = freq * us / 1_000_000;
97        cortex_m::asm::delay(cycles as u32);
98    }
99}
100
101/// ADC instance.
102#[cfg(not(any(
103    adc_f1,
104    adc_v1,
105    adc_l0,
106    adc_v2,
107    adc_v3,
108    adc_v4,
109    adc_g4,
110    adc_f3,
111    adc_f3_v1_1,
112    adc_g0,
113    adc_u0,
114    adc_h5,
115    adc_h7rs,
116    adc_u5,
117    adc_c0,
118    adc_wba,
119)))]
120#[allow(private_bounds)]
121pub trait Instance: SealedInstance + crate::PeripheralType {
122    type Interrupt: crate::interrupt::typelevel::Interrupt;
123}
124/// ADC instance.
125#[cfg(any(
126    adc_f1,
127    adc_v1,
128    adc_l0,
129    adc_v2,
130    adc_v3,
131    adc_v4,
132    adc_g4,
133    adc_f3,
134    adc_f3_v1_1,
135    adc_g0,
136    adc_u0,
137    adc_h5,
138    adc_h7rs,
139    adc_u5,
140    adc_c0,
141    adc_wba,
142))]
143#[allow(private_bounds)]
144pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral {
145    type Interrupt: crate::interrupt::typelevel::Interrupt;
146}
147
148/// ADC channel.
149#[allow(private_bounds)]
150pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
151    #[allow(unused_mut)]
152    fn degrade_adc(mut self) -> AnyAdcChannel<T> {
153        #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
154        self.setup();
155
156        AnyAdcChannel {
157            channel: self.channel(),
158            _phantom: PhantomData,
159        }
160    }
161}
162
163/// A type-erased channel for a given ADC instance.
164///
165/// This is useful in scenarios where you need the ADC channels to have the same type, such as
166/// storing them in an array.
167pub struct AnyAdcChannel<T> {
168    channel: u8,
169    _phantom: PhantomData<T>,
170}
171impl_peripheral!(AnyAdcChannel<T: Instance>);
172impl<T: Instance> AdcChannel<T> for AnyAdcChannel<T> {}
173impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
174    fn channel(&self) -> u8 {
175        self.channel
176    }
177}
178
179impl<T> AnyAdcChannel<T> {
180    #[allow(unused)]
181    pub fn get_hw_channel(&self) -> u8 {
182        self.channel
183    }
184}
185#[cfg(adc_wba)]
186foreach_adc!(
187    (ADC4, $common_inst:ident, $clock:ident) => {
188        impl crate::adc::adc4::SealedInstance for peripherals::ADC4 {
189            fn regs() -> crate::pac::adc::Adc4 {
190                crate::pac::ADC4
191            }
192        }
193
194        impl crate::adc::adc4::Instance for peripherals::ADC4 {
195            type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
196        }
197    };
198
199    ($inst:ident, $common_inst:ident, $clock:ident) => {
200        impl crate::adc::SealedInstance for peripherals::$inst {
201            fn regs() -> crate::pac::adc::Adc {
202                crate::pac::$inst
203            }
204
205            fn common_regs() -> crate::pac::adccommon::AdcCommon {
206                return crate::pac::$common_inst
207            }
208        }
209
210        impl crate::adc::Instance for peripherals::$inst {
211            type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
212        }
213    };
214);
215
216#[cfg(adc_u5)]
217foreach_adc!(
218    (ADC4, $common_inst:ident, $clock:ident) => {
219        impl crate::adc::adc4::SealedInstance for peripherals::ADC4 {
220            fn regs() -> crate::pac::adc::Adc4 {
221                crate::pac::ADC4
222            }
223        }
224
225        impl crate::adc::adc4::Instance for peripherals::ADC4 {
226            type Interrupt = crate::_generated::peripheral_interrupts::ADC4::GLOBAL;
227        }
228    };
229
230    ($inst:ident, $common_inst:ident, $clock:ident) => {
231        impl crate::adc::SealedInstance for peripherals::$inst {
232            fn regs() -> crate::pac::adc::Adc {
233                crate::pac::$inst
234            }
235
236            fn common_regs() -> crate::pac::adccommon::AdcCommon {
237                return crate::pac::$common_inst
238            }
239        }
240
241        impl crate::adc::Instance for peripherals::$inst {
242            type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
243        }
244    };
245);
246
247#[cfg(not(any(adc_u5, adc_wba)))]
248foreach_adc!(
249    ($inst:ident, $common_inst:ident, $clock:ident) => {
250        impl crate::adc::SealedInstance for peripherals::$inst {
251            #[cfg(not(adc_wba))]
252            fn regs() -> crate::pac::adc::Adc {
253                crate::pac::$inst
254            }
255
256            #[cfg(adc_wba)]
257            fn regs() -> crate::pac::adc::Adc4 {
258                crate::pac::$inst
259            }
260
261            #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0, adc_u5, adc_wba)))]
262            fn common_regs() -> crate::pac::adccommon::AdcCommon {
263                return crate::pac::$common_inst
264            }
265
266            #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
267            fn state() -> &'static State {
268                static STATE: State = State::new();
269                &STATE
270            }
271        }
272
273        impl crate::adc::Instance for peripherals::$inst {
274            type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL;
275        }
276    };
277);
278
279macro_rules! impl_adc_pin {
280    ($inst:ident, $pin:ident, $ch:expr) => {
281        impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
282        impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
283            #[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5, adc_wba))]
284            fn setup(&mut self) {
285                <crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
286            }
287
288            fn channel(&self) -> u8 {
289                $ch
290            }
291        }
292    };
293}
294
295/// Get the maximum reading value for this resolution.
296///
297/// This is `2**n - 1`.
298#[cfg(not(any(adc_f1, adc_f3_v2)))]
299pub const fn resolution_to_max_count(res: Resolution) -> u32 {
300    match res {
301        #[cfg(adc_v4)]
302        Resolution::BITS16 => (1 << 16) - 1,
303        #[cfg(any(adc_v4, adc_u5))]
304        Resolution::BITS14 => (1 << 14) - 1,
305        #[cfg(adc_v4)]
306        Resolution::BITS14V => (1 << 14) - 1,
307        #[cfg(adc_v4)]
308        Resolution::BITS12V => (1 << 12) - 1,
309        Resolution::BITS12 => (1 << 12) - 1,
310        Resolution::BITS10 => (1 << 10) - 1,
311        Resolution::BITS8 => (1 << 8) - 1,
312        #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_c0, adc_g0, adc_f3, adc_f3_v1_1, adc_h5))]
313        Resolution::BITS6 => (1 << 6) - 1,
314        #[allow(unreachable_patterns)]
315        _ => core::unreachable!(),
316    }
317}