stm32wlxx_hal/
adc.rs

1//! Analog to digital converter
2//!
3//! Quickstart:
4//!
5//! * [`Adc::pin`] Sample an analog pin
6//! * [`Adc::temperature`] Sample the junction temperature
7//! * [`Adc::vbat`] Sample the battery voltage
8#![cfg_attr(feature = "stm32wl5x_cm0p", allow(rustdoc::broken_intra_doc_links))]
9#![cfg_attr(feature = "stm32wl5x_cm0p", allow(dead_code))]
10#![cfg_attr(feature = "stm32wl5x_cm0p", allow(unused_imports))]
11
12#[cfg(not(feature = "stm32wl5x_cm0p"))]
13pub use pac::adc::cfgr2::{OVSR_A as OversampleRatio, OVSS_A as OversampleShift};
14
15use crate::gpio;
16use crate::Ratio;
17
18use super::pac;
19use core::{ptr::read_volatile, time::Duration};
20
21use embedded_hal::blocking::delay::DelayUs;
22
23// DS13293 rev 1 table 12
24// TS ADC raw data acquired at 30 °C (± 5 °C),
25// VDDA = VREF+ = 3.3 V (± 10 mV)
26fn ts_cal1() -> u16 {
27    unsafe { read_volatile(0x1FFF_75A8 as *const u16) }
28}
29
30// DS13293 rev 1 table 12
31// TS ADC raw data acquired at 130 °C (± 5 °C),
32// VDDA = VREF+ = 3.3 V (± 10 mV)
33fn ts_cal2() -> u16 {
34    unsafe { read_volatile(0x1FFF_75C8 as *const u16) }
35}
36
37fn ts_cal() -> (u16, u16) {
38    (ts_cal1(), ts_cal2())
39}
40
41const TS_CAL1_TEMP: i16 = 30;
42const TS_CAL2_TEMP: i16 = 130;
43const TS_CAL_TEMP_DELTA: i16 = TS_CAL2_TEMP - TS_CAL1_TEMP;
44
45/// t<sub>S_temp</sub> temperature sensor minimum sampling time
46///
47/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
48pub const TS_MIN_SAMPLE: Duration = Duration::from_micros(5);
49/// t<sub>START</sub> temperature sensor typical startup time when entering
50/// continuous mode
51///
52/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
53pub const TS_START_TYP: Duration = Duration::from_micros(70);
54/// t<sub>START</sub> temperature sensor maximum startup time when entering
55/// continuous mode
56///
57/// Value from DS13293 Rev 1 page 121 table 83 "TS characteristics"
58pub const TS_START_MAX: Duration = Duration::from_micros(120);
59
60/// t<sub>ADCVREG_SETUP</sub> ADC voltage regulator maximum startup time
61///
62/// Value from DS13293 Rev 1 page 117 table 80 "ADC characteristics"
63pub const T_ADCVREG_SETUP: Duration = Duration::from_micros(20);
64
65/// [`T_ADCVREG_SETUP`] expressed in microseconds
66///
67/// # Example
68///
69/// ```
70/// use stm32wlxx_hal::adc::{T_ADCVREG_SETUP, T_ADCVREG_SETUP_MICROS};
71///
72/// assert_eq!(
73///     u128::from(T_ADCVREG_SETUP_MICROS),
74///     T_ADCVREG_SETUP.as_micros()
75/// );
76/// ```
77pub const T_ADCVREG_SETUP_MICROS: u8 = T_ADCVREG_SETUP.as_micros() as u8;
78
79/// Mask of all valid channels
80///
81/// Channels 0-17, but without 15 and 16 because they are reserved.
82const CH_MASK: u32 = 0x27FFF;
83
84/// Interrupt masks
85///
86/// Used for [`Adc::set_isr`] and [`Adc::set_ier`].
87pub mod irq {
88    /// Channel configuration ready
89    pub const CCRDY: u32 = 1 << 13;
90    /// End of calibration
91    pub const EOCAL: u32 = 1 << 11;
92    /// Analog watchdog 3
93    pub const AWD3: u32 = 1 << 9;
94    /// Analog watchdog 2
95    pub const AWD2: u32 = 1 << 8;
96    /// Analog watchdog 1
97    pub const AWD1: u32 = 1 << 7;
98    /// Overrun
99    pub const OVR: u32 = 1 << 4;
100    /// End of conversion sequence
101    pub const EOS: u32 = 1 << 3;
102    /// End of conversion
103    pub const EOC: u32 = 1 << 2;
104    /// End of sampling
105    pub const EOSMP: u32 = 1 << 1;
106    /// ADC ready
107    pub const ADRDY: u32 = 1;
108
109    /// All IRQs
110    pub const ALL: u32 = CCRDY | EOCAL | AWD3 | AWD2 | AWD1 | OVR | EOS | EOC | EOSMP | ADRDY;
111}
112
113/// Internal voltage reference ADC calibration
114///
115/// This is raw ADC data acquired at 30 °C (± 5 °C).
116///
117/// V<sub>DDA</sub> = V<sub>REF+</sub> = 3.3 V (± 10mV)
118pub fn vref_cal() -> u16 {
119    // DS13293 rev 1 table 13
120    unsafe { read_volatile(0x1FFF_75AA as *const u16) }
121}
122
123/// ADC clock mode
124///
125/// In all synchronous clock modes, there is no jitter in the delay from a
126/// timer trigger to the start of a conversion.
127#[derive(Debug, PartialEq, Eq, Clone, Copy)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub enum Clk {
130    /// Asynchronous clock mode HSI16
131    RccHsi,
132    /// Asynchronous clock mode PLLP
133    RccPllP,
134    /// Asynchronous clock mode SYSCLK
135    RccSysClk,
136    /// Synchronous clock mode, pclk/2
137    PClkDiv2,
138    /// Synchronous clock mode, pclk/4
139    PClkDiv4,
140    /// Synchronous clock mode, pclk
141    ///
142    /// This configuration must be enabled only if PCLK has a 50% duty clock
143    /// cycle (APB prescaler configured inside the RCC must be bypassed and
144    /// the system clock must by 50% duty cycle)
145    PClk,
146}
147
148#[cfg(not(feature = "stm32wl5x_cm0p"))]
149impl Clk {
150    const fn ckmode(&self) -> pac::adc::cfgr2::CKMODE_A {
151        match self {
152            Clk::RccHsi | Clk::RccPllP | Clk::RccSysClk => pac::adc::cfgr2::CKMODE_A::Adclk,
153            Clk::PClkDiv2 => pac::adc::cfgr2::CKMODE_A::PclkDiv2,
154            Clk::PClkDiv4 => pac::adc::cfgr2::CKMODE_A::PclkDiv4,
155            Clk::PClk => pac::adc::cfgr2::CKMODE_A::Pclk,
156        }
157    }
158
159    const fn adcsel(&self) -> pac::rcc::ccipr::ADCSEL_A {
160        match self {
161            Clk::RccHsi => pac::rcc::ccipr::ADCSEL_A::Hsi16,
162            Clk::RccPllP => pac::rcc::ccipr::ADCSEL_A::Pllp,
163            Clk::RccSysClk => pac::rcc::ccipr::ADCSEL_A::Sysclk,
164            _ => pac::rcc::ccipr::ADCSEL_A::NoClock,
165        }
166    }
167}
168
169/// ADC sample times
170#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
171#[repr(u8)]
172pub enum Ts {
173    /// 1.5 ADC clock cycles
174    Cyc1 = 0,
175    /// 3.5 ADC clock cycles
176    Cyc3 = 1,
177    /// 7.5 ADC clock cycles
178    Cyc7 = 2,
179    /// 12.5 ADC clock cycles
180    Cyc12 = 3,
181    /// 19.5 ADC clock cycles
182    Cyc19 = 4,
183    /// 39.5 ADC clock cycles
184    Cyc39 = 5,
185    /// 79.5 ADC clock cycles
186    Cyc79 = 6,
187    /// 160.5 ADC clock cycles
188    Cyc160 = 7,
189}
190
191impl Default for Ts {
192    /// Reset value of the sample time.
193    fn default() -> Self {
194        Ts::Cyc1
195    }
196}
197
198impl Ts {
199    /// Maximum sample time, 160.5 ADC clock cycles.
200    ///
201    /// # Example
202    ///
203    /// ```
204    /// use stm32wlxx_hal::adc::Ts;
205    ///
206    /// assert_eq!(Ts::MAX, Ts::Cyc160);
207    /// ```
208    pub const MAX: Self = Self::Cyc160;
209
210    /// Minimum sample time, 1.5 ADC clock cycles.
211    ///
212    /// # Example
213    ///
214    /// ```
215    /// use stm32wlxx_hal::adc::Ts;
216    ///
217    /// assert_eq!(Ts::MIN, Ts::Cyc1);
218    /// ```
219    pub const MIN: Self = Self::Cyc1;
220
221    /// Number of cycles.
222    ///
223    /// # Example
224    ///
225    /// ```
226    /// use stm32wlxx_hal::adc::Ts;
227    ///
228    /// assert!(f32::from(Ts::Cyc1.cycles()) - 1.5 < 0.001);
229    /// assert!(f32::from(Ts::Cyc3.cycles()) - 3.5 < 0.001);
230    /// assert!(f32::from(Ts::Cyc7.cycles()) - 7.5 < 0.001);
231    /// assert!(f32::from(Ts::Cyc12.cycles()) - 12.5 < 0.001);
232    /// assert!(f32::from(Ts::Cyc19.cycles()) - 19.5 < 0.001);
233    /// assert!(f32::from(Ts::Cyc39.cycles()) - 39.5 < 0.001);
234    /// assert!(f32::from(Ts::Cyc79.cycles()) - 79.5 < 0.001);
235    /// assert!(f32::from(Ts::Cyc160.cycles()) - 160.5 < 0.001);
236    /// ```
237    pub const fn cycles(&self) -> Ratio<u16> {
238        match self {
239            Ts::Cyc1 => Ratio::new_raw(3, 2),
240            Ts::Cyc3 => Ratio::new_raw(7, 2),
241            Ts::Cyc7 => Ratio::new_raw(15, 2),
242            Ts::Cyc12 => Ratio::new_raw(25, 2),
243            Ts::Cyc19 => Ratio::new_raw(39, 2),
244            Ts::Cyc39 => Ratio::new_raw(79, 2),
245            Ts::Cyc79 => Ratio::new_raw(159, 2),
246            Ts::Cyc160 => Ratio::new_raw(321, 2),
247        }
248    }
249
250    /// Get the cycles as a duration.
251    ///
252    /// Fractional nano-seconds are rounded towards zero.
253    ///
254    /// You can get the ADC frequency with [`Adc::clock_hz`].
255    ///
256    /// # Example
257    ///
258    /// Assuming the ADC clock frequency is 16 MHz.
259    ///
260    /// ```
261    /// use core::time::Duration;
262    /// use stm32wlxx_hal::adc::Ts;
263    ///
264    /// const FREQ: u32 = 16_000_000;
265    ///
266    /// assert_eq!(Ts::Cyc1.as_duration(FREQ), Duration::from_nanos(93));
267    /// assert_eq!(Ts::Cyc3.as_duration(FREQ), Duration::from_nanos(218));
268    /// assert_eq!(Ts::Cyc7.as_duration(FREQ), Duration::from_nanos(468));
269    /// assert_eq!(Ts::Cyc12.as_duration(FREQ), Duration::from_nanos(781));
270    /// assert_eq!(Ts::Cyc19.as_duration(FREQ), Duration::from_nanos(1_218));
271    /// assert_eq!(Ts::Cyc39.as_duration(FREQ), Duration::from_nanos(2_468));
272    /// assert_eq!(Ts::Cyc79.as_duration(FREQ), Duration::from_nanos(4_968));
273    /// assert_eq!(Ts::Cyc160.as_duration(FREQ), Duration::from_nanos(10_031));
274    /// ```
275    ///
276    /// [`Adc::clock_hz`]: crate::adc::Adc::clock_hz
277    pub const fn as_duration(&self, hz: u32) -> Duration {
278        let numer: u64 = (*self.cycles().numer() as u64).saturating_mul(1_000_000_000);
279        let denom: u64 = (*self.cycles().denom() as u64).saturating_mul(hz as u64);
280        Duration::from_nanos(numer / denom)
281    }
282}
283
284impl From<Ts> for u8 {
285    fn from(ts: Ts) -> Self {
286        ts as u8
287    }
288}
289
290impl From<Ts> for u32 {
291    fn from(ts: Ts) -> Self {
292        ts as u32
293    }
294}
295
296/// ADC channels
297#[derive(Debug, PartialEq, Eq, Clone, Copy)]
298#[repr(u8)]
299pub enum Ch {
300    /// ADC input 0.
301    ///
302    /// Connected to [`B13`](crate::gpio::pins::B13).
303    In0 = 0,
304    /// ADC input 1.
305    ///
306    /// Connected to [`B14`](crate::gpio::pins::B14).
307    In1 = 1,
308    /// ADC input 2.
309    ///
310    /// Connected to [`B3`](crate::gpio::pins::B3).
311    In2 = 2,
312    /// ADC input 3.
313    ///
314    /// Connected to [`B4`](crate::gpio::pins::B4).
315    In3 = 3,
316    /// ADC input 4.
317    ///
318    /// Connected to [`B2`](crate::gpio::pins::B2).
319    In4 = 4,
320    /// ADC input 5.
321    ///
322    /// Connected to [`B1`](crate::gpio::pins::B1).
323    In5 = 5,
324    /// ADC input 6.
325    ///
326    /// Connected to [`A10`](crate::gpio::pins::A10).
327    In6 = 6,
328    /// ADC input 7.
329    ///
330    /// Connected to [`A11`](crate::gpio::pins::A11).
331    In7 = 7,
332    /// ADC input 8.
333    ///
334    /// Connected to [`A12`](crate::gpio::pins::A12).
335    In8 = 8,
336    /// ADC input 9.
337    ///
338    /// Connected to [`A13`](crate::gpio::pins::A13).
339    In9 = 9,
340    /// ADC input 10.
341    ///
342    /// Connected to [`A14`](crate::gpio::pins::A14).
343    In10 = 10,
344    /// ADC input 11.
345    ///
346    /// Connected to [`A15`](crate::gpio::pins::A15).
347    In11 = 11,
348    /// Junction temperature sensor.
349    Vts = 12,
350    /// Internal voltage reference.
351    Vref = 13,
352    /// Battery voltage divided by 3.
353    Vbat = 14,
354    // 15, 16 are reserved
355    /// Digital to analog converter output.
356    ///
357    /// The DAC outputs to this internal pin only when configured to output to
358    /// chip peripherals.
359    Dac = 17,
360}
361
362impl Ch {
363    /// Bitmask of the channel.
364    ///
365    /// # Example
366    ///
367    /// ```
368    /// use stm32wlxx_hal::adc::Ch;
369    ///
370    /// assert_eq!(Ch::In0.mask(), 0x001);
371    /// assert_eq!(Ch::In8.mask(), 0x100);
372    /// ```
373    pub const fn mask(self) -> u32 {
374        1 << (self as u8)
375    }
376}
377
378/// Analog to digital converter driver.
379#[derive(Debug)]
380#[cfg(not(feature = "stm32wl5x_cm0p"))]
381pub struct Adc {
382    adc: pac::ADC,
383}
384
385#[cfg(not(feature = "stm32wl5x_cm0p"))]
386impl Adc {
387    /// Create a new ADC driver from a ADC peripheral.
388    ///
389    /// This will enable the ADC clock and reset the ADC peripheral.
390    ///
391    /// **Note:** This will select the clock source, but you are responsible
392    /// for enabling that clock source.
393    ///
394    /// # Example
395    ///
396    /// Initialize the ADC with HSI16.
397    ///
398    /// ```no_run
399    /// use stm32wlxx_hal::{
400    ///     adc::{self, Adc},
401    ///     pac,
402    /// };
403    ///
404    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
405    ///
406    /// // enable the HSI16 source clock
407    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
408    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
409    ///
410    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
411    /// ```
412    ///
413    /// Initialize the ADC with PCLK/4.
414    ///
415    /// ```no_run
416    /// use stm32wlxx_hal::{
417    ///     adc::{self, Adc},
418    ///     pac,
419    /// };
420    ///
421    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
422    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
423    /// ```
424    #[inline]
425    pub fn new(adc: pac::ADC, clk: Clk, rcc: &mut pac::RCC) -> Self {
426        unsafe { Self::pulse_reset(rcc) };
427        Self::enable_clock(rcc);
428        let mut adc: Self = Self { adc };
429        adc.set_clock_source(clk, rcc);
430        adc
431    }
432
433    /// Create a new ADC driver from an ADC peripheral without initialization.
434    ///
435    /// This is a slightly safer version of [`steal`](Self::steal).
436    ///
437    /// # Safety
438    ///
439    /// 1. Reset the ADC peripheral if determinism is required.
440    /// 2. Enable the ADC peripheral clock before using the ADC.
441    /// 3. Select the clock source if a non-default clock is required.
442    ///
443    /// # Example
444    ///
445    /// ```no_run
446    /// use stm32wlxx_hal::{
447    ///     adc::{self, Adc},
448    ///     pac,
449    /// };
450    ///
451    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
452    ///
453    /// // safety: nothing is using the peripheral
454    /// unsafe { Adc::pulse_reset(&mut dp.RCC) };
455    ///
456    /// Adc::enable_clock(&mut dp.RCC);
457    ///
458    /// // safety: ADC peripheral has been reset and clocks are enabled
459    /// let mut adc: Adc = unsafe { Adc::new_no_init(dp.ADC) };
460    ///
461    /// // select the ADC clock, optional
462    /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
463    /// ```
464    #[inline]
465    pub const unsafe fn new_no_init(adc: pac::ADC) -> Self {
466        Self { adc }
467    }
468
469    /// Free the ADC peripheral from the driver.
470    ///
471    /// # Example
472    ///
473    /// ```no_run
474    /// use stm32wlxx_hal::{
475    ///     adc::{self, Adc},
476    ///     pac,
477    /// };
478    ///
479    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
480    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
481    /// // ... use ADC
482    /// let adc: pac::ADC = adc.free();
483    /// ```
484    #[inline]
485    pub fn free(self) -> pac::ADC {
486        self.adc
487    }
488
489    /// Steal the ADC peripheral from whatever is currently using it.
490    ///
491    /// This will **not** initialize the ADC (unlike [`new`]).
492    ///
493    /// # Safety
494    ///
495    /// 1. Ensure that the code stealing the ADC has exclusive access to the
496    ///    peripheral. Singleton checks are bypassed with this method.
497    /// 2. Reset the ADC peripheral if determinism is required.
498    /// 3. Enable the ADC peripheral clock before using the ADC.
499    /// 4. Select the clock source if a non-default clock is required.
500    ///
501    /// # Example
502    ///
503    /// ```no_run
504    /// use stm32wlxx_hal::{
505    ///     adc::{self, Adc},
506    ///     pac,
507    /// };
508    ///
509    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
510    /// let _: pac::ADC = dp.ADC;
511    ///
512    /// unsafe { Adc::pulse_reset(&mut dp.RCC) };
513    ///
514    /// Adc::enable_clock(&mut dp.RCC);
515    ///
516    /// let mut adc: Adc = unsafe { Adc::steal() };
517    ///
518    /// // select the ADC clock, optional
519    /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
520    /// ```
521    ///
522    /// [`new`]: Adc::new
523    #[inline]
524    pub unsafe fn steal() -> Adc {
525        Adc {
526            adc: pac::Peripherals::steal().ADC,
527        }
528    }
529
530    /// Set the ADC clock source.
531    ///
532    /// # Panics
533    ///
534    /// * (debug) ADC is enabled
535    ///
536    /// # Example
537    ///
538    /// ```no_run
539    /// use stm32wlxx_hal::{
540    ///     adc::{self, Adc},
541    ///     pac,
542    /// };
543    ///
544    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
545    /// let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
546    ///
547    /// // change the clock source
548    /// adc.disable();
549    /// adc.set_clock_source(adc::Clk::PClkDiv4, &mut dp.RCC);
550    /// ```
551    #[inline]
552    pub fn set_clock_source(&mut self, clk: Clk, rcc: &mut pac::RCC) {
553        debug_assert!(!self.is_enabled());
554        self.adc
555            .cfgr2
556            .modify(|_, w| w.ckmode().variant(clk.ckmode()));
557        rcc.ccipr.modify(|_, w| w.adcsel().variant(clk.adcsel()));
558    }
559
560    /// Get the ADC clock source.
561    ///
562    /// Returns `None` if the ADC is configured for an asynchronous clock,
563    /// but no asynchronous clock is selected.
564    ///
565    /// # Example
566    ///
567    /// ```no_run
568    /// use stm32wlxx_hal::{
569    ///     adc::{self, Adc},
570    ///     pac,
571    /// };
572    ///
573    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
574    /// let mut adc: Adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
575    ///
576    /// assert_eq!(adc.clock_source(&dp.RCC), Some(adc::Clk::PClkDiv4));
577    /// ```
578    pub fn clock_source(&self, rcc: &pac::RCC) -> Option<Clk> {
579        use pac::{adc::cfgr2::CKMODE_A, rcc::ccipr::ADCSEL_A};
580
581        match self.adc.cfgr2.read().ckmode().variant() {
582            CKMODE_A::Adclk => match rcc.ccipr.read().adcsel().variant() {
583                ADCSEL_A::NoClock => None,
584                ADCSEL_A::Hsi16 => Some(Clk::RccHsi),
585                ADCSEL_A::Pllp => Some(Clk::RccPllP),
586                ADCSEL_A::Sysclk => Some(Clk::RccSysClk),
587            },
588            CKMODE_A::PclkDiv2 => Some(Clk::PClkDiv2),
589            CKMODE_A::PclkDiv4 => Some(Clk::PClkDiv4),
590            CKMODE_A::Pclk => Some(Clk::PClk),
591        }
592    }
593
594    /// Disable the ADC clock.
595    ///
596    /// # Safety
597    ///
598    /// 1. Ensure nothing is using the ADC before disabling the clock.
599    /// 2. You are responsible for re-enabling the clock before using the ADC.
600    #[inline]
601    pub unsafe fn disable_clock(rcc: &mut pac::RCC) {
602        rcc.apb2enr.modify(|_, w| w.adcen().disabled());
603    }
604
605    /// Enable the ADC clock.
606    ///
607    /// [`new`](crate::adc::Adc::new) will enable clocks for you.
608    #[inline]
609    pub fn enable_clock(rcc: &mut pac::RCC) {
610        rcc.apb2enr.modify(|_, w| w.adcen().enabled());
611        rcc.apb2enr.read(); // delay after an RCC peripheral clock enabling
612    }
613
614    /// Pulse the ADC reset.
615    ///
616    /// [`new`](crate::adc::Adc::new) will pulse reset for you.
617    ///
618    /// # Safety
619    ///
620    /// 1. Ensure nothing is using the ADC before calling this function.
621    /// 2. You are responsible for setting up the ADC after a reset.
622    #[inline]
623    pub unsafe fn pulse_reset(rcc: &mut pac::RCC) {
624        rcc.apb2rstr.modify(|_, w| w.adcrst().set_bit());
625        rcc.apb2rstr.modify(|_, w| w.adcrst().clear_bit());
626    }
627
628    /// Calculate the ADC clock frequency in hertz.
629    ///
630    /// **Note:** If the ADC prescaler register erroneously returns a reserved
631    /// value the code will default to an ADC prescaler of 1.
632    ///
633    /// Fractional frequencies will be rounded towards zero.
634    ///
635    /// # Example
636    ///
637    /// ```no_run
638    /// use stm32wlxx_hal::{
639    ///     adc::{self, Adc},
640    ///     pac,
641    /// };
642    ///
643    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
644    ///
645    /// // enable the HSI16 source clock
646    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
647    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
648    ///
649    /// let adc: Adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
650    /// assert_eq!(adc.clock_hz(&dp.RCC), 16_000_000);
651    /// ```
652    pub fn clock_hz(&self, rcc: &pac::RCC) -> u32 {
653        use pac::{
654            adc::{ccr::PRESC_A, cfgr2::CKMODE_A},
655            rcc::ccipr::ADCSEL_A,
656        };
657
658        let source_freq: Ratio<u32> = match self.adc.cfgr2.read().ckmode().variant() {
659            CKMODE_A::Adclk => {
660                let src: Ratio<u32> = match rcc.ccipr.read().adcsel().variant() {
661                    ADCSEL_A::NoClock => Ratio::new_raw(0, 1),
662                    ADCSEL_A::Hsi16 => Ratio::new_raw(16_000_000, 1),
663                    ADCSEL_A::Pllp => crate::rcc::pllpclk(rcc, &rcc.pllcfgr.read()),
664                    ADCSEL_A::Sysclk => crate::rcc::sysclk(rcc, &rcc.cfgr.read()),
665                };
666
667                // only the asynchronous clocks have the prescaler applied
668                let ccr = self.adc.ccr.read();
669                let prescaler: u32 = match ccr.presc().variant() {
670                    Some(p) => match p {
671                        PRESC_A::Div1 => 1,
672                        PRESC_A::Div2 => 2,
673                        PRESC_A::Div4 => 4,
674                        PRESC_A::Div6 => 6,
675                        PRESC_A::Div8 => 8,
676                        PRESC_A::Div10 => 10,
677                        PRESC_A::Div12 => 12,
678                        PRESC_A::Div16 => 16,
679                        PRESC_A::Div32 => 32,
680                        PRESC_A::Div64 => 64,
681                        PRESC_A::Div128 => 128,
682                        PRESC_A::Div256 => 256,
683                    },
684                    None => {
685                        error!("Reserved ADC prescaler value {:#X}", ccr.presc().bits());
686                        1
687                    }
688                };
689
690                src / prescaler
691            }
692            CKMODE_A::PclkDiv2 => crate::rcc::pclk2(rcc, &rcc.cfgr.read()) / 2,
693            CKMODE_A::PclkDiv4 => crate::rcc::pclk2(rcc, &rcc.cfgr.read()) / 4,
694            CKMODE_A::Pclk => crate::rcc::pclk2(rcc, &rcc.cfgr.read()),
695        };
696
697        source_freq.to_integer()
698    }
699
700    /// Unmask the ADC IRQ in the NVIC.
701    ///
702    /// # Safety
703    ///
704    /// This can break mask-based critical sections.
705    ///
706    /// # Example
707    ///
708    /// ```no_run
709    /// # #[cfg(all(not(feature = "stm32wl5x_cm0p"), feature = "rt"))]
710    /// unsafe { stm32wlxx_hal::adc::Adc::unmask_irq() };
711    /// ```
712    #[cfg(feature = "rt")]
713    #[inline]
714    pub unsafe fn unmask_irq() {
715        pac::NVIC::unmask(pac::Interrupt::ADC)
716    }
717
718    /// Mask the ADC IRQ in the NVIC.
719    ///
720    /// # Example
721    ///
722    /// ```no_run
723    /// # #[cfg(all(not(feature = "stm32wl5x_cm0p"), feature = "rt"))]
724    /// unsafe { stm32wlxx_hal::adc::Adc::mask_irq() }
725    /// ```
726    #[cfg(feature = "rt")]
727    #[inline]
728    pub fn mask_irq() {
729        pac::NVIC::mask(pac::Interrupt::ADC)
730    }
731
732    /// Set sample times for **all** channels.
733    ///
734    /// For each bit in the mask:
735    ///
736    /// * `0`: Sample time is set by the `sel0` argument.
737    /// * `1`: Sample time is set by the `sel1` argument.
738    ///
739    /// # Panics
740    ///
741    /// * (debug) An ADC conversion is in-progress
742    ///
743    /// # Example
744    ///
745    /// Set ADC channels [`In0`] and [`In1`] (pins [`B13`] and [`B14`]
746    /// respectively) and the internal V<sub>BAT</sub> to a sample time of
747    /// 39.5 ADC clock cycles, and set all other channels to a sample time of
748    /// 160.5 clock cycles.
749    ///
750    /// ```no_run
751    /// use stm32wlxx_hal::{
752    ///     self as hal,
753    ///     adc::{self, Adc, Ts},
754    ///     gpio::pins::{B13, B14},
755    ///     pac,
756    /// };
757    ///
758    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
759    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
760    /// adc.set_sample_times(
761    ///     B14::ADC_CH.mask() | B13::ADC_CH.mask() | adc::Ch::Vbat.mask(),
762    ///     Ts::Cyc160,
763    ///     Ts::Cyc39,
764    /// );
765    /// ```
766    ///
767    /// [`In0`]: crate::adc::Ch::In0
768    /// [`In1`]: crate::adc::Ch::In1
769    /// [`B13`]: crate::gpio::pins::B13
770    /// [`B14`]: crate::gpio::pins::B14
771    #[inline]
772    pub fn set_sample_times(&mut self, mask: u32, sel0: Ts, sel1: Ts) {
773        debug_assert!(self.adc.cr.read().adstart().is_not_active());
774        self.adc.smpr.write(|w| unsafe {
775            w.bits((mask & CH_MASK) << 8 | u32::from(sel1) << 4 | u32::from(sel0))
776        })
777    }
778
779    /// Sets all channels to the maximum sample time.
780    ///
781    /// This is a helper for testing and rapid prototyping purpose because
782    /// [`set_sample_times`](Adc::set_sample_times) is verbose.
783    ///
784    /// This method is equivalent to this:
785    ///
786    /// ```no_run
787    /// # let mut adc = unsafe { stm32wlxx_hal::adc::Adc::steal() };
788    /// use stm32wlxx_hal::adc::Ts;
789    ///
790    /// adc.set_sample_times(0, Ts::Cyc160, Ts::Cyc160);
791    /// ```
792    ///
793    /// # Example
794    ///
795    /// ```no_run
796    /// use stm32wlxx_hal::{
797    ///     adc::{self, Adc},
798    ///     pac,
799    /// };
800    ///
801    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
802    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
803    /// adc.set_max_sample_time();
804    /// ```
805    #[inline]
806    pub fn set_max_sample_time(&mut self) {
807        self.set_sample_times(0, Ts::Cyc160, Ts::Cyc160);
808    }
809
810    /// Clear interrupts.
811    ///
812    /// # Example
813    ///
814    /// Clear all interrupts.
815    ///
816    /// ```no_run
817    /// use stm32wlxx_hal::{
818    ///     adc::{self, Adc},
819    ///     pac,
820    /// };
821    ///
822    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
823    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
824    /// adc.set_isr(adc::irq::ALL);
825    /// ```
826    #[inline]
827    pub fn set_isr(&mut self, isr: u32) {
828        // saftey: reserved bits are masked and will be held at reset value
829        self.adc.isr.write(|w| unsafe { w.bits(isr & irq::ALL) })
830    }
831
832    /// Read the interrupt status.
833    ///
834    /// # Example
835    ///
836    /// Check if the ADC is ready.
837    ///
838    /// ```no_run
839    /// use stm32wlxx_hal::{
840    ///     adc::{self, Adc},
841    ///     pac,
842    /// };
843    ///
844    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
845    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
846    /// // this will be false because the ADC is not enabled
847    /// let ready: bool = Adc::isr().adrdy().is_ready();
848    /// ```
849    #[inline]
850    pub fn isr() -> pac::adc::isr::R {
851        // saftey: atomic read with no side-effects
852        unsafe { (*pac::ADC::PTR).isr.read() }
853    }
854
855    /// Enable and disable interrupts.
856    ///
857    /// # Example
858    ///
859    /// Enable all IRQs
860    ///
861    /// ```no_run
862    /// use stm32wlxx_hal::{
863    ///     adc::{self, Adc},
864    ///     pac,
865    /// };
866    ///
867    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
868    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
869    /// adc.set_ier(adc::irq::ALL);
870    /// ```
871    #[inline]
872    pub fn set_ier(&mut self, ier: u32) {
873        // saftey: reserved bits are masked and will be held at reset value
874        self.adc.ier.write(|w| unsafe { w.bits(ier & irq::ALL) })
875    }
876
877    /// Configure the channel sequencer.
878    ///
879    /// This is advanced ADC usage, most of the time you will want to use a
880    /// one of the available sample methods that will configure this.
881    ///
882    /// * [`pin`](Self::pin)
883    /// * [`temperature`](Self::temperature)
884    /// * [`vbat`](Self::vbat)
885    ///
886    /// This will not poll for completion, when this method returns the channel
887    /// configuration may not be ready.
888    ///
889    /// # Panics
890    ///
891    /// * (debug) ADC conversion is in-progress.
892    ///
893    /// # Example
894    ///
895    /// Select the ADC V<sub>BAT</sub> channel.
896    ///
897    /// ```no_run
898    /// use stm32wlxx_hal::{
899    ///     adc::{self, Adc},
900    ///     pac,
901    /// };
902    ///
903    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
904    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
905    /// adc.start_chsel(adc::Ch::Vbat.mask());
906    /// while Adc::isr().ccrdy().is_not_complete() {}
907    /// ```
908    #[inline]
909    pub fn start_chsel(&mut self, ch: u32) {
910        debug_assert!(self.adc.cr.read().adstart().is_not_active());
911        // See section 18.3.8 page 542 "Channel selection"
912        // saftey: reserved bits are masked and will be held at reset value
913        self.adc
914            .chselr0()
915            .write(|w| unsafe { w.chsel().bits(ch & CH_MASK) });
916    }
917
918    #[inline]
919    fn cfg_ch_seq(&mut self, ch: u32) {
920        self.start_chsel(ch);
921        while self.adc.isr.read().ccrdy().is_not_complete() {}
922    }
923
924    /// Start an ADC conversion.
925    ///
926    /// This is advanced ADC usage, most of the time you will want to use a
927    /// one of the available sample methods that will configure this.
928    ///
929    /// * [`pin`](Self::pin)
930    /// * [`temperature`](Self::temperature)
931    /// * [`vbat`](Self::vbat)
932    ///
933    /// This will not poll for completion, when this method returns the AD
934    /// conversion may not be complete.
935    ///
936    /// # Panics
937    ///
938    /// * (debug) ADC is not enabled
939    /// * (debug) ADC has a pending disable request
940    ///
941    /// # Example
942    ///
943    /// See [`data`](Self::data).
944    #[inline]
945    pub fn start_conversion(&mut self) {
946        debug_assert!(self.is_enabled());
947        debug_assert!(self.adc.cr.read().addis().is_not_disabling());
948        self.adc.cr.write(|w| w.adstart().start_conversion());
949    }
950
951    /// Stop an ADC conversion if there is one in-progress.
952    pub fn stop_conversion(&mut self) {
953        if self.adc.cr.read().adstart().is_active() {
954            self.adc.cr.write(|w| w.adstp().stop_conversion());
955            while self.adc.cr.read().adstp().bit_is_set() {}
956        }
957    }
958
959    /// Read the ADC conversion data.
960    ///
961    /// This is advanced ADC usage, most of the time you will want to use a
962    /// one of the available sample methods.
963    ///
964    /// * [`pin`](Self::pin)
965    /// * [`temperature`](Self::temperature)
966    /// * [`vbat`](Self::vbat)
967    ///
968    /// # Example
969    ///
970    /// Read the ADC V<sub>BAT</sub> channel.
971    ///
972    /// ```no_run
973    /// use stm32wlxx_hal::{
974    ///     adc::{self, Adc},
975    ///     pac,
976    ///     util::new_delay,
977    /// };
978    ///
979    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
980    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
981    ///
982    /// // enable the HSI16 source clock
983    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
984    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
985    ///
986    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
987    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
988    ///
989    /// // calibrate the ADC before it is enabled
990    /// adc.calibrate(&mut delay);
991    ///
992    /// // enable the ADC
993    /// adc.enable();
994    ///
995    /// // set the sample times to the maximum (160.5 ADC cycles)
996    /// adc.set_max_sample_time();
997    ///
998    /// // select the Vbat channel and poll for completion
999    /// adc.start_chsel(adc::Ch::Vbat.mask());
1000    /// while Adc::isr().ccrdy().is_not_complete() {}
1001    ///
1002    /// // start the conversion and poll for completion
1003    /// adc.start_conversion();
1004    /// while Adc::isr().eoc().is_not_complete() {}
1005    ///
1006    /// // read the ADC data
1007    /// let vbat: u16 = adc.data();
1008    /// ```
1009    #[inline]
1010    pub fn data(&self) -> u16 {
1011        self.adc.dr.read().data().bits()
1012    }
1013
1014    fn poll_data(&self) -> u16 {
1015        while self.adc.isr.read().eoc().is_not_complete() {}
1016        let data: u16 = self.data();
1017        self.adc.isr.write(|w| w.eoc().set_bit());
1018        data
1019    }
1020
1021    /// Enable the temperature sensor.
1022    ///
1023    /// You **MUST** wait for the temperature sensor to start up
1024    /// ([`TS_START_TYP`] or [`TS_START_MAX`])
1025    /// before the samples will be accurate.
1026    ///
1027    /// # Example
1028    ///
1029    /// ```no_run
1030    /// use stm32wlxx_hal::{
1031    ///     adc::{self, Adc},
1032    ///     pac, rcc,
1033    ///     util::new_delay,
1034    /// };
1035    ///
1036    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1037    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1038    ///
1039    /// // enable the HSI16 source clock
1040    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1041    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1042    ///
1043    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1044    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1045    /// adc.enable_tsen();
1046    /// // wait for the temperature sensor to startup
1047    /// delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
1048    /// ```
1049    #[inline]
1050    pub fn enable_tsen(&mut self) {
1051        self.adc.ccr.modify(|_, w| w.tsen().enabled())
1052    }
1053
1054    /// Disable the temperature sensor.
1055    #[inline]
1056    pub fn disable_tsen(&mut self) {
1057        self.adc.ccr.modify(|_, w| w.tsen().disabled())
1058    }
1059
1060    /// Returns `true` if the temperature sensor is enabled.
1061    #[inline]
1062    #[must_use]
1063    pub fn is_tsen_enabled(&mut self) -> bool {
1064        self.adc.ccr.read().tsen().is_enabled()
1065    }
1066
1067    /// Get the junction temperature.
1068    ///
1069    /// # Panics
1070    ///
1071    /// * (debug) ADC is not enabled
1072    /// * (debug) ADC has a pending disable request
1073    /// * (debug) Temperature sensor is not enabled
1074    ///
1075    /// # Sample Time
1076    ///
1077    /// You must set a sampling time with
1078    /// [`set_sample_times`](Adc::set_sample_times) greater than or equal to
1079    /// [`TS_MIN_SAMPLE`] before calling this method.
1080    /// When in doubt use the maximum sampling time, [`Ts::Cyc160`].
1081    ///
1082    /// # Calibration
1083    ///
1084    /// The temperature calibration provided on-chip appears to be for an
1085    /// uncalibrated ADC, though I can find no mention of this in the
1086    /// datasheet.
1087    ///
1088    /// If the ADC has been calibrated with [`calibrate`] the calibration offset
1089    /// will be removed from the sample.
1090    ///
1091    /// # Example
1092    ///
1093    /// ```no_run
1094    /// use stm32wlxx_hal::{
1095    ///     adc::{self, Adc},
1096    ///     pac, rcc,
1097    ///     util::new_delay,
1098    /// };
1099    ///
1100    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1101    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1102    ///
1103    /// // enable the HSI16 source clock
1104    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1105    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1106    ///
1107    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1108    ///
1109    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1110    /// adc.enable();
1111    /// adc.enable_tsen();
1112    /// delay.delay_us(adc::TS_START_MAX.as_micros() as u32);
1113    /// adc.set_max_sample_time();
1114    ///
1115    /// let tj: i16 = adc.temperature().to_integer();
1116    /// ```
1117    ///
1118    /// [`calibrate`]: crate::adc::Adc::calibrate
1119    pub fn temperature(&mut self) -> Ratio<i16> {
1120        debug_assert!(self.is_enabled());
1121        debug_assert!(self.is_tsen_enabled());
1122
1123        self.cfg_ch_seq(Ch::Vts.mask());
1124        self.start_conversion();
1125
1126        let (ts_cal1, ts_cal2): (u16, u16) = ts_cal();
1127        let ret: Ratio<i16> =
1128            Ratio::new_raw(TS_CAL_TEMP_DELTA, ts_cal2.wrapping_sub(ts_cal1) as i16);
1129
1130        let calfact: u8 = self.adc.calfact.read().calfact().bits();
1131        let ts_data: u16 = self.poll_data().saturating_add(u16::from(calfact));
1132
1133        ret * (ts_data.wrapping_sub(ts_cal1) as i16) + TS_CAL1_TEMP
1134    }
1135
1136    /// Enable the internal voltage reference.
1137    #[inline]
1138    pub fn enable_vref(&mut self) {
1139        self.adc.ccr.modify(|_, w| w.vrefen().enabled())
1140    }
1141
1142    /// Disable the internal voltage reference.
1143    #[inline]
1144    pub fn disable_vref(&mut self) {
1145        self.adc.ccr.modify(|_, w| w.vrefen().disabled())
1146    }
1147
1148    /// Returns `true` if the internal voltage reference is enabled.
1149    #[inline]
1150    #[must_use]
1151    pub fn is_vref_enabled(&mut self) -> bool {
1152        self.adc.ccr.read().vrefen().is_enabled()
1153    }
1154
1155    /// Enable oversampling.
1156    ///
1157    /// # Panics
1158    ///
1159    /// * (debug) ADC is enabled
1160    #[inline]
1161    #[cfg(not(feature = "stm32wl5x_cm0p"))]
1162    pub fn enable_oversampling(&mut self, ratio: OversampleRatio, shift: OversampleShift) {
1163        debug_assert!(!self.is_enabled());
1164        self.adc.cfgr2.modify(|_, w| {
1165            w.ovse()
1166                .enabled()
1167                .ovsr()
1168                .variant(ratio)
1169                .ovss()
1170                .variant(shift)
1171        })
1172    }
1173
1174    /// Disables oversampling.
1175    ///
1176    /// # Panics
1177    ///
1178    /// * (debug) ADC is enabled
1179    #[inline]
1180    pub fn disable_oversampling(&mut self) {
1181        debug_assert!(!self.is_enabled());
1182        self.adc.cfgr2.modify(|_, w| w.ovse().disabled())
1183    }
1184
1185    /// Returns `true` if oversampling is enabled.
1186    #[inline]
1187    #[must_use]
1188    pub fn is_oversampling_enabled(&mut self) -> bool {
1189        self.adc.cfgr2.read().ovse().is_enabled()
1190    }
1191
1192    /// Read the internal voltage reference.
1193    ///
1194    /// # Panics
1195    ///
1196    /// * (debug) ADC is not enabled
1197    /// * (debug) ADC has a pending disable request
1198    /// * (debug) Voltage reference is not enabled
1199    ///
1200    /// # Example
1201    ///
1202    /// ```no_run
1203    /// use stm32wlxx_hal::{
1204    ///     adc::{self, Adc},
1205    ///     pac, rcc,
1206    ///     util::new_delay,
1207    /// };
1208    ///
1209    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1210    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1211    ///
1212    /// // enable the HSI16 source clock
1213    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1214    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1215    ///
1216    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1217    ///
1218    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1219    /// adc.calibrate(&mut delay);
1220    /// adc.set_max_sample_time();
1221    /// adc.enable();
1222    /// adc.enable_vref();
1223    ///
1224    /// let vref: u16 = adc.vref();
1225    /// let vref_cal: u16 = adc::vref_cal();
1226    /// let error: i16 = ((vref as i16) - (vref_cal as i16)).abs();
1227    /// assert!(error < 10);
1228    /// ```
1229    pub fn vref(&mut self) -> u16 {
1230        debug_assert!(self.is_enabled());
1231        debug_assert!(self.is_vref_enabled());
1232        self.cfg_ch_seq(Ch::Vref.mask());
1233        self.start_conversion();
1234        self.poll_data()
1235    }
1236
1237    /// Sample the DAC output.
1238    ///
1239    /// The DAC must be configured to output to chip peripherals for this to
1240    /// work as expected.
1241    ///
1242    /// # Panics
1243    ///
1244    /// * (debug) ADC is not enabled
1245    /// * (debug) ADC has a pending disable request
1246    ///
1247    /// # Example
1248    ///
1249    /// ```no_run
1250    /// use stm32wlxx_hal::{
1251    ///     adc::{self, Adc},
1252    ///     dac::{Dac, ModeChip},
1253    ///     pac, rcc,
1254    ///     util::new_delay,
1255    /// };
1256    ///
1257    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1258    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1259    ///
1260    /// // enable the HSI16 source clock
1261    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1262    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1263    ///
1264    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1265    ///
1266    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1267    /// adc.calibrate(&mut delay);
1268    /// adc.set_max_sample_time();
1269    ///
1270    /// let mut dac: Dac = Dac::new(dp.DAC, &mut dp.RCC);
1271    /// dac.set_mode_chip(ModeChip::Norm);
1272    ///
1273    /// dac.setup_soft_trigger();
1274    /// dac.soft_trigger(1234);
1275    /// // should be in the same ballpark as the DAC output
1276    /// let sample: u16 = adc.dac();
1277    /// ```
1278    pub fn dac(&mut self) -> u16 {
1279        debug_assert!(self.is_enabled());
1280        self.cfg_ch_seq(Ch::Dac.mask());
1281        self.start_conversion();
1282        self.poll_data()
1283    }
1284
1285    /// Sample a GPIO pin.
1286    ///
1287    /// # Panics
1288    ///
1289    /// * (debug) ADC is not enabled
1290    /// * (debug) ADC has a pending disable request
1291    ///
1292    /// # Example
1293    ///
1294    /// ```no_run
1295    /// use stm32wlxx_hal::{
1296    ///     adc::{self, Adc},
1297    ///     gpio::{pins::B4, Analog, PortB},
1298    ///     pac, rcc,
1299    ///     util::new_delay,
1300    /// };
1301    ///
1302    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1303    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1304    ///
1305    /// // enable the HSI16 source clock
1306    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1307    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1308    ///
1309    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1310    ///
1311    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1312    /// adc.calibrate(&mut delay);
1313    /// adc.set_max_sample_time();
1314    /// adc.enable();
1315    ///
1316    /// let gpiob: PortB = PortB::split(dp.GPIOB, &mut dp.RCC);
1317    /// let b4: Analog<B4> = cortex_m::interrupt::free(|cs| Analog::new(gpiob.b4, cs));
1318    ///
1319    /// let sample: u16 = adc.pin(&b4);
1320    /// ```
1321    #[allow(unused_variables)]
1322    pub fn pin<P: gpio::sealed::AdcCh>(&mut self, pin: &gpio::Analog<P>) -> u16 {
1323        debug_assert!(self.is_enabled());
1324        self.cfg_ch_seq(P::ADC_CH.mask());
1325        self.start_conversion();
1326        self.poll_data()
1327    }
1328
1329    /// Enable V<sub>BAT</sub>.
1330    ///
1331    /// To prevent any unwanted consumption on the battery, it is recommended to
1332    /// enable the bridge divider only when needed for ADC conversion.
1333    #[inline]
1334    pub fn enable_vbat(&mut self) {
1335        self.adc.ccr.modify(|_, w| w.vbaten().enabled())
1336    }
1337
1338    /// Disable V<sub>BAT</sub>.
1339    #[inline]
1340    pub fn disable_vbat(&mut self) {
1341        self.adc.ccr.modify(|_, w| w.vbaten().disabled());
1342    }
1343
1344    /// Returns `true` if V<sub>BAT</sub> is enabled.
1345    #[inline]
1346    #[must_use]
1347    pub fn is_vbat_enabled(&self) -> bool {
1348        self.adc.ccr.read().vbaten().is_enabled()
1349    }
1350
1351    /// Sample the V<sub>BAT</sub> pin.
1352    ///
1353    /// This is internally connected to a bridge divider, the converted digital
1354    /// value is a third the V<sub>BAT</sub> voltage.
1355    ///
1356    /// # Panics
1357    ///
1358    /// * (debug) ADC is not enabled
1359    /// * (debug) ADC has a pending disable request
1360    /// * (debug) V<sub>BAT</sub> is not enabled
1361    ///
1362    /// # Example
1363    ///
1364    /// ```no_run
1365    /// use stm32wlxx_hal::{
1366    ///     self as hal,
1367    ///     adc::{self, Adc},
1368    ///     dac::{Dac, ModeChip},
1369    ///     pac, rcc,
1370    ///     util::new_delay,
1371    /// };
1372    ///
1373    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1374    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1375    ///
1376    /// // enable the HSI16 source clock
1377    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1378    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1379    ///
1380    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1381    ///
1382    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1383    /// adc.calibrate(&mut delay);
1384    ///
1385    /// adc.enable();
1386    /// adc.enable_vbat();
1387    /// adc.set_max_sample_time();
1388    /// let sample: u16 = adc.vbat();
1389    /// ```
1390    pub fn vbat(&mut self) -> u16 {
1391        debug_assert!(self.is_enabled());
1392        debug_assert!(self.is_vbat_enabled());
1393        self.cfg_ch_seq(Ch::Vbat.mask());
1394        self.start_conversion();
1395        self.poll_data()
1396    }
1397}
1398
1399// on-off control
1400// see RM0453 rev 1 section 18.3.4 page 537
1401#[cfg(not(feature = "stm32wl5x_cm0p"))]
1402impl Adc {
1403    /// Returns `true` if the ADC is enabled.
1404    ///
1405    /// # Example
1406    ///
1407    /// ```no_run
1408    /// use stm32wlxx_hal::{
1409    ///     adc::{self, Adc},
1410    ///     pac,
1411    /// };
1412    ///
1413    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1414    ///
1415    /// // enable the HSI16 source clock
1416    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1417    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1418    ///
1419    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1420    /// assert_eq!(adc.is_enabled(), false);
1421    /// ```
1422    #[inline]
1423    #[must_use]
1424    pub fn is_enabled(&self) -> bool {
1425        self.adc.cr.read().aden().bit_is_set()
1426    }
1427
1428    /// Returns `true` if an ADC disable command is in-progress.
1429    #[inline]
1430    #[must_use]
1431    pub fn disable_in_progress(&self) -> bool {
1432        self.adc.cr.read().addis().bit_is_set()
1433    }
1434
1435    /// Returns `true` if the ADC is disabled, and there is no disable command
1436    /// in-progress.
1437    ///
1438    /// # Example
1439    ///
1440    /// ```no_run
1441    /// use stm32wlxx_hal::{
1442    ///     adc::{self, Adc},
1443    ///     pac,
1444    /// };
1445    ///
1446    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1447    ///
1448    /// // enable the HSI16 source clock
1449    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1450    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1451    ///
1452    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1453    /// assert_eq!(adc.is_disabled(), true);
1454    /// ```
1455    #[inline]
1456    #[must_use]
1457    pub fn is_disabled(&self) -> bool {
1458        let cr = self.adc.cr.read();
1459        cr.aden().bit_is_clear() && cr.addis().bit_is_clear()
1460    }
1461
1462    /// Start the ADC enable procedure.
1463    ///
1464    /// This is advanced ADC usage, most of the time you will want to use
1465    /// [`enable`](Self::enable).
1466    ///
1467    /// This will not poll for completion, when this method returns the ADC
1468    /// may not be enabled.
1469    ///
1470    /// The method returns `true` if the caller function should poll for
1471    /// completion (the ADC was not already enabled),
1472    /// if the ADC was already enabled and the ADRDY interrupt was cleared then
1473    /// the ADRDY bit will **not** be set again after calling this method
1474    /// which can lead to polling loops that will never terminate.
1475    ///
1476    /// # Example
1477    ///
1478    /// ```no_run
1479    /// use stm32wlxx_hal::{
1480    ///     adc::{self, Adc},
1481    ///     pac,
1482    /// };
1483    ///
1484    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1485    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1486    /// if adc.start_enable() {
1487    ///     while Adc::isr().adrdy().is_not_ready() {}
1488    /// }
1489    /// ```
1490    #[inline]
1491    #[must_use = "the return value indicates if you should wait for completion"]
1492    pub fn start_enable(&mut self) -> bool {
1493        if self.adc.cr.read().aden().is_disabled() {
1494            self.adc.isr.write(|w| w.adrdy().set_bit());
1495            self.adc.cr.write(|w| w.aden().set_bit());
1496            true
1497        } else {
1498            false
1499        }
1500    }
1501
1502    /// Enable the ADC and poll for completion.
1503    ///
1504    /// # Example
1505    ///
1506    /// ```no_run
1507    /// use stm32wlxx_hal::{
1508    ///     adc::{self, Adc},
1509    ///     pac,
1510    /// };
1511    ///
1512    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1513    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1514    /// adc.enable();
1515    /// ```
1516    #[inline]
1517    pub fn enable(&mut self) {
1518        if self.start_enable() {
1519            while self.adc.isr.read().adrdy().is_not_ready() {}
1520        }
1521    }
1522
1523    /// Start the ADC disable procedure.
1524    ///
1525    /// This is advanced ADC usage, most of the time you will want to use
1526    /// [`disable`](Self::disable).
1527    ///
1528    /// This will not poll for completion, when this function returns the ADC
1529    /// may not be disabled.
1530    ///
1531    /// This will stop any conversions in-progress.
1532    ///
1533    /// The ADC takes about 20 CPU cycles to disable with a 48MHz sysclk and
1534    /// the ADC on the 16MHz HSI clock.
1535    ///
1536    /// # Example
1537    ///
1538    /// ```no_run
1539    /// use stm32wlxx_hal::{
1540    ///     adc::{self, Adc},
1541    ///     pac,
1542    /// };
1543    ///
1544    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1545    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1546    /// adc.enable();
1547    /// // ... use ADC
1548    /// adc.start_disable();
1549    /// while !adc.is_disabled() {}
1550    /// ```
1551    pub fn start_disable(&mut self) {
1552        // RM0453 rev 1 section 18.3.4 page 537 ADC on-off control
1553        // 1. Check that ADSTART = 0 in the ADC_CR register to ensure that no
1554        //    conversion is ongoing.
1555        //    If required, stop any ongoing conversion by writing 1 to the
1556        //    ADSTP bit in the ADC_CR register and waiting until this bit is
1557        //    read at 0.
1558        // 2. Set ADDIS = 1 in the ADC_CR register.
1559        // 3. If required by the application, wait until ADEN = 0 in the ADC_CR
1560        //    register, indicating that the ADC is fully disabled
1561        //    (ADDIS is automatically reset once ADEN = 0).
1562        // 4. Clear the ADRDY bit in ADC_ISR register by programming this bit to 1
1563        //    (optional).
1564        self.stop_conversion();
1565        // Setting ADDIS to `1` is only effective when ADEN = 1 and ADSTART = 0
1566        // (which ensures that no conversion is ongoing)
1567        if self.adc.cr.read().aden().bit_is_set() {
1568            self.adc.cr.write(|w| w.addis().set_bit());
1569        }
1570    }
1571
1572    /// Disable the ADC and poll for completion.
1573    ///
1574    /// # Example
1575    ///
1576    /// ```no_run
1577    /// use stm32wlxx_hal::{
1578    ///     adc::{self, Adc},
1579    ///     pac,
1580    /// };
1581    ///
1582    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1583    /// let mut adc = Adc::new(dp.ADC, adc::Clk::PClkDiv4, &mut dp.RCC);
1584    /// adc.enable();
1585    /// // ... use ADC
1586    /// adc.disable();
1587    /// ```
1588    pub fn disable(&mut self) {
1589        self.start_disable();
1590        while !self.is_disabled() {}
1591    }
1592}
1593
1594// calibration related methods
1595// see RM0453 rev 1 section 18.3.3 page 536
1596#[cfg(not(feature = "stm32wl5x_cm0p"))]
1597impl Adc {
1598    /// Calibrate the ADC for additional accuracy.
1599    ///
1600    /// Calibration should be performed before starting A/D conversion.
1601    /// It removes the offset error which may vary from chip to chip due to
1602    /// process variation.
1603    ///
1604    /// The calibration factor is lost in the following cases:
1605    /// * The power supply is removed from the ADC
1606    ///   (for example when entering STANDBY or VBAT mode)
1607    /// * The ADC peripheral is reset.
1608    ///
1609    /// This will disable the ADC if it is not already disabled.
1610    ///
1611    /// This function is the simple way to calibrate the ADC, you can use
1612    /// these methods to achieve the same results if you desire finer controls:
1613    ///
1614    /// * [`enable_vreg`](Self::enable_vreg)
1615    /// * A delay function
1616    /// * [`start_calibrate`](Self::start_calibrate)
1617    /// * [`set_ier`](Self::set_ier) (optional)
1618    /// * [`Adc::isr`]
1619    ///
1620    /// # Example
1621    ///
1622    /// ```no_run
1623    /// use stm32wlxx_hal::{
1624    ///     adc::{self, Adc},
1625    ///     pac, rcc,
1626    ///     util::new_delay,
1627    /// };
1628    ///
1629    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1630    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1631    ///
1632    /// // enable the HSI16 source clock
1633    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1634    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1635    ///
1636    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1637    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1638    /// adc.calibrate(&mut delay);
1639    /// ```
1640    pub fn calibrate<D: DelayUs<u8>>(&mut self, delay: &mut D) {
1641        self.enable_vreg();
1642
1643        // voltage regulator output is available after T_ADCVREG_SETUP
1644        delay.delay_us(T_ADCVREG_SETUP_MICROS);
1645
1646        self.start_calibrate();
1647
1648        // takes 401 cycles at 48MHz sysclk, ADC at 16MHz with HSI
1649        while self.adc.cr.read().adcal().is_calibrating() {}
1650        self.adc.isr.write(|w| w.eocal().set_bit());
1651    }
1652
1653    /// Enable the ADC voltage regulator for calibration.
1654    ///
1655    /// This is advanced ADC usage, most of the time you will want to use
1656    /// [`calibrate`](Self::calibrate).
1657    ///
1658    /// This will disable the ADC and DMA request generation if not already
1659    /// disabled.
1660    ///
1661    /// You **MUST** wait [`T_ADCVREG_SETUP`] before the voltage regulator
1662    /// output is available.  This delay is not performed for you.
1663    ///
1664    /// # Example
1665    ///
1666    /// ```no_run
1667    /// use stm32wlxx_hal::{
1668    ///     adc::{self, Adc},
1669    ///     pac, rcc,
1670    ///     util::new_delay,
1671    /// };
1672    ///
1673    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1674    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1675    ///
1676    /// // enable the HSI16 source clock
1677    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1678    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1679    ///
1680    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1681    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1682    /// adc.enable_vreg();
1683    /// delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
1684    /// ```
1685    pub fn enable_vreg(&mut self) {
1686        // RM0453 rev 1 section 18.3.3 page 536 Software calibration procedure
1687        // 1. Ensure that ADEN = 0, ADVREGEN = 1 and DMAEN = 0.
1688        // 2. Set ADCAL = 1.
1689        // 3. Wait until ADCAL = 0 (or until EOCAL = 1).
1690        //    This can be handled by interrupt if the interrupt is enabled by
1691        //    setting the EOCALIE bit in the ADC_IER register
1692        // 4. The calibration factor can be read from bits 6:0 of ADC_DR or
1693        //    ADC_CALFACT registers.
1694
1695        // takes appx 55 cycles when already disabled
1696        self.disable();
1697
1698        // enable the voltage regulator as soon as possible to start the
1699        // countdown on the regulator setup time
1700        // this is a write because all other fields must be zero
1701        self.adc.cr.write(|w| w.advregen().enabled());
1702        // disable DMA per the calibration procedure
1703        self.adc.cfgr1.modify(|_, w| w.dmaen().clear_bit());
1704    }
1705
1706    /// Disable the ADC voltage regulator.
1707    ///
1708    /// # Panics
1709    ///
1710    /// * (debug) ADC is enabled
1711    #[inline]
1712    pub fn disable_vreg(&mut self) {
1713        debug_assert!(self.is_disabled());
1714        self.adc.cr.write(|w| w.advregen().disabled());
1715    }
1716
1717    /// Start the ADC calibration.
1718    ///
1719    /// This is advanced ADC usage, most of the time you will want to use
1720    /// [`calibrate`](Self::calibrate).
1721    ///
1722    /// When this function returns the ADC calibration has started, but
1723    /// may not have finished.
1724    /// Check if the ADC calibration has finished with [`Adc::isr`].
1725    ///
1726    /// # Panics
1727    ///
1728    /// * (debug) ADC is enabled.
1729    /// * (debug) ADC voltage regulator is not enabled.
1730    ///
1731    /// # Example
1732    ///
1733    /// ```no_run
1734    /// use stm32wlxx_hal::{
1735    ///     adc::{self, Adc},
1736    ///     pac, rcc,
1737    ///     util::new_delay,
1738    /// };
1739    ///
1740    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1741    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1742    ///
1743    /// // enable the HSI16 source clock
1744    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1745    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1746    ///
1747    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1748    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1749    ///
1750    /// adc.enable_vreg();
1751    /// delay.delay_us(u32::from(adc::T_ADCVREG_SETUP_MICROS));
1752    /// adc.start_calibrate();
1753    /// // datasheet says this takes 82 ADC clock cycles
1754    /// // my measurements are closer to 120 ADC clock cycles
1755    /// while Adc::isr().eocal().is_not_complete() {}
1756    /// ```
1757    #[inline]
1758    pub fn start_calibrate(&mut self) {
1759        debug_assert!(self.adc.cr.read().advregen().is_enabled());
1760        debug_assert!(self.is_disabled());
1761        self.adc
1762            .cr
1763            .write(|w| w.adcal().start_calibration().advregen().enabled());
1764    }
1765
1766    /// Get the ADC calibration factor.
1767    ///
1768    /// # Example
1769    ///
1770    /// See [`force_cal`](Self::force_cal).
1771    #[inline]
1772    pub fn calfact(&self) -> u8 {
1773        self.adc.calfact.read().calfact().bits()
1774    }
1775
1776    /// Force the ADC calibration.
1777    ///
1778    /// The calibration factor is lost each time power is removed from the ADC
1779    /// (for example when entering standby or V<sub>BAT</sub> mode)
1780    /// It is possible to save and restore the calibration factor with firmware
1781    /// to save time when re-starting the ADC (as long as temperature and
1782    /// voltage are stable during the ADC power-down).
1783    ///
1784    /// # Panics
1785    ///
1786    /// * (debug) ADC is not enabled
1787    /// * (debug) ADC conversion is in-progress
1788    ///
1789    /// # Example
1790    ///
1791    /// ```no_run
1792    /// use stm32wlxx_hal::{
1793    ///     adc::{self, Adc},
1794    ///     pac, rcc,
1795    ///     util::new_delay,
1796    /// };
1797    ///
1798    /// let mut dp: pac::Peripherals = pac::Peripherals::take().unwrap();
1799    /// let cp: pac::CorePeripherals = pac::CorePeripherals::take().unwrap();
1800    ///
1801    /// // enable the HSI16 source clock
1802    /// dp.RCC.cr.modify(|_, w| w.hsion().set_bit());
1803    /// while dp.RCC.cr.read().hsirdy().is_not_ready() {}
1804    ///
1805    /// let mut delay = new_delay(cp.SYST, &dp.RCC);
1806    /// let mut adc = Adc::new(dp.ADC, adc::Clk::RccHsi, &mut dp.RCC);
1807    /// adc.calibrate(&mut delay);
1808    ///
1809    /// // save the calibration factor
1810    /// let calfact: u8 = adc.calfact();
1811    ///
1812    /// // restore the calibration
1813    /// adc.enable(); // ADC must be enabled to restore the calibration
1814    /// adc.force_cal(calfact);
1815    /// ```
1816    #[inline]
1817    pub fn force_cal(&mut self, calfact: u8) {
1818        debug_assert!(self.is_enabled());
1819        debug_assert!(self.adc.cr.read().adstart().bit_is_clear());
1820        self.adc.calfact.write(|w| w.calfact().bits(calfact))
1821    }
1822}