stm32f3xx_hal/
adc.rs

1//! # Analog to Digital Converter.
2//!
3//! ## Examples
4//!
5//! Check out [examples/adc.rs].
6//!
7//! It can be built for the `STM32F3Discovery` running
8//! `cargo build --example adc --features=stm32f303xc`
9//!
10//! [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs
11
12use core::ops::Deref;
13use core::{convert::TryInto, marker::PhantomData};
14
15use cortex_m::asm;
16use embedded_hal::adc::Channel;
17
18#[track_caller]
19unsafe fn unreachable_unchecked() -> ! {
20    #[cfg(debug_assertions)]
21    crate::unreachable!();
22    #[cfg(not(debug_assertions))]
23    #[allow(unused_unsafe)]
24    unsafe {
25        core::hint::unreachable_unchecked();
26    }
27}
28
29use crate::{
30    pac::{self, adc1, Interrupt},
31    rcc::{Clocks, Enable, AHB},
32    time::{duration::Microseconds, fixed_point::FixedPoint, rate::Hertz},
33    Switch,
34};
35
36use crate::pac::{adc1_2, adc1_2::ccr::CKMODE_A};
37
38#[cfg(feature = "enumset")]
39use enumset::{EnumSet, EnumSetType};
40
41const MAX_ADVREGEN_STARTUP: Microseconds = Microseconds(10);
42
43/// Internal voltage reference, which is also used for calibration.
44#[derive(Debug)]
45#[cfg_attr(feature = "defmt", derive(defmt::Format))]
46#[doc(alias = "V_REFINT")]
47pub struct VoltageInternalReference<ADC> {
48    _adc: PhantomData<ADC>,
49}
50
51/// Battery voltage signal, used for monitoring the battery (if used)
52#[derive(Debug)]
53#[cfg_attr(feature = "defmt", derive(defmt::Format))]
54#[doc(alias = "V_BAT")]
55pub struct VoltageBattery<ADC> {
56    _adc: PhantomData<ADC>,
57}
58
59/// Internal core temperature signal
60#[derive(Debug)]
61#[cfg_attr(feature = "defmt", derive(defmt::Format))]
62#[doc(alias = "V_TS")]
63pub struct TemperatureSensor<ADC> {
64    _adc: PhantomData<ADC>,
65}
66
67// TODO(Sh3Rm4n): As soon as OPAMPs are implemented
68// /// Reference Voltage for the Operational Amplifier 2
69// #[derive(Debug)]
70// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
71// #[doc(alias = "V_REFOPAMP2")]
72// pub struct VoltageOpAmp2Reference(pub(crate) ());
73//
74// /// Reference Voltage for the Operational Amplifier 3
75// #[derive(Debug)]
76// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
77// #[doc(alias = "V_REFOPAMP3")]
78// #[cfg(all(
79//     feature = "svd-f303",
80//     any(feature = "gpio-f303", feature = "gpio-f303e")
81// ))]
82// pub struct VoltageOpAmp3Reference(pub(crate) ());
83//
84// /// Reference Voltage for the Operational Amplifier 4
85// #[derive(Debug)]
86// #[cfg_attr(feature = "defmt", derive(defmt::Format))]
87// #[doc(alias = "V_REFOPAMP4")]
88// #[cfg(all(
89//     feature = "svd-f303",
90//     any(feature = "gpio-f303", feature = "gpio-f303e")
91// ))]
92// pub struct VoltageOpAmp4Reference(pub(crate) ());
93
94/// The common ADC peripheral, which is shared between different concrete ADC peripheral.
95///
96/// For example [`CommonAdc<ADC1_2>`] shares control over [`pac::ADC1`] and [`pac::ADC2`].
97///
98/// This peripheral can control different parts, like enabling internal sensors (like temperature sensor)
99/// or enable dual channel mode (which is not supported yet.)
100#[allow(clippy::module_name_repetitions)]
101pub struct CommonAdc<ADC> {
102    reg: ADC,
103}
104
105impl<ADC> CommonAdc<ADC>
106where
107    ADC: CommonInstance,
108{
109    /// Create a [`CommonAdc`] instance, consuming the [`pac`]'s ADC (e.g. [`pac::ADC1_2`].
110    pub fn new(mut common_adc: ADC, clocks: &Clocks, ahb: &mut AHB) -> Self {
111        common_adc.enable_clock(clocks, ahb);
112
113        Self { reg: common_adc }
114    }
115
116    /// Get access to the underlying register block.
117    ///
118    /// # Safety
119    ///
120    /// This function is not _memory_ unsafe per se, but does not guarantee
121    /// anything about assumptions of invariants made in this implementation.
122    ///
123    /// Changing specific options can lead to un-expected behavior and nothing
124    /// is guaranteed.
125    pub unsafe fn peripheral(&mut self) -> &mut ADC {
126        &mut self.reg
127    }
128}
129
130impl<ADC> CommonAdc<ADC>
131where
132    ADC: CommonInstance + crate::rcc::Enable,
133{
134    /// Releases the common ADC peripheral
135    pub fn free(self, _adcs: &<ADC as CommonInstance>::Childs) -> ADC {
136        critical_section::with(|_| {
137            // SAFETY: Guaranteed to be the only instance left, which has control over the
138            // `ADC`perpherals, and criticala section ensure that no race condition happens
139            // on the `Bus` peripheral.
140            unsafe { ADC::disable_unchecked() };
141        });
142        self.reg
143    }
144}
145
146/// Interrupt and status events.
147///
148/// All events can be cleared by [`Adc::clear_event`] or [`Adc::clear_events`].
149/// Some events are also cleared on other conditions.
150#[derive(Debug)]
151#[cfg_attr(feature = "defmt", derive(defmt::Format))]
152#[cfg_attr(feature = "enumset", derive(EnumSetType))]
153#[cfg_attr(not(feature = "enumset"), derive(Copy, Clone, PartialEq, Eq))]
154#[non_exhaustive]
155pub enum Event {
156    /// This event is set by hardware after the ADC has been enabled.
157    /// and when the ADC reaches a state where it is ready to accept conversion requests.
158    #[doc(alias = "ADRDY")]
159    AdcReady,
160    /// This event is set by hardware during the conversion of any channel (only for regular channels),
161    /// at the end of the sampling phase.
162    #[doc(alias = "EOSMP")]
163    EndOfSamplingPhase,
164    /// This event is set by hardware at the end of each regular conversion of a channel
165    /// when a new data is available in the data register ([`Adc::data_register`]).
166    #[doc(alias = "EOC")]
167    EndOfConversion,
168    /// This event is set by hardware at the end of the conversions of a regular sequence of channels.
169    ///
170    /// When this event will occur, will depend on the [`Adc::sequence_length`] or
171    /// [`config::ConversionMode`].
172    #[doc(alias = "EOS")]
173    EndOfSequence,
174    /// This event is set by hardware when an overrun occurs on a regular channel, meaning that a new
175    /// conversion has completed while the [`Event::EndOfConversion`] flag was already set.
176    ///
177    /// # Note
178    ///
179    /// If [`OverrunMode::Preserve`] is configured and DMA is enabled ([`config::DmaMode`]),
180    /// the DMA transfer requests are blocked until the event is cleared. ([`Adc::clear_event`])
181    ///
182    /// [`OverrunMode::Preserve`]: `config::OverrunMode::Preserve`
183    #[doc(alias = "OVR")]
184    Overrun,
185    /// This event is set by hardware at the end of each injected conversion of a channel
186    /// when a new data is available in the corresponding ADCx_JDRy register.
187    #[doc(alias = "JEOC")]
188    InjectedChannelEndOfConversion,
189    /// This event is set by hardware at the end of the conversions of all injected channels in the group.
190    #[doc(alias = "JEOS")]
191    InjectedChannelEndOfSequence,
192    /// This event is set by hardware when the converted voltage crosses the values programmed
193    /// in the fields `LT1[11:0]` and `HT1[11:0]` of ADCx_TR1 register.
194    // TODO(Sh3Rm4n): Improve doc
195    #[doc(alias = "AWD1")]
196    AnalogWatchdog1,
197    /// This event is set by hardware when the converted voltage crosses the values programmed
198    /// in the fields `LT2[7:0]` and `HT2[7:0]` of ADCx_TR2 register.
199    // TODO(Sh3Rm4n): Improve doc
200    #[doc(alias = "AWD2")]
201    AnalogWatchdog2,
202    /// This event is set by hardware when the converted voltage crosses the values programmed
203    /// in the fields `LT3[7:0]` and `HT3[7:0]` of ADCx_TR3 register. I
204    // TODO(Sh3Rm4n): Improve doc
205    #[doc(alias = "AWD3")]
206    AnalogWatchdog3,
207    /// This event is set by hardware when an Overflow of the Injected Queue of Context occurs.
208    #[doc(alias = "JQOVF")]
209    InjectedContextQueueOverfow,
210}
211
212/// Analog Digital Converter Peripheral
213#[derive(Debug)]
214pub struct Adc<ADC, State = Enabled> {
215    /// ADC Register
216    reg: ADC,
217    /// [`Enabled`] / [`Disabled`] type state
218    state: PhantomData<State>,
219}
220
221/// Implements [`Channel`] for all pins
222pub mod channel;
223
224pub mod config;
225
226/// Implements [`Channel`] trait for special pins
227macro_rules! sp_channel {
228    ([$(($Pin:ident, $ADC:ident, $chan:expr)),+ $(,)*]) => {
229        $(
230            impl Channel<pac::$ADC> for $Pin<<pac::$ADC as Instance>::SharedInstance> {
231                type ID = channel::Id;
232                fn channel() -> Self::ID { $chan }
233            }
234        )+
235    };
236}
237
238macro_rules! sp_pins {
239    ([$(($Pin:ident, $en:ident)),+ $(,)*]) => {
240        $(
241            impl<Common> $Pin<Common>
242            where
243                Common: CommonInstance,
244            {
245                /// Creating a type associated with the special ADC sensor, which
246                /// implements the [`embedded_hal::adc::Channel`] trait.
247                ///
248                /// # Example
249                ///
250                /// Imagine you'd like to measure the core temperature via `ADC1`.
251                ///
252                /// In that case this function takes both the common ADC, e.g. [`pac::ADC1_2`], as
253                /// well as both associated ADCs, e.g. [`pac::ADC1`] & [`pac::ADC2`] to ensure,
254                /// that these ADCs are still disabled, because the internal ADC sensor can only be
255                /// enabled, if these ADCs are disabled, see [RM0316] 15.6.2.
256                ///
257                /// Code example can be seen in [examples/adc.rs].
258                ///
259                /// [examples/adc.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.10.0/examples/adc.rs
260                /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00094349.pdf
261                // FIXME(Sh3Rm4n): Soundness hole: Still mutliple sensor objects can be created.
262                // An idea might be to split out the sensors from CommonAdc similar to the
263                // DevicePeripheral.
264                #[inline]
265                pub fn new(
266                    // Does this now expect CommonAdc or pac::ADC1_2?
267                    common_adc: &mut CommonAdc<Common>,
268                    // &mut adc ensures, that adc is disabled and with the shard instance the reference can be
269                    // configured / enabled.
270                    // As of RM0316 15.6.2: Software is allowed to write this bit only when the ADCs are
271                    // disabled (ADCAL=0, JADSTART=0, ADSTART=0, ADSTP=0, ADDIS=0 and ADEN=0)
272                    // TODO(Sh3Rm4n): Childs is currently a tuple of the raw ADCs but could also be
273                    // (Adc<ADC1, Disabled>, Adc<ADC2, Disabled>)
274                    _adcs: &mut <Common as CommonInstance>::Childs,
275                ) -> Self {
276                    common_adc.reg.ccr.modify(|_, w| w.$en().enabled());
277                    Self { _adc: PhantomData }
278                }
279            }
280        )+
281    };
282}
283
284// See RM0316 table 86.
285sp_channel!([
286    (TemperatureSensor, ADC1, channel::Id::Sixteen),
287    (VoltageBattery, ADC1, channel::Id::Seventeen),
288    (VoltageInternalReference, ADC1, channel::Id::Eighteen),
289]);
290
291#[cfg(any(feature = "svd-f302", feature = "svd-f303", feature = "svd-f3x4"))]
292sp_channel!([(VoltageInternalReference, ADC2, channel::Id::Eighteen),]);
293
294#[cfg(feature = "svd-f303")]
295sp_channel!([
296    (VoltageInternalReference, ADC3, channel::Id::Eighteen),
297    (VoltageInternalReference, ADC4, channel::Id::Eighteen),
298]);
299
300sp_pins!([
301    (TemperatureSensor, tsen),
302    (VoltageBattery, vbaten),
303    (VoltageInternalReference, vrefen),
304]);
305
306impl<ADC> Adc<ADC, Enabled>
307where
308    ADC: Instance,
309{
310    /// Initialize a new ADC peripheral.
311    ///
312    /// Enables the clock, performs a calibration and enables the ADC.
313    #[inline]
314    pub fn new(
315        adc: ADC,
316        config: impl Into<config::Config>,
317        clocks: &Clocks,
318        common_adc: &CommonAdc<<ADC as Instance>::SharedInstance>,
319    ) -> Adc<ADC, Enabled> {
320        let mut adc = Adc::new_disabled(adc);
321        let config: config::Config = config.into();
322        adc.set_config(config);
323        adc.calibrate(clocks, common_adc);
324        adc.into_enabled()
325    }
326
327    /// Returns the current sample stored in the ADC data register
328    ///
329    /// At the end of each regular conversion channel (when [`Event::EndOfConversion`] event occurs),
330    /// the result of the converted data is stored into the data register.
331    ///
332    /// # Note
333    ///
334    /// This function does no error handling or configuration of the
335    /// peripheral. The value read might be invalid, because the device
336    /// is not configured accordingly..
337    ///
338    /// ## Embedded HAL
339    ///
340    /// There is a more managed way to read from the adc via the [`embedded_hal::adc::OneShot`] trait.
341    #[doc(alias = "ADC_DR")]
342    #[must_use]
343    #[inline]
344    pub fn data_register(&self) -> u16 {
345        self.reg.dr.read().rdata().bits()
346    }
347
348    /// Returns the address of the ADC data register. Primarily useful for configuring DMA.
349    // TODO(Sh3Rm4n): Check against and integrate to DMA
350    #[inline]
351    pub fn data_register_address(&self) -> u32 {
352        core::ptr::addr_of!(self.reg.dr) as u32
353    }
354
355    /// Manually start a conversion sequence.
356    ///
357    /// * To automatically start a conversion consider setting [`Adc::set_external_trigger`].
358    /// * The conversion mode is configured via [`Adc::set_conversion_mode`].
359    #[inline]
360    pub fn start_conversion(&mut self) {
361        self.reg.cr.modify(|_, w| w.adstart().start_conversion());
362    }
363
364    /// Configure and convert the [`Adc`] instance into [`OneShot`] mode.
365    #[inline]
366    #[must_use]
367    pub fn into_oneshot(mut self) -> Adc<ADC, OneShot> {
368        self.stop_conversion();
369        while self.is_conversion_ongoing() {}
370        self.set_conversion_mode(config::ConversionMode::Single);
371        self.set_dma_mode(config::DmaMode::Disabled);
372        self.set_external_trigger(None);
373
374        self.disable_interrupt(Event::EndOfConversion);
375        self.disable_interrupt(Event::EndOfSequence);
376
377        self.set_sequence_length(config::Sequence::One);
378
379        Adc {
380            reg: self.reg,
381            state: PhantomData,
382        }
383    }
384
385    /// Disables the peripheral and convert it into [`Disabled`] mode.
386    #[inline]
387    #[must_use]
388    pub fn into_disabled(self) -> Adc<ADC, Disabled> {
389        // Software procedure to disable the ADC according to [RM0316]: 15.3.9
390
391        // 1. Check that both ADSTART=0 and JADSTART=0 to ensure that no conversion is ongoing. If
392        //    required, stop any regular and injected conversion ongoing by setting ADSTP=1 and
393        //    JADSTP=1 and then wait until ADSTP=0 and JADSTP=0
394        if self.reg.cr.read().aden().bit()
395            && (self.reg.cr.read().adstart().bit() || self.reg.cr.read().jadstart().bit())
396        {
397            self.reg.cr.modify(|_, w| w.adstp().stop_conversion());
398            // In auto-injection mode (JAUTO=1), setting ADSTP bit aborts both
399            // regular and injected conversions (do not use JADSTP)
400            if !self.reg.cfgr.read().jauto().is_enabled() {
401                self.reg.cr.modify(|_, w| w.jadstp().stop_conversion());
402            }
403            while self.reg.cr.read().adstp().bit() || self.reg.cr.read().jadstp().bit() {}
404        }
405
406        // Software is allowed to set ADDIS only when ADEN=1 and both ADSTART=0
407        // and JADSTART=0 (which ensures that no conversion is ongoing)
408        if self.reg.cr.read().aden().is_enabled() {
409            // 2. Disable ADC
410            // TODO(Sh3Rm4n): Use w.aaddis().disable() once https://github.com/stm32-rs/stm32-rs/pull/699 is merged
411            self.reg.cr.modify(|_, w| w.addis().set_bit());
412            // 3. Wait for ADC being disabled
413            while self.reg.cr.read().aden().is_enabled() {}
414        }
415
416        Adc {
417            reg: self.reg,
418            state: PhantomData,
419        }
420    }
421
422    /// Releases the ADC peripheral
423    #[inline]
424    pub fn free(self) -> ADC {
425        self.into_disabled().reg
426    }
427}
428
429impl<ADC> Adc<ADC, Disabled>
430where
431    ADC: Instance,
432{
433    /// Create an [`Adc`] instance in [`Disabled`] mode.
434    ///
435    /// In this mode, the peripheral is not yet enabled, and neither guaranteed to be calibrated.
436    /// To convert the [`Adc`] peripheral into [`Enabled`] mode, you can do the following:
437    ///
438    /// ```
439    /// let clocks = rcc.cfgr.freeze(/*... */);
440    /// let adc_common = CommonAdc::new(/*...*/);
441    ///
442    /// let mut adc = adc::Adc::new_disabled(dp.ADC1);
443    /// adc.calibrate(&clocks, &adc_common); // Optional
444    /// adc.set_config(adc::config::Config::default()); // Optional
445    /// let adc: Adc<ADC1, Enabled> = adc2.into_enabled();
446    /// ```
447    #[inline]
448    pub fn new_disabled(adc: ADC) -> Self {
449        Self {
450            reg: adc,
451            state: PhantomData,
452        }
453    }
454
455    /// Convert the [`Adc`] into [`Enabled`] mode.
456    #[inline]
457    #[must_use]
458    pub fn into_enabled(self) -> Adc<ADC, Enabled> {
459        // Enabled According to [RM0316] 15.3.9.
460        // This check assumes, that the ADC was enabled before and it was waited until
461        // ADRDY=1 was set.
462        // This assumption is true, if the peripheral was initially enabled through
463        // this method.
464        if !self.reg.cr.read().aden().is_enabled() {
465            // Set ADEN=1
466            self.reg.cr.modify(|_, w| w.aden().enabled());
467            // Wait until ADRDY=1 (ADRDY is set after the ADC startup time). This can be
468            // done using the associated interrupt (setting ADRDYIE=1).
469            while self.reg.isr.read().adrdy().is_not_ready() {}
470        }
471
472        Adc {
473            reg: self.reg,
474            state: PhantomData,
475        }
476    }
477
478    /// Calibrate according to [RM0316] 15.3.8
479    ///
480    /// The internal analog calibration is lost each time the power of the ADC is removed.
481    ///
482    /// # Note
483    ///
484    /// The ADC is calibrated, when created via [`Adc::new`], so immidiate calibration after that
485    /// should not be needed.
486    ///
487    /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00094349.pdf
488    // TODO(Sh3Rm4n): CALFACT to save the calibration state
489    #[inline]
490    pub fn calibrate(
491        &mut self,
492        clocks: &Clocks,
493        common_adc: &CommonAdc<<ADC as Instance>::SharedInstance>,
494        // TODO(Sh3Rm4n): Would about concurrent calibrations between related ADCs?
495        // int_ref: &mut VoltageInternalReference<ADC>,
496    ) {
497        self.configure_voltage_regulator(Switch::On, clocks);
498
499        self.reg
500            .cr
501            .modify(|_, w| w.adcaldif().single_ended().adcal().calibration());
502
503        while self.reg.cr.read().adcal().is_calibration() {}
504
505        // ADEN bit cannot be set during ADCAL=1 and 4 ADC clock cycle after the ADCAL bit is
506        // cleared by hardware
507        let adc_cycles = 4;
508        let frequency = common_adc
509            .reg
510            .clock(clocks)
511            .unwrap_or_else(|| clocks.sysclk());
512        let cpu_cycles = adc_cycles * clocks.sysclk().0 / frequency.0;
513        asm::delay(cpu_cycles);
514
515        // When the internal voltage regulator is disabled, the internal analog calibration is kept
516        self.configure_voltage_regulator(Switch::Off, clocks);
517    }
518
519    /// Enable the interal voltage generator Blocks until regulator is enabled.
520    fn configure_voltage_regulator(&mut self, toggle: impl Into<Switch>, clocks: &Clocks) {
521        let already_on = self.reg.cr.read().advregen().is_enabled();
522        let toggle = toggle.into();
523        self.reg.cr.modify(|_, w| w.advregen().intermediate());
524        self.reg.cr.modify(|_, w| {
525            w.advregen().variant(match toggle {
526                Switch::On => adc1::cr::ADVREGEN_A::Enabled,
527                Switch::Off => adc1::cr::ADVREGEN_A::Disabled,
528            })
529        });
530        if toggle == Switch::On && !already_on {
531            let wait = MAX_ADVREGEN_STARTUP.integer()
532                * clocks.sysclk().integer()
533                * <Microseconds as FixedPoint>::SCALING_FACTOR;
534            asm::delay(wait);
535        }
536    }
537
538    /// Releases the ADC peripheral
539    #[inline]
540    pub fn free(self) -> ADC {
541        self.reg
542    }
543}
544
545impl<ADC, State> Adc<ADC, State>
546where
547    ADC: Instance,
548{
549    /// Get the current overrun mode.
550    #[inline]
551    pub fn overrun_mode(&self) -> config::OverrunMode {
552        self.reg.cfgr.read().ovrmod().variant().into()
553    }
554
555    /// Get the sampling resolution.
556    #[inline]
557    pub fn resolution(&self) -> config::Resolution {
558        self.reg.cfgr.read().res().variant().into()
559    }
560
561    /// Get the current configured data alignment.
562    #[inline]
563    pub fn data_alignment(&self) -> config::DataAlignment {
564        self.reg.cfgr.read().align().variant().into()
565    }
566
567    /// Get the current configured external trigger.
568    ///
569    /// If no (valid) trigger is set, return `None`
570    #[inline]
571    pub fn external_trigger(&self) -> Option<config::ExternalTrigger> {
572        use adc1::cfgr::{EXTEN_A, EXTSEL_A};
573        use config::ExternalTrigger;
574        let cfgr = self.reg.cfgr.read();
575
576        match (cfgr.exten().variant(), cfgr.extsel().variant()) {
577            (EXTEN_A::Disabled, _) | (_, None) => None,
578            (edge, Some(ext)) => {
579                let edge = match edge {
580                    EXTEN_A::Disabled => {
581                        // SAFETY: This arm can not be reached, because of the
582                        // (EXTEN_A::DISABLED, _) arm above.
583                        unsafe { unreachable_unchecked() }
584                    }
585                    EXTEN_A::RisingEdge => config::TriggerMode::RisingEdge,
586                    EXTEN_A::FallingEdge => config::TriggerMode::FallingEdge,
587                    EXTEN_A::BothEdges => config::TriggerMode::BothEdges,
588                };
589
590                Some(match ext {
591                    EXTSEL_A::HrtimAdctrg1 => ExternalTrigger::HrtimAdcTrg1(edge),
592                    EXTSEL_A::HrtimAdctrg3 => ExternalTrigger::HrtimAdcTrg3(edge),
593                    EXTSEL_A::Tim1Cc1 => ExternalTrigger::Tim1Cc1(edge),
594                    EXTSEL_A::Tim1Cc2 => ExternalTrigger::Tim1Cc2(edge),
595                    EXTSEL_A::Tim1Cc3 => ExternalTrigger::Tim1Cc3(edge),
596                    EXTSEL_A::Tim2Cc2 => ExternalTrigger::Tim2Cc2(edge),
597                    EXTSEL_A::Tim3Trgo => ExternalTrigger::Tim3Trgo(edge),
598                    EXTSEL_A::Exti11 => ExternalTrigger::Exti11(edge),
599                    EXTSEL_A::Tim1Trgo => ExternalTrigger::Tim1Trgo(edge),
600                    EXTSEL_A::Tim1Trgo2 => ExternalTrigger::Tim1Trgo2(edge),
601                    EXTSEL_A::Tim2Trgo => ExternalTrigger::Tim2Trgo(edge),
602                    EXTSEL_A::Tim6Trgo => ExternalTrigger::Tim6Trgo(edge),
603                    EXTSEL_A::Tim15Trgo => ExternalTrigger::Tim15Trgo(edge),
604                    EXTSEL_A::Tim3Cc4 => ExternalTrigger::Tim3Cc4(edge),
605                })
606            }
607        }
608    }
609
610    /// Return the conversion mode the peripheral is currently operating in.
611    #[inline]
612    pub fn conversion_mode(&self) -> config::ConversionMode {
613        use adc1::cfgr::{CONT_A, DISCEN_A};
614        let cfgr = self.reg.cfgr.read();
615
616        match (
617            cfgr.cont().variant(),
618            cfgr.discen().variant(),
619            cfgr.discnum().bits(),
620        ) {
621            (CONT_A::Single, DISCEN_A::Disabled, _) => config::ConversionMode::Single,
622            (CONT_A::Continuous, DISCEN_A::Disabled, _) => config::ConversionMode::Continuous,
623            // It is not possible to have both discontinuous mode and continuous mode enabled. In this
624            // case (if DISCEN=1, CONT=1), the ADC behaves as if continuous mode was disabled.
625            // [RM0316 15.3.20]
626            (_, DISCEN_A::Enabled, n) => config::ConversionMode::Discontinuous(n),
627        }
628    }
629
630    /// Get the current configured DMA mode.
631    #[inline]
632    pub fn dma_mode(&self) -> config::DmaMode {
633        use adc1::cfgr::{DMACFG_A, DMAEN_A};
634
635        let cfgr = self.reg.cfgr.read();
636        match (cfgr.dmaen().variant(), cfgr.dmacfg().variant()) {
637            (DMAEN_A::Disabled, _) => config::DmaMode::Disabled,
638            (DMAEN_A::Enabled, DMACFG_A::OneShot) => config::DmaMode::OneShot,
639            (DMAEN_A::Enabled, DMACFG_A::Circular) => config::DmaMode::Circular,
640        }
641    }
642
643    #[inline]
644    #[cfg(feature = "svd-f373")]
645    // TODO(Sh3Rm4n): This is dead code, becuase svd-f373 is not supported as of now.
646    pub fn scan(&self) -> config::Scan {
647        self.reg.cr1.modify(|_, w| w.scan().variant(scan.into()));
648    }
649
650    /// Get the current [`config::Config`] the peripheral is configured to.
651    pub fn config(&self) -> config::Config {
652        config::Config {
653            resolution: self.resolution(),
654            data_alignment: self.data_alignment(),
655            #[cfg(feature = "svd-f373")]
656            scan: self.scan(),
657            overrun: self.overrun_mode(),
658            external_trigger: self.external_trigger(),
659            conversion: self.conversion_mode(),
660            dma: self.dma_mode(),
661            // TODO(Sh3Rm4n): Voltage reference?
662        }
663    }
664
665    /// Check if a conversion is ongoing.
666    ///
667    /// * A conversion can not only be started manually via [`Adc::start_conversion`], but
668    ///   also by an [`config::ExternalTrigger`].
669    /// * Stopping a conversion might be needed to be able to configure the peripheral,
670    ///   which is not allowed during a conversion.
671    /// * Alternativly a conversino stop is signaled via the [`Event::EndOfConversion`] event.
672    #[inline]
673    pub fn is_conversion_ongoing(&self) -> bool {
674        self.reg.cr.read().adstart().is_active()
675    }
676
677    /// Get the [`channel::Id`] at a specific [`config::Sequence`] position.
678    ///
679    /// Return [`None`] when no channel was set at the sequence position.
680    ///
681    /// # Example
682    ///
683    /// Getting the pin in a specific sequence position
684    ///
685    /// ```
686    /// let pin_id: u8 = adc.channel_sequence(adc::config::Sequence::Seven).unwrap().into();
687    /// ```
688    #[inline]
689    #[rustfmt::skip]
690    pub fn channel_sequence(&self, sequence: config::Sequence) ->  Option<channel::Id> {
691        // Set the channel in the right sequence field
692        match sequence {
693            config::Sequence::One      => self.reg.sqr1.read().sq1().bits().try_into().ok(),
694            config::Sequence::Two      => self.reg.sqr1.read().sq2().bits().try_into().ok(),
695            config::Sequence::Three    => self.reg.sqr1.read().sq3().bits().try_into().ok(),
696            config::Sequence::Four     => self.reg.sqr1.read().sq4().bits().try_into().ok(),
697            config::Sequence::Five     => self.reg.sqr2.read().sq5().bits().try_into().ok(),
698            config::Sequence::Six      => self.reg.sqr2.read().sq6().bits().try_into().ok(),
699            config::Sequence::Seven    => self.reg.sqr2.read().sq7().bits().try_into().ok(),
700            config::Sequence::Eight    => self.reg.sqr2.read().sq8().bits().try_into().ok(),
701            config::Sequence::Nine     => self.reg.sqr2.read().sq9().bits().try_into().ok(),
702            config::Sequence::Ten      => self.reg.sqr3.read().sq10().bits().try_into().ok(),
703            config::Sequence::Eleven   => self.reg.sqr3.read().sq11().bits().try_into().ok(),
704            config::Sequence::Twelve   => self.reg.sqr3.read().sq12().bits().try_into().ok(),
705            config::Sequence::Thirteen => self.reg.sqr3.read().sq13().bits().try_into().ok(),
706            config::Sequence::Fourteen => self.reg.sqr3.read().sq14().bits().try_into().ok(),
707            config::Sequence::Fifteen  => self.reg.sqr4.read().sq15().bits().try_into().ok(),
708            config::Sequence::Sixteen  => self.reg.sqr4.read().sq16().bits().try_into().ok(),
709        }
710    }
711
712    /// Return the current configured sample time for the given pin.
713    // TODO: Sample_time or sampling_time (same for the type)
714    pub fn sample_time<Pin>(&self, _pin: &Pin) -> config::SampleTime
715    where
716        Pin: Channel<ADC, ID = channel::Id>,
717    {
718        let channel = Pin::channel();
719        // Set the sample time for the channel
720        match channel {
721            #[cfg(feature = "gpio-f373")]
722            channel::Id::Zero => self.adc.smpr1.read().smp0().variant().into(),
723            channel::Id::One => self.reg.smpr1.read().smp1().variant().into(),
724            channel::Id::Two => self.reg.smpr1.read().smp2().variant().into(),
725            channel::Id::Three => self.reg.smpr1.read().smp3().variant().into(),
726            channel::Id::Four => self.reg.smpr1.read().smp4().variant().into(),
727            channel::Id::Five => self.reg.smpr1.read().smp5().variant().into(),
728            channel::Id::Six => self.reg.smpr1.read().smp6().variant().into(),
729            channel::Id::Seven => self.reg.smpr1.read().smp7().variant().into(),
730            channel::Id::Eight => self.reg.smpr1.read().smp8().variant().into(),
731            channel::Id::Nine => self.reg.smpr1.read().smp9().variant().into(),
732            channel::Id::Ten => self.reg.smpr2.read().smp10().variant().into(),
733            channel::Id::Eleven => self.reg.smpr2.read().smp11().variant().into(),
734            channel::Id::Twelve => self.reg.smpr2.read().smp12().variant().into(),
735            channel::Id::Thirteen => self.reg.smpr2.read().smp13().variant().into(),
736            channel::Id::Fourteen => self.reg.smpr2.read().smp14().variant().into(),
737            channel::Id::Fifteen => self.reg.smpr2.read().smp15().variant().into(),
738            channel::Id::Sixteen => self.reg.smpr2.read().smp16().variant().into(),
739            channel::Id::Seventeen => self.reg.smpr2.read().smp17().variant().into(),
740            channel::Id::Eighteen => self.reg.smpr2.read().smp18().variant().into(),
741            // #[cfg(not(feature = "gpio-f373"))]
742            // // SAFETY: We know, that channel IDs will not exceed 18, see [`crate::adc::channel`]
743            // _ => unsafe { unreachable_unchecked() },
744        }
745    }
746
747    /// Returns the total number of conversions in a regular channel sequence.
748    #[inline]
749    pub fn sequence_length(&self) -> config::Sequence {
750        match self.reg.sqr1.read().l().bits().try_into() {
751            Ok(seq) => seq,
752            // SAFETY: We are directly reading from the register, which can't give
753            // use back invalid values, so this should never be called.
754            Err(_) => unsafe { unreachable_unchecked() },
755        }
756    }
757
758    #[inline]
759    #[cfg(feature = "__disabled")]
760    pub fn is_injected_conversion_stopped(&self) -> bool {
761        self.adc.cr.read().jadstp().is_stop()
762    }
763
764    /// Check if an interrupt is configured for the [`Event`]
765    #[inline]
766    pub fn is_interrupt_configured(&self, event: Event) -> bool {
767        match event {
768            Event::AdcReady => self.reg.ier.read().adrdyie().is_enabled(),
769            Event::EndOfSamplingPhase => self.reg.ier.read().eosmpie().is_enabled(),
770            Event::EndOfConversion => self.reg.ier.read().eocie().is_enabled(),
771            Event::EndOfSequence => self.reg.ier.read().eosie().is_enabled(),
772            Event::Overrun => self.reg.ier.read().ovrie().is_enabled(),
773            Event::InjectedChannelEndOfConversion => self.reg.ier.read().jeocie().is_enabled(),
774            Event::InjectedChannelEndOfSequence => self.reg.ier.read().jeosie().is_enabled(),
775            Event::AnalogWatchdog1 => self.reg.ier.read().awd1ie().is_enabled(),
776            Event::AnalogWatchdog2 => self.reg.ier.read().awd2ie().is_enabled(),
777            Event::AnalogWatchdog3 => self.reg.ier.read().awd3ie().is_enabled(),
778            Event::InjectedContextQueueOverfow => self.reg.ier.read().jqovfie().is_enabled(),
779        }
780    }
781
782    /// Check which interrupts are enabled for all [`Event`]s
783    #[cfg(feature = "enumset")]
784    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
785    #[inline]
786    pub fn configured_interrupts(&mut self) -> EnumSet<Event> {
787        let mut events = EnumSet::new();
788
789        for event in EnumSet::<Event>::all().iter() {
790            if self.is_interrupt_configured(event) {
791                events |= event;
792            }
793        }
794
795        events
796    }
797
798    /// Check if an interrupt event happend.
799    #[inline]
800    pub fn is_event_triggered(&self, event: Event) -> bool {
801        let isr = self.reg.isr.read();
802        match event {
803            Event::AdcReady => isr.adrdy().is_ready(),
804            Event::EndOfSamplingPhase => isr.eosmp().is_ended(),
805            Event::EndOfConversion => isr.eoc().is_complete(),
806            Event::EndOfSequence => isr.eos().is_complete(),
807            Event::Overrun => isr.ovr().is_overrun(),
808            Event::InjectedChannelEndOfConversion => isr.jeoc().is_complete(),
809            Event::InjectedChannelEndOfSequence => isr.jeos().is_complete(),
810            Event::AnalogWatchdog1 => isr.awd1().is_event(),
811            Event::AnalogWatchdog2 => isr.awd2().is_event(),
812            Event::AnalogWatchdog3 => isr.awd3().is_event(),
813            Event::InjectedContextQueueOverfow => isr.jqovf().is_overflow(),
814        }
815    }
816
817    /// Get an [`EnumSet`] of all fired interrupt events.
818    ///
819    /// # Examples
820    ///
821    /// This allows disabling all fired event at once, via the enum set abstraction, like so
822    ///
823    /// ```rust
824    /// for event in adc.events() {
825    ///     adc.configure_interrupt(event, false);
826    /// }
827    /// ```
828    #[cfg(feature = "enumset")]
829    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
830    pub fn triggered_events(&self) -> EnumSet<Event> {
831        let mut events = EnumSet::new();
832
833        for event in EnumSet::<Event>::all().iter() {
834            if self.is_event_triggered(event) {
835                events |= event;
836            }
837        }
838
839        events
840    }
841
842    /// Get access to the underlying register block.
843    ///
844    /// # Safety
845    ///
846    /// This function is not _memory_ unsafe per se, but does not guarantee
847    /// anything about assumptions of invariants made in this implementation.
848    ///
849    /// Changing specific options can lead to un-expected behavior and nothing
850    /// is guaranteed.
851    #[inline]
852    pub unsafe fn peripheral(&mut self) -> &mut ADC {
853        &mut self.reg
854    }
855}
856
857impl<ADC, State> Adc<ADC, State>
858where
859    ADC: Instance,
860    State: Configurable,
861{
862    /// Apply a whole new [`config::Config`] to the peripheral.
863    pub fn set_config(&mut self, config: config::Config) {
864        self.set_resolution(config.resolution);
865        self.set_data_alignment(config.data_alignment);
866        #[cfg(feature = "svd-f373")]
867        self.set_scan(config.scan);
868        self.set_overrun_mode(config.overrun);
869        self.set_external_trigger(config.external_trigger);
870        self.set_conversion_mode(config.conversion);
871        self.set_dma_mode(config.dma);
872    }
873
874    /// Set the overrun mode
875    #[inline]
876    pub fn set_overrun_mode(&mut self, mode: config::OverrunMode) {
877        self.reg.cfgr.modify(|_, w| w.ovrmod().variant(mode.into()));
878    }
879
880    /// Sets the sampling resolution.
881    #[inline]
882    pub fn set_resolution(&mut self, resolution: config::Resolution) {
883        self.reg
884            .cfgr
885            .modify(|_, w| w.res().variant(resolution.into()));
886    }
887
888    /// Sets the data register alignment
889    #[inline]
890    pub fn set_data_alignment(&mut self, align: config::DataAlignment) {
891        self.reg.cfgr.modify(|_, w| w.align().variant(align.into()));
892    }
893
894    // TODO(Sh3Rm4n): setting offset might be useful, see RM0316 15.3.26
895    // #[inline]
896    // pub fn set_channel_offset(&self) {}
897
898    /// Set an external trigger for a conversion.
899    ///
900    /// This is an alternative to starting a conversion by software ([`Adc::start_conversion`])
901    #[inline]
902    // Allow external trigger beeing None if trigger mode is disabled?
903    pub fn set_external_trigger(&mut self, trigger: Option<config::ExternalTrigger>) {
904        // Only allowed to write when no conversion is ongoing
905        self.stop_conversion();
906
907        self.reg.cfgr.modify(|_, w| {
908            if let Some(ext) = trigger {
909                w.extsel().variant(ext.into()).exten().variant(ext.into())
910            } else {
911                w.exten().disabled()
912            }
913        });
914    }
915
916    /// Set the conversion mode the ADC peripheral is operating in.
917    ///
918    /// This mode is the heart of how the ADC is operating and what it is used for.
919    /// For a better explenatnion of the modes, read the documentation of [`config::ConversionMode`].
920    ///
921    /// E.g. for the [`embedded_hal::adc::OneShot`] trait this peripheral is operating in
922    /// [`config::ConversionMode::Single`], while, when using the ADC for DMA or similar,
923    /// [`config::ConversionMode::Continuous`] makes more sense. (DMA itself is configured via
924    /// [`Adc::set_dma_mode`]).
925    #[inline]
926    pub fn set_conversion_mode(&mut self, conversion_mode: config::ConversionMode) {
927        // TODO: If we don't support 0, to what mode should the periperhal be set?
928        self.reg.cfgr.modify(|_, w| {
929            w.discen()
930                .variant(conversion_mode.into())
931                .cont()
932                .variant(conversion_mode.into())
933        });
934
935        if let config::ConversionMode::Discontinuous(n) = conversion_mode {
936            self.reg
937                .cfgr
938                .modify(|_, w| w.discnum().bits(if n < 0b111 { n } else { 0b111 }));
939        }
940    }
941
942    /// Sets DMA to disabled, single or continuous
943    // TODO: Check against DMA, so that it is working
944    #[inline]
945    pub fn set_dma_mode(&mut self, dma: config::DmaMode) {
946        use adc1::cfgr::{DMACFG_A, DMAEN_A};
947        let (en, mode) = match dma {
948            config::DmaMode::Disabled => (DMAEN_A::Disabled, DMACFG_A::OneShot),
949            config::DmaMode::OneShot => (DMAEN_A::Enabled, DMACFG_A::OneShot),
950            config::DmaMode::Circular => (DMAEN_A::Enabled, DMACFG_A::Circular),
951        };
952
953        self.reg
954            .cfgr
955            .modify(|_, w| w.dmaen().variant(en).dmacfg().variant(mode));
956    }
957
958    /// Enables and disables scan mode
959    #[inline]
960    #[cfg(feature = "svd-f373")]
961    // TODO(Sh3Rm4n): This is dead code, becuase svd-f373 is not supported as of now.
962    // * Rename to set_scan_mode or merge with conversion Mode?
963    // * Is this a [`Event`]?
964    pub fn set_scan(&mut self, scan: config::Scan) {
965        self.reg.cr1.modify(|_, w| w.scan().variant(scan.into()));
966    }
967
968    /// Signal the peripheral to stop any ongoing conversion
969    ///
970    /// This function will **block** until the conversion is stopped.
971    ///
972    /// For further details how stop is working, see [RM0316] 15.3.17
973    ///
974    /// [RM0316]: https://www.st.com/resource/en/reference_manual/dm00094349.pdf
975    #[inline]
976    pub fn stop_conversion(&mut self) {
977        // If no conversion is ongoing, this may lead to the stop bit never beeing reset?
978        if self.is_conversion_ongoing() {
979            self.reg.cr.modify(|_, w| w.adstp().stop_conversion());
980        }
981
982        while self.reg.cr.read().adstp().bit_is_set() {}
983    }
984
985    /// Wraps [`Adc::set_channel_sequence_position`] to be able to take a pin.
986    #[inline]
987    pub fn set_pin_sequence_position<Pin>(&mut self, sequence: config::Sequence, _pin: &mut Pin)
988    where
989        Pin: Channel<ADC, ID = channel::Id>,
990    {
991        let channel = Pin::channel();
992
993        // SAFETY: We have the Pin not the channel, so it should be safe to set the corresponding
994        // channel to the pin.
995        unsafe { self.set_channel_sequence_position(sequence, channel) };
996    }
997
998    /// Configure the sequence position of a channel.
999    ///
1000    /// # Note
1001    ///
1002    /// * The [`Adc::sequence_length`] will be increased, if [`Sequence`] < [`Adc::sequence_length`].
1003    /// * To configure a channel, any ongoing conversion will be stopped ([`Adc::stop_conversion`])
1004    ///
1005    /// # Safety
1006    ///
1007    /// This function can not guarantee, that one channel is not used by multiple ADCs at similar
1008    /// times. For example [`channel::Id::Eighteen`], which is the [`VoltageInternalReference`].
1009    ///
1010    /// It can also not guarantee that the corresponding GPIO pin was set into analog mode.
1011    ///
1012    /// For the **safe** variant use [`Adc::set_pin_sequence_position`].
1013    ///
1014    /// [`ConversionMode::Continuous`]: `config::ConversionMode::Continuous`
1015    /// [`Sequence`]: `config::Sequence`
1016    ///
1017    #[inline]
1018    #[rustfmt::skip]
1019    pub unsafe fn set_channel_sequence_position(&mut self, sequence: config::Sequence, channel: channel::Id) {
1020        self.stop_conversion();
1021
1022        // Increase the Sequence lenght, if it is not long enough
1023        if self.sequence_length() < sequence {
1024            self.set_sequence_length(sequence);
1025        }
1026
1027        // Set the channel in the right sequence field
1028        // SAFETY: the channel.into() implementation ensures that those are valid values
1029        unsafe {
1030            match sequence {
1031                config::Sequence::One      => self.reg.sqr1.modify(|_, w| w.sq1().bits(channel.into())),
1032                config::Sequence::Two      => self.reg.sqr1.modify(|_, w| w.sq2().bits(channel.into())),
1033                config::Sequence::Three    => self.reg.sqr1.modify(|_, w| w.sq3().bits(channel.into())),
1034                config::Sequence::Four     => self.reg.sqr1.modify(|_, w| w.sq4().bits(channel.into())),
1035                config::Sequence::Five     => self.reg.sqr2.modify(|_, w| w.sq5().bits(channel.into())),
1036                config::Sequence::Six      => self.reg.sqr2.modify(|_, w| w.sq6().bits(channel.into())),
1037                config::Sequence::Seven    => self.reg.sqr2.modify(|_, w| w.sq7().bits(channel.into())),
1038                config::Sequence::Eight    => self.reg.sqr2.modify(|_, w| w.sq8().bits(channel.into())),
1039                config::Sequence::Nine     => self.reg.sqr2.modify(|_, w| w.sq9().bits(channel.into())),
1040                config::Sequence::Ten      => self.reg.sqr3.modify(|_, w| w.sq10().bits(channel.into())),
1041                config::Sequence::Eleven   => self.reg.sqr3.modify(|_, w| w.sq11().bits(channel.into())),
1042                config::Sequence::Twelve   => self.reg.sqr3.modify(|_, w| w.sq12().bits(channel.into())),
1043                config::Sequence::Thirteen => self.reg.sqr3.modify(|_, w| w.sq13().bits(channel.into())),
1044                config::Sequence::Fourteen => self.reg.sqr3.modify(|_, w| w.sq14().bits(channel.into())),
1045                config::Sequence::Fifteen  => self.reg.sqr4.modify(|_, w| w.sq15().bits(channel.into())),
1046                config::Sequence::Sixteen  => self.reg.sqr4.modify(|_, w| w.sq16().bits(channel.into())),
1047            }
1048        }
1049    }
1050
1051    /// Each channel can be sampled with a different sampling time.
1052    ///
1053    /// # Note
1054    ///
1055    /// Before starting a conversion, the ADC must establish a direct connection between the
1056    /// voltage source under measurement and the embedded sampling capacitor of the ADC.
1057    /// This sampling time must be enough for the input voltage source to charge the embedded
1058    /// capacitor to the input voltage level.
1059    #[rustfmt::skip]
1060    pub fn set_sample_time<Pin>(&mut self, _pin: &Pin, sample_time: config::SampleTime)
1061    where
1062        Pin: Channel<ADC, ID = channel::Id>,
1063    {
1064        let channel = Pin::channel();
1065        // Set the sample time for the channel
1066        match channel {
1067            #[cfg(feature = "gpio-f373")]
1068            channel::Id::Zero     => self.adc.smpr1.modify(|_, w| w.smp0().variant(sample_time.into())),
1069            channel::Id::One      => self.reg.smpr1.modify(|_, w| w.smp1().variant(sample_time.into())),
1070            channel::Id::Two      => self.reg.smpr1.modify(|_, w| w.smp2().variant(sample_time.into())),
1071            channel::Id::Three    => self.reg.smpr1.modify(|_, w| w.smp3().variant(sample_time.into())),
1072            channel::Id::Four     => self.reg.smpr1.modify(|_, w| w.smp4().variant(sample_time.into())),
1073            channel::Id::Five     => self.reg.smpr1.modify(|_, w| w.smp5().variant(sample_time.into())),
1074            channel::Id::Six      => self.reg.smpr1.modify(|_, w| w.smp6().variant(sample_time.into())),
1075            channel::Id::Seven    => self.reg.smpr1.modify(|_, w| w.smp7().variant(sample_time.into())),
1076            channel::Id::Eight    => self.reg.smpr1.modify(|_, w| w.smp8().variant(sample_time.into())),
1077            channel::Id::Nine     => self.reg.smpr1.modify(|_, w| w.smp9().variant(sample_time.into())),
1078            channel::Id::Ten      => self.reg.smpr2.modify(|_, w| w.smp10().variant(sample_time.into())),
1079            channel::Id::Eleven   => self.reg.smpr2.modify(|_, w| w.smp11().variant(sample_time.into())),
1080            channel::Id::Twelve   => self.reg.smpr2.modify(|_, w| w.smp12().variant(sample_time.into())),
1081            channel::Id::Thirteen => self.reg.smpr2.modify(|_, w| w.smp13().variant(sample_time.into())),
1082            channel::Id::Fourteen => self.reg.smpr2.modify(|_, w| w.smp14().variant(sample_time.into())),
1083            channel::Id::Fifteen  => self.reg.smpr2.modify(|_, w| w.smp15().variant(sample_time.into())),
1084            channel::Id::Sixteen  => self.reg.smpr2.modify(|_, w| w.smp16().variant(sample_time.into())),
1085            channel::Id::Seventeen => self.reg.smpr2.modify(|_, w| w.smp17().variant(sample_time.into())),
1086            channel::Id::Eighteen => self.reg.smpr2.modify(|_, w| w.smp18().variant(sample_time.into())),
1087            // #[cfg(not(feature = "gpio-f373"))]
1088            // _ => () // Make it a no-op for channels which are not available.
1089        }
1090    }
1091
1092    /// Define the total number of conversions in the regular channel conversion sequence.
1093    ///
1094    /// The end of the whole sequence is notfied via the [`Event::EndOfSequence`], while
1095    /// the end of a single conversion of a "slot" is notfied via [`Event::EndOfConversion`].
1096    #[inline]
1097    pub fn set_sequence_length(&mut self, sequence: config::Sequence) {
1098        self.reg.sqr1.modify(|_, w| w.l().bits(sequence.into()));
1099    }
1100
1101    // TODO(Sh3Rm4n): Implement, when injection mode is implemented.
1102    #[inline]
1103    #[cfg(feature = "__disabled")]
1104    pub fn stop_injected_conversion(&mut self) {
1105        self.adc.cr.modify(|_, w| w.jadstp().stop());
1106    }
1107
1108    /// Enable the interrupt for the specified [`Event`].
1109    #[inline]
1110    pub fn enable_interrupt(&mut self, event: Event) {
1111        self.configure_interrupt(event, Switch::On);
1112    }
1113
1114    /// Disable the interrupt for the specified [`Event`].
1115    #[inline]
1116    pub fn disable_interrupt(&mut self, event: Event) {
1117        self.configure_interrupt(event, Switch::Off);
1118    }
1119
1120    /// Enable or disable the interrupt for the specified [`Event`].
1121    #[inline]
1122    pub fn configure_interrupt(&mut self, event: Event, enable: impl Into<Switch>) {
1123        // Do a round way trip to be convert Into<Switch> -> bool
1124        let enable: Switch = enable.into();
1125        let enable: bool = enable.into();
1126        match event {
1127            Event::AdcReady => self.reg.ier.modify(|_, w| w.adrdyie().bit(enable)),
1128            Event::EndOfSamplingPhase => self.reg.ier.modify(|_, w| w.eosmpie().bit(enable)),
1129            Event::EndOfConversion => self.reg.ier.modify(|_, w| w.eocie().bit(enable)),
1130            Event::EndOfSequence => self.reg.ier.modify(|_, w| w.eosie().bit(enable)),
1131            Event::Overrun => self.reg.ier.modify(|_, w| w.ovrie().bit(enable)),
1132            Event::InjectedChannelEndOfConversion => {
1133                self.reg.ier.modify(|_, w| w.jeocie().bit(enable));
1134            }
1135            Event::InjectedChannelEndOfSequence => {
1136                self.reg.ier.modify(|_, w| w.jeosie().bit(enable));
1137            }
1138            Event::AnalogWatchdog1 => self.reg.ier.modify(|_, w| w.awd1ie().bit(enable)),
1139            Event::AnalogWatchdog2 => self.reg.ier.modify(|_, w| w.awd2ie().bit(enable)),
1140            Event::AnalogWatchdog3 => self.reg.ier.modify(|_, w| w.awd3ie().bit(enable)),
1141            Event::InjectedContextQueueOverfow => {
1142                self.reg.ier.modify(|_, w| w.jqovfie().bit(enable));
1143            }
1144        };
1145    }
1146
1147    /// Enable or disable interrupt for the specified [`Event`]s.
1148    ///
1149    /// Like [`Adc::configure_interrupt`], but instead using an enumset. The corresponding
1150    /// interrupt for every [`Event`] in the set will be enabled, every other interrupt will be
1151    /// **disabled**.
1152    #[cfg(feature = "enumset")]
1153    #[cfg_attr(docsrs, doc(cfg(feature = "enumset")))]
1154    #[inline]
1155    pub fn configure_interrupts(&mut self, events: EnumSet<Event>) {
1156        for event in events.complement().iter() {
1157            self.configure_interrupt(event, false);
1158        }
1159        for event in events.iter() {
1160            self.configure_interrupt(event, true);
1161        }
1162    }
1163
1164    /// Clear the given interrupt event flag.
1165    #[inline]
1166    pub fn clear_event(&mut self, event: Event) {
1167        self.reg.isr.write(|w| match event {
1168            Event::AdcReady => w.adrdy().clear(),
1169            Event::EndOfSamplingPhase => w.eosmp().clear(),
1170            Event::EndOfConversion => w.eoc().clear(),
1171            Event::EndOfSequence => w.eos().clear(),
1172            Event::Overrun => w.ovr().clear(),
1173            Event::InjectedChannelEndOfConversion => w.jeoc().clear(),
1174            Event::InjectedChannelEndOfSequence => w.jeos().clear(),
1175            Event::AnalogWatchdog1 => w.awd1().clear(),
1176            Event::AnalogWatchdog2 => w.awd2().clear(),
1177            Event::AnalogWatchdog3 => w.awd3().clear(),
1178            Event::InjectedContextQueueOverfow => w.jqovf().clear(),
1179        });
1180    }
1181
1182    /// Clear **all** interrupt events.
1183    #[inline]
1184    pub fn clear_events(&mut self) {
1185        // SAFETY: TO clear all events, write 1 to it.
1186        self.reg.isr.write(|w| unsafe { w.bits(u32::MAX) });
1187    }
1188}
1189
1190impl<ADC> Adc<ADC, OneShot>
1191where
1192    ADC: Instance,
1193{
1194    /// Converts the [`Adc`] in [`OneShot`] mode back to [`Enabled`] mode, while still staying in
1195    /// the confiugration for [`OneShot`] mode.
1196    pub fn into_enabled(self) -> Adc<ADC, Enabled> {
1197        Adc {
1198            reg: self.reg,
1199            state: PhantomData,
1200        }
1201    }
1202
1203    /// Releases the ADC peripheral
1204    #[inline]
1205    pub fn free(self) -> ADC {
1206        self.into_enabled().into_disabled().reg
1207    }
1208}
1209
1210impl<ADC> Adc<ADC>
1211where
1212    ADC: crate::interrupts::InterruptNumber,
1213{
1214    /// Obtain the associated interrupt number for the serial peripheral.
1215    ///
1216    /// Used to unmask / enable the interrupt with [`cortex_m::peripheral::NVIC::unmask()`].
1217    /// This is useful for all `cortex_m::peripheral::INTERRUPT` functions.
1218    ///
1219    /// # Note
1220    ///
1221    /// This is the easier alternative to obatain the interrupt for:
1222    ///
1223    /// ```
1224    /// use cortex_m::peripheral::INTERRUPT;
1225    /// use stm32f3xx_hal::pac::ADC1;
1226    /// use stm32f3xx_hal::interrupt::InterruptNumber;
1227    ///
1228    /// const INTERRUPT: Interrupt = <ADC1 as InterruptNumber>::INTERRUPT;
1229    /// ```
1230    ///
1231    /// though this function can not be used in a const context.
1232    // #[doc(alias = "unmask")]
1233    pub fn interrupt(&self) -> <ADC as crate::interrupts::InterruptNumber>::Interrupt {
1234        <ADC as crate::interrupts::InterruptNumber>::INTERRUPT
1235    }
1236}
1237
1238/// Marker trait if a type state allows to configure the [`Adc`] peripheral.
1239pub trait Configurable: crate::private::Sealed {}
1240
1241impl<ADC, Word, Pin> embedded_hal::adc::OneShot<ADC, Word, Pin> for Adc<ADC>
1242where
1243    ADC: Instance,
1244    Word: From<u16>,
1245    Pin: Channel<ADC, ID = channel::Id>,
1246{
1247    type Error = ();
1248
1249    /// Synchronously record a single sample of `pin`.
1250    ///
1251    /// # Note
1252    ///
1253    /// This function needs to reconfigure the peripheral to read a single sample, but no such
1254    /// reconfiguration should be visible to the user. If this is the case, consider it a bug!
1255    ///
1256    /// This function should not trigger any interrupt.
1257    ///
1258    /// To have a more efficient implementation of this trait, configure the device
1259    /// to [`OneShot`] mode via [`Adc::into_oneshot`].
1260    fn read(&mut self, pin: &mut Pin) -> nb::Result<Word, Self::Error> {
1261        let conv = self.conversion_mode();
1262        let dma = self.dma_mode();
1263        let ext = self.external_trigger();
1264        self.set_conversion_mode(config::ConversionMode::Single);
1265        self.set_dma_mode(config::DmaMode::Disabled);
1266        self.set_external_trigger(None);
1267
1268        // TODO(Sh3Rm4n): Is this an event?
1269        #[cfg(feature = "svd-f373")]
1270        let scan = self.scan();
1271        #[cfg(feature = "svd-f373")]
1272        self.set_scan(config::Scan::Disabled);
1273
1274        let is_end_of_conversion_enabled = self.is_interrupt_configured(Event::EndOfConversion);
1275        let is_end_of_sequence_enabled = self.is_interrupt_configured(Event::EndOfSequence);
1276        self.disable_interrupt(Event::EndOfConversion);
1277        self.disable_interrupt(Event::EndOfSequence);
1278
1279        let seq_len = self.sequence_length();
1280        let old_id = self.channel_sequence(config::Sequence::One);
1281        self.set_sequence_length(config::Sequence::One);
1282        self.set_pin_sequence_position(config::Sequence::One, pin);
1283
1284        // Wait for the sequence to complete
1285        self.clear_event(Event::EndOfConversion);
1286        self.clear_event(Event::EndOfSequence);
1287        self.start_conversion();
1288        while !self.is_event_triggered(Event::EndOfConversion)
1289            && !self.is_event_triggered(Event::EndOfSequence)
1290        {}
1291        self.clear_event(Event::EndOfConversion);
1292        self.clear_event(Event::EndOfSequence);
1293
1294        // Resolve this method overwrite.
1295        let result = self.data_register();
1296
1297        // Reset the config
1298        if let Some(id) = old_id {
1299            // SAFETY: As long as the user has set the channel through the safe interface,
1300            // this should'nt be a problem.
1301            unsafe { self.set_channel_sequence_position(config::Sequence::One, id) };
1302        }
1303        self.set_sequence_length(seq_len);
1304
1305        self.configure_interrupt(Event::EndOfSequence, is_end_of_sequence_enabled);
1306        self.configure_interrupt(Event::EndOfConversion, is_end_of_conversion_enabled);
1307
1308        #[cfg(feature = "svd-f373")]
1309        self.set_scan(config::Scan::Disabled);
1310
1311        self.set_external_trigger(ext);
1312        self.set_dma_mode(dma);
1313        self.set_conversion_mode(conv);
1314
1315        Ok(result.into())
1316    }
1317}
1318
1319impl<ADC, Word, Pin> embedded_hal::adc::OneShot<ADC, Word, Pin> for Adc<ADC, OneShot>
1320where
1321    ADC: Instance,
1322    Word: From<u16>,
1323    Pin: Channel<ADC, ID = channel::Id>,
1324{
1325    type Error = ();
1326
1327    /// Synchronously record a single sample of `pin`.
1328    fn read(&mut self, _pin: &mut Pin) -> nb::Result<Word, Self::Error> {
1329        // NOTE: as ADC is not configurable (`OneShot` does not implement `Configurable`), we can't
1330        // use the public methods to configure the ADC but have to fallback to the lower level
1331        // methods.
1332
1333        // self.set_pin_sequence_position(config::Sequence::One, pin);
1334        self.reg.sqr1.modify(|_, w|
1335                // SAFETY: channel().into() ensure the right channel value
1336                unsafe { w.sq1().bits(Pin::channel().into()) });
1337
1338        // Wait for the sequence to complete
1339
1340        // self.clear_events();
1341        self.reg.isr.reset();
1342        // self.start_conversion();
1343        self.reg.cr.modify(|_, w| w.adstart().start_conversion());
1344        // while !self.is_event_triggered(Event::EndOfConversion)
1345        //     && !self.is_event_triggered(Event::EndOfSequence)
1346        // {}
1347        while !self.reg.isr.read().eoc().is_complete() && !self.reg.isr.read().eos().is_complete() {
1348        }
1349        // self.clear_events();
1350        self.reg.isr.reset();
1351
1352        // Resolve this method overwrite.
1353        // self.data_register().into()
1354        Ok(self.reg.dr.read().rdata().bits().into())
1355    }
1356}
1357
1358/// ADC Instance
1359pub trait Instance: Deref<Target = adc1::RegisterBlock> + crate::private::Sealed {
1360    /// Shared Instance / Registerblock between multiple ADCs
1361    type SharedInstance: CommonInstance;
1362}
1363
1364/// The common ADC instance, which is shared by two ADC peripherals
1365pub trait CommonInstance: Deref<Target = adc1_2::RegisterBlock> + crate::private::Sealed {
1366    /// The one ADC peripheral associated with the common ADC
1367    type Childs;
1368
1369    #[doc(hidden)]
1370    fn enable_clock(&mut self, clocks: &Clocks, ahb: &mut AHB);
1371    #[doc(hidden)]
1372    // TODO: Make public?
1373    fn clock(&self, clocks: &Clocks) -> Option<Hertz>;
1374}
1375
1376/// Type State for an enabled [`Adc`]
1377///
1378/// An [`Adc`] in that state can be obtained via [`Adc::new`].
1379pub struct Enabled;
1380impl crate::private::Sealed for Enabled {}
1381impl Configurable for Enabled {}
1382
1383/// Type State for an disabled [`Adc`], which does also not guarantee to be calibrated.
1384///
1385/// An [`Adc`] in that state can be obtained via [`Adc::new_disabled`].
1386pub struct Disabled;
1387impl crate::private::Sealed for Disabled {}
1388impl Configurable for Disabled {}
1389
1390/// Type State for an [`Adc`] ready to be used for the [`embedded_hal::adc::OneShot`] trait.
1391///
1392/// To convert an [`Adc`] into that state, use [`Adc::into_oneshot`].
1393///
1394/// # Note
1395///
1396/// This ensure the most efficient implementation for this trait and is inteded to be used,
1397/// when passing the peripheral to drivers erxpecting that mode to be configured.
1398///
1399/// Nothing else can be done with the peripheral in that mode though. Converting
1400/// the peripheral back can be done via [`Adc::into_enabled`].
1401pub struct OneShot;
1402
1403// Macro to implement ADC functionality for ADC1 and ADC2
1404macro_rules! adc {
1405    ($(
1406        $ADC:ident: (
1407            $ADCX_Y:ident,
1408            $INTERRUPT:path
1409        ),
1410    )+) => {
1411        $(
1412            impl crate::private::Sealed for pac::$ADC {}
1413
1414            impl Instance for pac::$ADC {
1415                type SharedInstance = pac::$ADCX_Y;
1416            }
1417
1418            impl crate::interrupts::InterruptNumber for pac::$ADC {
1419                type Interrupt = Interrupt;
1420                const INTERRUPT: Interrupt = $INTERRUPT;
1421            }
1422        )+
1423    };
1424
1425    ([ $(($A:literal, $X:literal, $Y:literal, $INTERRUPT:path)),+ ]) => {
1426        paste::paste! {
1427            adc!(
1428                $(
1429                    [<ADC $A>]: (
1430                        [<ADC $X _ $Y>],
1431                        $INTERRUPT
1432                    ),
1433                )+
1434            );
1435        }
1436    };
1437}
1438
1439macro_rules! adc_common {
1440    ($(
1441        $ADCX_Y:ident: (
1442            $ADC_CHILDS:ty,
1443            $ADCXYPRES_A:ident,
1444            $adcXYen:ident,
1445            $adcXYpres:ident
1446        ),
1447    )+) => {
1448        $(
1449
1450            impl CommonInstance for pac::$ADCX_Y {
1451                type Childs = $ADC_CHILDS;
1452
1453                fn enable_clock(&mut self, clocks: &Clocks, ahb: &mut AHB) {
1454                    pac::$ADCX_Y::enable(ahb);
1455                    // self.enable(ahb);
1456
1457
1458                    // No clock can be set, so we have to fallback to a default.
1459                    if self.clock(clocks).is_none() {
1460                        self.ccr.modify(|_, w| w
1461                            .ckmode().variant(CKMODE_A::SyncDiv1)
1462                        );
1463                    };
1464                }
1465
1466                fn clock(&self, clocks: &Clocks) -> Option<Hertz> {
1467                    use crate::pac::rcc::cfgr2::$ADCXYPRES_A;
1468                    use crate::pac::RCC;
1469                    // SAFETY: atomic read with no side effects
1470                    let adc_pres = unsafe { &(*RCC::ptr()).cfgr2.read().$adcXYpres() };
1471                    // let common_adc = unsafe { &(*Self::SharedInstance::ptr()) };
1472
1473                    // FIXME(Sh3Rm4n): ADC_PRES is not clocking the peripheral?
1474                    // (Note HSE has to be on) Also setting SYNCDIV does not work.
1475                    // TODO: For no ADCPRES to work. ASYNC mode has to be on!
1476                    Some(match clocks.pllclk() {
1477                        Some(pllclk) if !adc_pres.is_no_clock()  => {
1478                            pllclk
1479                                / match adc_pres.variant() {
1480                                    Some($ADCXYPRES_A::Div1) => 1,
1481                                    Some($ADCXYPRES_A::Div2) => 2,
1482                                    Some($ADCXYPRES_A::Div4) => 4,
1483                                    Some($ADCXYPRES_A::Div6) => 6,
1484                                    Some($ADCXYPRES_A::Div8) => 8,
1485                                    Some($ADCXYPRES_A::Div10) => 10,
1486                                    Some($ADCXYPRES_A::Div12) => 12,
1487                                    Some($ADCXYPRES_A::Div16) => 16,
1488                                    Some($ADCXYPRES_A::Div32) => 32,
1489                                    Some($ADCXYPRES_A::Div64) => 64,
1490                                    Some($ADCXYPRES_A::Div128) => 128,
1491                                    Some($ADCXYPRES_A::Div256) => 256,
1492                                    Some($ADCXYPRES_A::NoClock) | None => 1,
1493                                }
1494                        }
1495                        _ => {
1496                            clocks.sysclk()
1497                                / match self.ccr.read().ckmode().variant() {
1498                                    CKMODE_A::SyncDiv1 => 1,
1499                                    CKMODE_A::SyncDiv2 => 2,
1500                                    CKMODE_A::SyncDiv4 => 4,
1501                                    // Asynchronous should be enabled if PLL is on. If this line of
1502                                    // code is reached PLL is off. Indicate that, so fallbacks can
1503                                    // be set.
1504                                    CKMODE_A::Asynchronous => return None,
1505                                }
1506                        }
1507                    })
1508                }
1509            }
1510        )+
1511    };
1512
1513    ([ $(($X:literal, $Y:literal)),+ ]) => {
1514        paste::paste! {
1515            adc_common!(
1516                $(
1517                    [<ADC $X _ $Y>]: (
1518                        (pac::[<ADC $X>], pac::[<ADC $Y>]),
1519                        [<ADC $X $Y PRES_A>],
1520                        [<adc $X $Y en>],
1521                        [<adc $X $Y pres>]
1522                    ),
1523                )+
1524            );
1525        }
1526    };
1527
1528    // TODO(Sh3Rm4n): https://github.com/stm32-rs/stm32-rs/pull/696
1529    ([ $(($X:literal, $Y:literal, $ADC:ident)),+ ]) => {
1530        paste::paste! {
1531            adc_common!(
1532                $(
1533                    $ADC: (
1534                        (pac::[<ADC $X>], pac::[<ADC $Y>]),
1535                        [<ADC $X $Y PRES_A>],
1536                        [<adc $X $Y en>],
1537                        [<adc $X $Y pres>]
1538                    ),
1539                )+
1540            );
1541        }
1542    };
1543
1544    ([ $(($A:literal, $X:literal, $Y:literal)),+ ]) => {
1545        paste::paste! {
1546            adc_common!(
1547                $(
1548                    [<ADC $X _ $Y>]: (
1549                        pac::[<ADC $A>],
1550                        [<ADC $X PRES_A>],
1551                        [<adc $X en>],
1552                        [<adc $X pres>]
1553                    ),
1554                )+
1555            );
1556        }
1557    };
1558}
1559
1560cfg_if::cfg_if! {
1561    if #[cfg(feature = "svd-f301")] {
1562        adc_common!([(1, 1, 2)]);
1563        adc!([(1, 1, 2, Interrupt::ADC1_IRQ)]);
1564    } else {
1565        adc_common!([(1, 2)]);
1566        adc!([(1, 1, 2, Interrupt::ADC1_2)]);
1567    }
1568}
1569
1570// TODO(Sh3Rm4n):
1571// * stm32f373 will become complicated, because no ADC1_2
1572
1573// See https://stm32-rs.github.io/stm32-rs/stm32f/stm32f3/index.html for an overview
1574#[cfg(any(feature = "svd-f302", feature = "svd-f303", feature = "svd-f3x4"))]
1575adc!([(2, 1, 2, Interrupt::ADC1_2)]);
1576
1577cfg_if::cfg_if! {
1578    if #[cfg(feature = "svd-f303")] {
1579        adc_common!([(3, 4)]);
1580        adc!([(3, 3, 4, Interrupt::ADC3), (4, 3, 4, Interrupt::ADC4)]);
1581    }
1582}