Merge pull request #2985 from rumcake-rs/stm32-adc-anyadcchannel
stm32/adc: add AnyAdcChannel type
This commit is contained in:
		
						commit
						e5c579d9fb
					
				@ -5,7 +5,7 @@ use core::task::Poll;
 | 
			
		||||
use embassy_hal_internal::into_ref;
 | 
			
		||||
 | 
			
		||||
use super::blocking_delay_us;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::{interrupt, Peripheral};
 | 
			
		||||
 | 
			
		||||
@ -32,16 +32,16 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vref;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Vref {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Vref {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vref {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vref {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        17
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        16
 | 
			
		||||
    }
 | 
			
		||||
@ -135,8 +135,8 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        T::regs().dr().read().0 as u16
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
        Self::set_channel_sample_time(pin.channel(), self.sample_time);
 | 
			
		||||
    pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        Self::set_channel_sample_time(channel.channel(), self.sample_time);
 | 
			
		||||
        T::regs().cr1().modify(|reg| {
 | 
			
		||||
            reg.set_scan(false);
 | 
			
		||||
            reg.set_discen(false);
 | 
			
		||||
@ -151,7 +151,7 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Configure the channel to sample
 | 
			
		||||
        T::regs().sqr3().write(|reg| reg.set_sq(0, pin.channel()));
 | 
			
		||||
        T::regs().sqr3().write(|reg| reg.set_sq(0, channel.channel()));
 | 
			
		||||
        self.convert().await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,7 @@ use core::task::Poll;
 | 
			
		||||
use embassy_hal_internal::into_ref;
 | 
			
		||||
 | 
			
		||||
use super::blocking_delay_us;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
 | 
			
		||||
use crate::interrupt::typelevel::Interrupt;
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::{interrupt, Peripheral};
 | 
			
		||||
@ -32,8 +32,8 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vref;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Vref {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Vref {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vref {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vref {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        18
 | 
			
		||||
    }
 | 
			
		||||
@ -47,8 +47,8 @@ impl Vref {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        16
 | 
			
		||||
    }
 | 
			
		||||
@ -154,11 +154,11 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        T::regs().dr().read().rdata()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
        Self::set_channel_sample_time(pin.channel(), self.sample_time);
 | 
			
		||||
    pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        Self::set_channel_sample_time(channel.channel(), self.sample_time);
 | 
			
		||||
 | 
			
		||||
        // Configure the channel to sample
 | 
			
		||||
        T::regs().sqr1().write(|w| w.set_sq(0, pin.channel()));
 | 
			
		||||
        T::regs().sqr1().write(|w| w.set_sq(0, channel.channel()));
 | 
			
		||||
        self.convert().await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ use embassy_hal_internal::into_ref;
 | 
			
		||||
use embassy_time::Instant;
 | 
			
		||||
 | 
			
		||||
use super::Resolution;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
 | 
			
		||||
use crate::interrupt::typelevel::Interrupt;
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::{interrupt, Peripheral};
 | 
			
		||||
@ -64,8 +64,8 @@ fn update_vref<T: Instance>(op: i8) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vref<T: Instance>(core::marker::PhantomData<T>);
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Vref<T> {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Vref<T> {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vref<T> {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vref<T> {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        17
 | 
			
		||||
    }
 | 
			
		||||
@ -123,8 +123,8 @@ impl<T: Instance> Drop for Vref<T> {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature<T: Instance>(core::marker::PhantomData<T>);
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Temperature<T> {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature<T> {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature<T> {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature<T> {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        16
 | 
			
		||||
    }
 | 
			
		||||
@ -271,8 +271,8 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
        self.set_sample_sequence(&[pin.channel()]).await;
 | 
			
		||||
    pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        self.set_sample_sequence(&[channel.channel()]).await;
 | 
			
		||||
        self.convert().await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -283,18 +283,18 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn set_sample_time(&mut self, pin: &mut impl AdcPin<T>, sample_time: SampleTime) {
 | 
			
		||||
        if Self::get_channel_sample_time(pin.channel()) != sample_time {
 | 
			
		||||
    pub async fn set_sample_time(&mut self, channel: &mut impl AdcChannel<T>, sample_time: SampleTime) {
 | 
			
		||||
        if Self::get_channel_sample_time(channel.channel()) != sample_time {
 | 
			
		||||
            self.stop_adc().await;
 | 
			
		||||
            unsafe {
 | 
			
		||||
                Self::set_channel_sample_time(pin.channel(), sample_time);
 | 
			
		||||
                Self::set_channel_sample_time(channel.channel(), sample_time);
 | 
			
		||||
            }
 | 
			
		||||
            self.start_adc().await;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn get_sample_time(&self, pin: &impl AdcPin<T>) -> SampleTime {
 | 
			
		||||
        Self::get_channel_sample_time(pin.channel())
 | 
			
		||||
    pub fn get_sample_time(&self, channel: &impl AdcChannel<T>) -> SampleTime {
 | 
			
		||||
        Self::get_channel_sample_time(channel.channel())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Sets the channel sample time
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
use pac::adc::vals::{Adcaldif, Difsel, Exten};
 | 
			
		||||
use pac::adccommon::vals::Presc;
 | 
			
		||||
 | 
			
		||||
use super::{blocking_delay_us, Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};
 | 
			
		||||
use super::{blocking_delay_us, Adc, AdcChannel, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::{pac, Peripheral};
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,8 @@ const VBAT_CHANNEL: u8 = 17;
 | 
			
		||||
// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
 | 
			
		||||
/// Internal voltage reference channel.
 | 
			
		||||
pub struct VrefInt;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for VrefInt {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        VREF_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -42,8 +42,8 @@ impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
 | 
			
		||||
 | 
			
		||||
/// Internal temperature channel.
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        TEMP_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -51,8 +51,8 @@ impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
 | 
			
		||||
 | 
			
		||||
/// Internal battery voltage channel.
 | 
			
		||||
pub struct Vbat;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for Vbat {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vbat {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        VBAT_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -258,18 +258,9 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Read an ADC pin.
 | 
			
		||||
    pub fn read<P>(&mut self, pin: &mut P) -> u16
 | 
			
		||||
    where
 | 
			
		||||
        P: AdcPin<T>,
 | 
			
		||||
        P: crate::gpio::Pin,
 | 
			
		||||
    {
 | 
			
		||||
        pin.set_as_analog();
 | 
			
		||||
    pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        channel.setup();
 | 
			
		||||
 | 
			
		||||
        self.read_channel(pin.channel())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Read an ADC internal channel.
 | 
			
		||||
    pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
 | 
			
		||||
        self.read_channel(channel.channel())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,8 @@
 | 
			
		||||
#[cfg_attr(adc_g4, path = "g4.rs")]
 | 
			
		||||
mod _version;
 | 
			
		||||
 | 
			
		||||
use core::marker::PhantomData;
 | 
			
		||||
 | 
			
		||||
#[allow(unused)]
 | 
			
		||||
#[cfg(not(adc_f3_v2))]
 | 
			
		||||
pub use _version::*;
 | 
			
		||||
@ -58,19 +60,14 @@ trait SealedInstance {
 | 
			
		||||
    fn state() -> &'static State;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) trait SealedAdcPin<T: Instance> {
 | 
			
		||||
    #[cfg(any(adc_v1, adc_l0, adc_v2))]
 | 
			
		||||
    fn set_as_analog(&mut self) {}
 | 
			
		||||
pub(crate) trait SealedAdcChannel<T> {
 | 
			
		||||
    #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4))]
 | 
			
		||||
    fn setup(&mut self) {}
 | 
			
		||||
 | 
			
		||||
    #[allow(unused)]
 | 
			
		||||
    fn channel(&self) -> u8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
trait SealedInternalChannel<T> {
 | 
			
		||||
    #[allow(unused)]
 | 
			
		||||
    fn channel(&self) -> u8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Performs a busy-wait delay for a specified number of microseconds.
 | 
			
		||||
#[allow(unused)]
 | 
			
		||||
pub(crate) fn blocking_delay_us(us: u32) {
 | 
			
		||||
@ -124,12 +121,36 @@ pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::R
 | 
			
		||||
    type Interrupt: crate::interrupt::typelevel::Interrupt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// ADC pin.
 | 
			
		||||
/// ADC channel.
 | 
			
		||||
#[allow(private_bounds)]
 | 
			
		||||
pub trait AdcPin<T: Instance>: SealedAdcPin<T> {}
 | 
			
		||||
/// ADC internal channel.
 | 
			
		||||
#[allow(private_bounds)]
 | 
			
		||||
pub trait InternalChannel<T>: SealedInternalChannel<T> {}
 | 
			
		||||
pub trait AdcChannel<T>: SealedAdcChannel<T> + Sized {
 | 
			
		||||
    #[allow(unused_mut)]
 | 
			
		||||
    fn degrade_adc(mut self) -> AnyAdcChannel<T> {
 | 
			
		||||
        #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4))]
 | 
			
		||||
        self.setup();
 | 
			
		||||
 | 
			
		||||
        AnyAdcChannel {
 | 
			
		||||
            channel: self.channel(),
 | 
			
		||||
            _phantom: PhantomData,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// A type-erased channel for a given ADC instance.
 | 
			
		||||
///
 | 
			
		||||
/// This is useful in scenarios where you need the ADC channels to have the same type, such as
 | 
			
		||||
/// storing them in an array.
 | 
			
		||||
pub struct AnyAdcChannel<T> {
 | 
			
		||||
    channel: u8,
 | 
			
		||||
    _phantom: PhantomData<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for AnyAdcChannel<T> {}
 | 
			
		||||
impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        self.channel
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
foreach_adc!(
 | 
			
		||||
    ($inst:ident, $common_inst:ident, $clock:ident) => {
 | 
			
		||||
@ -158,11 +179,10 @@ foreach_adc!(
 | 
			
		||||
 | 
			
		||||
macro_rules! impl_adc_pin {
 | 
			
		||||
    ($inst:ident, $pin:ident, $ch:expr) => {
 | 
			
		||||
        impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {}
 | 
			
		||||
 | 
			
		||||
        impl crate::adc::SealedAdcPin<peripherals::$inst> for crate::peripherals::$pin {
 | 
			
		||||
            #[cfg(any(adc_v1, adc_l0, adc_v2))]
 | 
			
		||||
            fn set_as_analog(&mut self) {
 | 
			
		||||
        impl crate::adc::AdcChannel<peripherals::$inst> for crate::peripherals::$pin {}
 | 
			
		||||
        impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::peripherals::$pin {
 | 
			
		||||
            #[cfg(any(adc_v1, adc_l0, adc_v2, adc_g4, adc_v4))]
 | 
			
		||||
            fn setup(&mut self) {
 | 
			
		||||
                <Self as crate::gpio::SealedPin>::set_as_analog(self);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,7 @@ use embassy_hal_internal::into_ref;
 | 
			
		||||
use stm32_metapac::adc::vals::Ckmode;
 | 
			
		||||
 | 
			
		||||
use super::blocking_delay_us;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::interrupt::typelevel::Interrupt;
 | 
			
		||||
use crate::peripherals::ADC1;
 | 
			
		||||
use crate::{interrupt, Peripheral};
 | 
			
		||||
@ -36,26 +36,26 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
 | 
			
		||||
pub struct Vbat;
 | 
			
		||||
 | 
			
		||||
#[cfg(not(adc_l0))]
 | 
			
		||||
impl AdcPin<ADC1> for Vbat {}
 | 
			
		||||
impl AdcChannel<ADC1> for Vbat {}
 | 
			
		||||
 | 
			
		||||
#[cfg(not(adc_l0))]
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for Vbat {
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for Vbat {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        18
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vref;
 | 
			
		||||
impl AdcPin<ADC1> for Vref {}
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for Vref {
 | 
			
		||||
impl AdcChannel<ADC1> for Vref {}
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for Vref {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        17
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl AdcPin<ADC1> for Temperature {}
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for Temperature {
 | 
			
		||||
impl AdcChannel<ADC1> for Temperature {}
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        16
 | 
			
		||||
    }
 | 
			
		||||
@ -155,12 +155,12 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
        let channel = pin.channel();
 | 
			
		||||
        pin.set_as_analog();
 | 
			
		||||
    pub async fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        let ch_num = channel.channel();
 | 
			
		||||
        channel.setup();
 | 
			
		||||
 | 
			
		||||
        // A.7.5 Single conversion sequence code example - Software trigger
 | 
			
		||||
        T::regs().chselr().write(|reg| reg.set_chselx(channel as usize, true));
 | 
			
		||||
        T::regs().chselr().write(|reg| reg.set_chselx(ch_num as usize, true));
 | 
			
		||||
 | 
			
		||||
        self.convert().await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
use embassy_hal_internal::into_ref;
 | 
			
		||||
 | 
			
		||||
use super::blocking_delay_us;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::peripherals::ADC1;
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::Peripheral;
 | 
			
		||||
@ -12,8 +12,8 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
 | 
			
		||||
pub const VREF_CALIB_MV: u32 = 3300;
 | 
			
		||||
 | 
			
		||||
pub struct VrefInt;
 | 
			
		||||
impl AdcPin<ADC1> for VrefInt {}
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for VrefInt {
 | 
			
		||||
impl AdcChannel<ADC1> for VrefInt {}
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for VrefInt {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        17
 | 
			
		||||
    }
 | 
			
		||||
@ -27,8 +27,8 @@ impl VrefInt {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl AdcPin<ADC1> for Temperature {}
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for Temperature {
 | 
			
		||||
impl AdcChannel<ADC1> for Temperature {}
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        cfg_if::cfg_if! {
 | 
			
		||||
            if #[cfg(any(stm32f2, stm32f40, stm32f41))] {
 | 
			
		||||
@ -48,8 +48,8 @@ impl Temperature {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vbat;
 | 
			
		||||
impl AdcPin<ADC1> for Vbat {}
 | 
			
		||||
impl super::SealedAdcPin<ADC1> for Vbat {
 | 
			
		||||
impl AdcChannel<ADC1> for Vbat {}
 | 
			
		||||
impl super::SealedAdcChannel<ADC1> for Vbat {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        18
 | 
			
		||||
    }
 | 
			
		||||
@ -175,11 +175,11 @@ where
 | 
			
		||||
        T::regs().dr().read().0 as u16
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
        pin.set_as_analog();
 | 
			
		||||
    pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        channel.setup();
 | 
			
		||||
 | 
			
		||||
        // Configure ADC
 | 
			
		||||
        let channel = pin.channel();
 | 
			
		||||
        let channel = channel.channel();
 | 
			
		||||
 | 
			
		||||
        // Select channel
 | 
			
		||||
        T::regs().sqr3().write(|reg| reg.set_sq(0, channel));
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ use cfg_if::cfg_if;
 | 
			
		||||
use embassy_hal_internal::into_ref;
 | 
			
		||||
 | 
			
		||||
use super::blocking_delay_us;
 | 
			
		||||
use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::Peripheral;
 | 
			
		||||
 | 
			
		||||
/// Default VREF voltage used for sample conversion to millivolts.
 | 
			
		||||
@ -11,8 +11,8 @@ pub const VREF_DEFAULT_MV: u32 = 3300;
 | 
			
		||||
pub const VREF_CALIB_MV: u32 = 3000;
 | 
			
		||||
 | 
			
		||||
pub struct VrefInt;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for VrefInt {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for VrefInt {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        cfg_if! {
 | 
			
		||||
            if #[cfg(adc_g0)] {
 | 
			
		||||
@ -30,8 +30,8 @@ impl<T: Instance> super::SealedAdcPin<T> for VrefInt {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        cfg_if! {
 | 
			
		||||
            if #[cfg(adc_g0)] {
 | 
			
		||||
@ -49,8 +49,8 @@ impl<T: Instance> super::SealedAdcPin<T> for Temperature {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Vbat;
 | 
			
		||||
impl<T: Instance> AdcPin<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcPin<T> for Vbat {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vbat {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        cfg_if! {
 | 
			
		||||
            if #[cfg(adc_g0)] {
 | 
			
		||||
@ -70,8 +70,8 @@ impl<T: Instance> super::SealedAdcPin<T> for Vbat {
 | 
			
		||||
cfg_if! {
 | 
			
		||||
    if #[cfg(adc_h5)] {
 | 
			
		||||
        pub struct VddCore;
 | 
			
		||||
        impl<T: Instance> AdcPin<T> for VddCore {}
 | 
			
		||||
        impl<T: Instance> super::SealedAdcPin<T> for VddCore {
 | 
			
		||||
        impl<T: Instance> AdcChannel<T> for VddCore {}
 | 
			
		||||
        impl<T: Instance> super::SealedAdcChannel<T> for VddCore {
 | 
			
		||||
            fn channel(&self) -> u8 {
 | 
			
		||||
                6
 | 
			
		||||
            }
 | 
			
		||||
@ -82,8 +82,8 @@ cfg_if! {
 | 
			
		||||
cfg_if! {
 | 
			
		||||
    if #[cfg(adc_u0)] {
 | 
			
		||||
        pub struct DacOut;
 | 
			
		||||
        impl<T: Instance> AdcPin<T> for DacOut {}
 | 
			
		||||
        impl<T: Instance> super::SealedAdcPin<T> for DacOut {
 | 
			
		||||
        impl<T: Instance> AdcChannel<T> for DacOut {}
 | 
			
		||||
        impl<T: Instance> super::SealedAdcChannel<T> for DacOut {
 | 
			
		||||
            fn channel(&self) -> u8 {
 | 
			
		||||
                19
 | 
			
		||||
            }
 | 
			
		||||
@ -220,7 +220,7 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        T::regs().dr().read().0 as u16
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
 | 
			
		||||
    pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        // Make sure bits are off
 | 
			
		||||
        while T::regs().cr().read().addis() {
 | 
			
		||||
            // spin
 | 
			
		||||
@ -241,18 +241,18 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        // RM0492, RM0481, etc.
 | 
			
		||||
        // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
 | 
			
		||||
        #[cfg(adc_h5)]
 | 
			
		||||
        if pin.channel() == 0 {
 | 
			
		||||
        if channel.channel() == 0 {
 | 
			
		||||
            T::regs().or().modify(|reg| reg.set_op0(true));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Configure channel
 | 
			
		||||
        Self::set_channel_sample_time(pin.channel(), self.sample_time);
 | 
			
		||||
        Self::set_channel_sample_time(channel.channel(), self.sample_time);
 | 
			
		||||
 | 
			
		||||
        // Select channel
 | 
			
		||||
        #[cfg(not(any(adc_g0, adc_u0)))]
 | 
			
		||||
        T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
 | 
			
		||||
        T::regs().sqr1().write(|reg| reg.set_sq(0, channel.channel()));
 | 
			
		||||
        #[cfg(any(adc_g0, adc_u0))]
 | 
			
		||||
        T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel()));
 | 
			
		||||
        T::regs().chselr().write(|reg| reg.set_chsel(1 << channel.channel()));
 | 
			
		||||
 | 
			
		||||
        // Some models are affected by an erratum:
 | 
			
		||||
        // If we perform conversions slower than 1 kHz, the first read ADC value can be
 | 
			
		||||
@ -270,7 +270,7 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        // RM0492, RM0481, etc.
 | 
			
		||||
        // "This option bit must be set to 1 when ADCx_INP0 or ADCx_INN1 channel is selected."
 | 
			
		||||
        #[cfg(adc_h5)]
 | 
			
		||||
        if pin.channel() == 0 {
 | 
			
		||||
        if channel.channel() == 0 {
 | 
			
		||||
            T::regs().or().modify(|reg| reg.set_op0(false));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
use pac::adc::vals::{Adcaldif, Boost, Difsel, Exten, Pcsel};
 | 
			
		||||
use pac::adccommon::vals::Presc;
 | 
			
		||||
 | 
			
		||||
use super::{blocking_delay_us, Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime};
 | 
			
		||||
use super::{blocking_delay_us, Adc, AdcChannel, Instance, Resolution, SampleTime};
 | 
			
		||||
use crate::time::Hertz;
 | 
			
		||||
use crate::{pac, Peripheral};
 | 
			
		||||
 | 
			
		||||
@ -33,8 +33,8 @@ const VBAT_CHANNEL: u8 = 17;
 | 
			
		||||
// NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs
 | 
			
		||||
/// Internal voltage reference channel.
 | 
			
		||||
pub struct VrefInt;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for VrefInt {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for VrefInt {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        VREF_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -42,8 +42,8 @@ impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
 | 
			
		||||
 | 
			
		||||
/// Internal temperature channel.
 | 
			
		||||
pub struct Temperature;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Temperature {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        TEMP_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -51,8 +51,8 @@ impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
 | 
			
		||||
 | 
			
		||||
/// Internal battery voltage channel.
 | 
			
		||||
pub struct Vbat;
 | 
			
		||||
impl<T: Instance> InternalChannel<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedInternalChannel<T> for Vbat {
 | 
			
		||||
impl<T: Instance> AdcChannel<T> for Vbat {}
 | 
			
		||||
impl<T: Instance> super::SealedAdcChannel<T> for Vbat {
 | 
			
		||||
    fn channel(&self) -> u8 {
 | 
			
		||||
        VBAT_CHANNEL
 | 
			
		||||
    }
 | 
			
		||||
@ -271,19 +271,10 @@ impl<'d, T: Instance> Adc<'d, T> {
 | 
			
		||||
        T::regs().dr().read().0 as u16
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Read an ADC pin.
 | 
			
		||||
    pub fn read<P>(&mut self, pin: &mut P) -> u16
 | 
			
		||||
    where
 | 
			
		||||
        P: AdcPin<T>,
 | 
			
		||||
        P: crate::gpio::Pin,
 | 
			
		||||
    {
 | 
			
		||||
        pin.set_as_analog();
 | 
			
		||||
    /// Read an ADC channel.
 | 
			
		||||
    pub fn read(&mut self, channel: &mut impl AdcChannel<T>) -> u16 {
 | 
			
		||||
        channel.setup();
 | 
			
		||||
 | 
			
		||||
        self.read_channel(pin.channel())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Read an ADC internal channel.
 | 
			
		||||
    pub fn read_internal(&mut self, channel: &mut impl InternalChannel<T>) -> u16 {
 | 
			
		||||
        self.read_channel(channel.channel())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -198,7 +198,7 @@ macro_rules! impl_opamp_external_output {
 | 
			
		||||
    ($inst:ident, $adc:ident, $ch:expr) => {
 | 
			
		||||
        foreach_adc!(
 | 
			
		||||
            ($adc, $common_inst:ident, $adc_clock:ident) => {
 | 
			
		||||
                impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
 | 
			
		||||
                impl<'d> crate::adc::SealedAdcChannel<crate::peripherals::$adc>
 | 
			
		||||
                    for OpAmpOutput<'d, crate::peripherals::$inst>
 | 
			
		||||
                {
 | 
			
		||||
                    fn channel(&self) -> u8 {
 | 
			
		||||
@ -206,7 +206,7 @@ macro_rules! impl_opamp_external_output {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                impl<'d> crate::adc::AdcPin<crate::peripherals::$adc>
 | 
			
		||||
                impl<'d> crate::adc::AdcChannel<crate::peripherals::$adc>
 | 
			
		||||
                    for OpAmpOutput<'d, crate::peripherals::$inst>
 | 
			
		||||
                {
 | 
			
		||||
                }
 | 
			
		||||
@ -244,7 +244,7 @@ macro_rules! impl_opamp_internal_output {
 | 
			
		||||
    ($inst:ident, $adc:ident, $ch:expr) => {
 | 
			
		||||
        foreach_adc!(
 | 
			
		||||
            ($adc, $common_inst:ident, $adc_clock:ident) => {
 | 
			
		||||
                impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
 | 
			
		||||
                impl<'d> crate::adc::SealedAdcChannel<crate::peripherals::$adc>
 | 
			
		||||
                    for OpAmpInternalOutput<'d, crate::peripherals::$inst>
 | 
			
		||||
                {
 | 
			
		||||
                    fn channel(&self) -> u8 {
 | 
			
		||||
@ -252,7 +252,7 @@ macro_rules! impl_opamp_internal_output {
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                impl<'d> crate::adc::AdcPin<crate::peripherals::$adc>
 | 
			
		||||
                impl<'d> crate::adc::AdcChannel<crate::peripherals::$adc>
 | 
			
		||||
                    for OpAmpInternalOutput<'d, crate::peripherals::$inst>
 | 
			
		||||
                {
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@ -51,7 +51,7 @@ async fn main(_spawner: Spawner) {
 | 
			
		||||
    let mut vrefint_channel = adc.enable_vrefint();
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let vrefint = adc.read_internal(&mut vrefint_channel);
 | 
			
		||||
        let vrefint = adc.read(&mut vrefint_channel);
 | 
			
		||||
        info!("vrefint: {}", vrefint);
 | 
			
		||||
        let measured = adc.read(&mut p.PC0);
 | 
			
		||||
        info!("measured: {}", measured);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user