stm32: add ADC f3_v1_1
This commit is contained in:
parent
e5fdd35bd6
commit
35f16c6003
408
embassy-stm32/src/adc/f3_v1_1.rs
Normal file
408
embassy-stm32/src/adc/f3_v1_1.rs
Normal file
@ -0,0 +1,408 @@
|
|||||||
|
use core::future::poll_fn;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy_futures::yield_now;
|
||||||
|
use embassy_hal_internal::into_ref;
|
||||||
|
use embassy_time::Instant;
|
||||||
|
|
||||||
|
use super::Resolution;
|
||||||
|
use crate::adc::{Adc, AdcPin, Instance, SampleTime};
|
||||||
|
use crate::interrupt::typelevel::Interrupt;
|
||||||
|
use crate::time::Hertz;
|
||||||
|
use crate::{interrupt, Peripheral};
|
||||||
|
|
||||||
|
const ADC_FREQ: Hertz = crate::rcc::HSI_FREQ;
|
||||||
|
|
||||||
|
pub const VDDA_CALIB_MV: u32 = 3300;
|
||||||
|
pub const ADC_MAX: u32 = (1 << 12) - 1;
|
||||||
|
pub const VREF_INT: u32 = 1230;
|
||||||
|
|
||||||
|
pub enum AdcPowerMode {
|
||||||
|
AlwaysOn,
|
||||||
|
DelayOff,
|
||||||
|
IdleOff,
|
||||||
|
DelayIdleOff,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum Prescaler {
|
||||||
|
Div1,
|
||||||
|
Div2,
|
||||||
|
Div3,
|
||||||
|
Div4,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Interrupt handler.
|
||||||
|
pub struct InterruptHandler<T: Instance> {
|
||||||
|
_phantom: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
|
||||||
|
unsafe fn on_interrupt() {
|
||||||
|
if T::regs().sr().read().eoc() {
|
||||||
|
T::regs().cr1().modify(|w| w.set_eocie(false));
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
T::state().waker.wake();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_vref<T: Instance>(op: i8) {
|
||||||
|
static VREF_STATUS: core::sync::atomic::AtomicU8 = core::sync::atomic::AtomicU8::new(0);
|
||||||
|
|
||||||
|
if op > 0 {
|
||||||
|
if VREF_STATUS.fetch_add(1, core::sync::atomic::Ordering::SeqCst) == 0 {
|
||||||
|
T::regs().ccr().modify(|w| w.set_tsvrefe(true));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if VREF_STATUS.fetch_sub(1, core::sync::atomic::Ordering::SeqCst) == 1 {
|
||||||
|
T::regs().ccr().modify(|w| w.set_tsvrefe(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Vref<T: Instance>(core::marker::PhantomData<T>);
|
||||||
|
impl<T: Instance> AdcPin<T> for Vref<T> {}
|
||||||
|
impl<T: Instance> super::sealed::AdcPin<T> for Vref<T> {
|
||||||
|
fn channel(&self) -> u8 {
|
||||||
|
17
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> Vref<T> {
|
||||||
|
/// The value that vref would be if vdda was at 3000mv
|
||||||
|
pub fn calibrated_value(&self) -> u16 {
|
||||||
|
crate::pac::VREFINTCAL.data().read().value()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn calibrate(&mut self, adc: &mut Adc<'_, T>) -> Calibration {
|
||||||
|
let vref_val = adc.read(self).await;
|
||||||
|
Calibration {
|
||||||
|
vref_cal: self.calibrated_value(),
|
||||||
|
vref_val,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Calibration {
|
||||||
|
vref_cal: u16,
|
||||||
|
vref_val: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calibration {
|
||||||
|
/// The millivolts that the calibration value was measured at
|
||||||
|
pub const CALIBRATION_UV: u32 = 3_000_000;
|
||||||
|
|
||||||
|
/// Returns the measured VddA in microvolts (uV)
|
||||||
|
pub fn vdda_uv(&self) -> u32 {
|
||||||
|
(Self::CALIBRATION_UV * self.vref_cal as u32) / self.vref_val as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the measured VddA as an f32
|
||||||
|
pub fn vdda_f32(&self) -> f32 {
|
||||||
|
(Self::CALIBRATION_UV as f32 / 1_000.0) * (self.vref_cal as f32 / self.vref_val as f32)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a calibrated voltage value as in microvolts (uV)
|
||||||
|
pub fn cal_uv(&self, raw: u16, resolution: super::Resolution) -> u32 {
|
||||||
|
(self.vdda_uv() / resolution.to_max_count()) * raw as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a calibrated voltage value as an f32
|
||||||
|
pub fn cal_f32(&self, raw: u16, resolution: super::Resolution) -> f32 {
|
||||||
|
raw as f32 * self.vdda_f32() / resolution.to_max_count() as f32
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> Drop for Vref<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
update_vref::<T>(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Temperature<T: Instance>(core::marker::PhantomData<T>);
|
||||||
|
impl<T: Instance> AdcPin<T> for Temperature<T> {}
|
||||||
|
impl<T: Instance> super::sealed::AdcPin<T> for Temperature<T> {
|
||||||
|
fn channel(&self) -> u8 {
|
||||||
|
16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Instance> Drop for Temperature<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
update_vref::<T>(-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Adc<'d, T> {
|
||||||
|
pub fn new(
|
||||||
|
adc: impl Peripheral<P = T> + 'd,
|
||||||
|
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
|
||||||
|
) -> Self {
|
||||||
|
into_ref!(adc);
|
||||||
|
|
||||||
|
T::enable_and_reset();
|
||||||
|
|
||||||
|
//let r = T::regs();
|
||||||
|
//r.cr2().write(|w| w.set_align(true));
|
||||||
|
|
||||||
|
T::Interrupt::unpend();
|
||||||
|
unsafe {
|
||||||
|
T::Interrupt::enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
Self { adc }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn freq() -> Hertz {
|
||||||
|
let div = T::regs().ccr().read().adcpre() + 1;
|
||||||
|
ADC_FREQ / div as u32
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn set_resolution(&mut self, res: Resolution) {
|
||||||
|
let was_on = Self::is_on();
|
||||||
|
if was_on {
|
||||||
|
self.stop_adc().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
T::regs().cr1().modify(|w| w.set_res(res.into()));
|
||||||
|
|
||||||
|
if was_on {
|
||||||
|
self.start_adc().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolution(&self) -> Resolution {
|
||||||
|
T::regs().cr1().read().res().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_vref(&self) -> Vref<T> {
|
||||||
|
update_vref::<T>(1);
|
||||||
|
|
||||||
|
Vref(core::marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_temperature(&self) -> Temperature<T> {
|
||||||
|
T::regs().ccr().modify(|w| w.set_tsvrefe(true));
|
||||||
|
|
||||||
|
Temperature::<T>(core::marker::PhantomData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Perform a single conversion.
|
||||||
|
async fn convert(&mut self) -> u16 {
|
||||||
|
let was_on = Self::is_on();
|
||||||
|
|
||||||
|
if !was_on {
|
||||||
|
self.start_adc().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.wait_sample_ready().await;
|
||||||
|
|
||||||
|
T::regs().sr().write(|_| {});
|
||||||
|
T::regs().cr1().modify(|w| {
|
||||||
|
w.set_eocie(true);
|
||||||
|
w.set_scan(false);
|
||||||
|
});
|
||||||
|
T::regs().cr2().modify(|w| {
|
||||||
|
w.set_swstart(true);
|
||||||
|
w.set_cont(false);
|
||||||
|
}); // swstart cleared by HW
|
||||||
|
|
||||||
|
let res = poll_fn(|cx| {
|
||||||
|
T::state().waker.register(cx.waker());
|
||||||
|
|
||||||
|
if T::regs().sr().read().eoc() {
|
||||||
|
let res = T::regs().dr().read().rdata();
|
||||||
|
Poll::Ready(res)
|
||||||
|
} else {
|
||||||
|
Poll::Pending
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if !was_on {
|
||||||
|
self.stop_adc().await;
|
||||||
|
}
|
||||||
|
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn is_on() -> bool {
|
||||||
|
T::regs().sr().read().adons() || T::regs().cr2().read().adon()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start_adc(&self) {
|
||||||
|
//defmt::trace!("Turn ADC on");
|
||||||
|
T::regs().cr2().modify(|w| w.set_adon(true));
|
||||||
|
//defmt::trace!("Waiting for ADC to turn on");
|
||||||
|
|
||||||
|
let mut t = Instant::now();
|
||||||
|
|
||||||
|
while !T::regs().sr().read().adons() {
|
||||||
|
yield_now().await;
|
||||||
|
if t.elapsed() > embassy_time::Duration::from_millis(1000) {
|
||||||
|
t = Instant::now();
|
||||||
|
//defmt::trace!("ADC still not on");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//defmt::trace!("ADC on");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn stop_adc(&self) {
|
||||||
|
if T::regs().cr2().read().adon() {
|
||||||
|
//defmt::trace!("ADC should be on, wait for it to start");
|
||||||
|
while !T::regs().csr().read().adons1() {
|
||||||
|
yield_now().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//defmt::trace!("Turn ADC off");
|
||||||
|
|
||||||
|
T::regs().cr2().modify(|w| w.set_adon(false));
|
||||||
|
|
||||||
|
//defmt::trace!("Waiting for ADC to turn off");
|
||||||
|
|
||||||
|
while T::regs().csr().read().adons1() {
|
||||||
|
yield_now().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
|
||||||
|
self.set_sample_sequence(&[pin.channel()]).await;
|
||||||
|
self.convert().await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn wait_sample_ready(&self) {
|
||||||
|
//trace!("Waiting for sample channel to be ready");
|
||||||
|
while T::regs().sr().read().rcnr() {
|
||||||
|
yield_now().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
self.stop_adc().await;
|
||||||
|
unsafe {
|
||||||
|
Self::set_channel_sample_time(pin.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())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the channel sample time
|
||||||
|
///
|
||||||
|
/// ## SAFETY:
|
||||||
|
/// - ADON == 0 i.e ADC must not be enabled when this is called.
|
||||||
|
unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
|
||||||
|
let sample_time = sample_time.into();
|
||||||
|
|
||||||
|
match ch {
|
||||||
|
0..=9 => T::regs().smpr3().modify(|reg| reg.set_smp(ch as _, sample_time)),
|
||||||
|
10..=19 => T::regs()
|
||||||
|
.smpr2()
|
||||||
|
.modify(|reg| reg.set_smp(ch as usize - 10, sample_time)),
|
||||||
|
20..=29 => T::regs()
|
||||||
|
.smpr1()
|
||||||
|
.modify(|reg| reg.set_smp(ch as usize - 20, sample_time)),
|
||||||
|
30..=31 => T::regs()
|
||||||
|
.smpr0()
|
||||||
|
.modify(|reg| reg.set_smp(ch as usize - 30, sample_time)),
|
||||||
|
_ => panic!("Invalid channel to sample"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_channel_sample_time(ch: u8) -> SampleTime {
|
||||||
|
match ch {
|
||||||
|
0..=9 => T::regs().smpr3().read().smp(ch as _),
|
||||||
|
10..=19 => T::regs().smpr2().read().smp(ch as usize - 10),
|
||||||
|
20..=29 => T::regs().smpr1().read().smp(ch as usize - 20),
|
||||||
|
30..=31 => T::regs().smpr0().read().smp(ch as usize - 30),
|
||||||
|
_ => panic!("Invalid channel to sample"),
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the sequence to sample the ADC. Must be less than 28 elements.
|
||||||
|
async fn set_sample_sequence(&self, sequence: &[u8]) {
|
||||||
|
assert!(sequence.len() <= 28);
|
||||||
|
let mut iter = sequence.iter();
|
||||||
|
T::regs().sqr1().modify(|w| w.set_l((sequence.len() - 1) as _));
|
||||||
|
for (idx, ch) in iter.by_ref().take(6).enumerate() {
|
||||||
|
T::regs().sqr5().modify(|w| w.set_sq(idx, *ch));
|
||||||
|
}
|
||||||
|
for (idx, ch) in iter.by_ref().take(6).enumerate() {
|
||||||
|
T::regs().sqr4().modify(|w| w.set_sq(idx, *ch));
|
||||||
|
}
|
||||||
|
for (idx, ch) in iter.by_ref().take(6).enumerate() {
|
||||||
|
T::regs().sqr3().modify(|w| w.set_sq(idx, *ch));
|
||||||
|
}
|
||||||
|
for (idx, ch) in iter.by_ref().take(6).enumerate() {
|
||||||
|
T::regs().sqr2().modify(|w| w.set_sq(idx, *ch));
|
||||||
|
}
|
||||||
|
for (idx, ch) in iter.by_ref().take(4).enumerate() {
|
||||||
|
T::regs().sqr1().modify(|w| w.set_sq(idx, *ch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_res_clks(res: Resolution) -> u32 {
|
||||||
|
match res {
|
||||||
|
Resolution::TwelveBit => 12,
|
||||||
|
Resolution::TenBit => 11,
|
||||||
|
Resolution::EightBit => 9,
|
||||||
|
Resolution::SixBit => 7,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_sample_time_clks(sample_time: SampleTime) -> u32 {
|
||||||
|
match sample_time {
|
||||||
|
SampleTime::Cycles4 => 4,
|
||||||
|
SampleTime::Cycles9 => 9,
|
||||||
|
SampleTime::Cycles16 => 16,
|
||||||
|
SampleTime::Cycles24 => 24,
|
||||||
|
SampleTime::Cycles48 => 48,
|
||||||
|
SampleTime::Cycles96 => 96,
|
||||||
|
SampleTime::Cycles192 => 192,
|
||||||
|
SampleTime::Cycles384 => 384,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
|
||||||
|
let res_clks = Self::get_res_clks(self.resolution());
|
||||||
|
let us_clks = us * Self::freq().0 / 1_000_000;
|
||||||
|
let clks = us_clks.saturating_sub(res_clks);
|
||||||
|
match clks {
|
||||||
|
0..=4 => SampleTime::Cycles4,
|
||||||
|
5..=9 => SampleTime::Cycles9,
|
||||||
|
10..=16 => SampleTime::Cycles16,
|
||||||
|
17..=24 => SampleTime::Cycles24,
|
||||||
|
25..=48 => SampleTime::Cycles48,
|
||||||
|
49..=96 => SampleTime::Cycles96,
|
||||||
|
97..=192 => SampleTime::Cycles192,
|
||||||
|
193.. => SampleTime::Cycles384,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn us_for_cfg(&self, res: Resolution, sample_time: SampleTime) -> u32 {
|
||||||
|
let res_clks = Self::get_res_clks(res);
|
||||||
|
let sample_clks = Self::get_sample_time_clks(sample_time);
|
||||||
|
(res_clks + sample_clks) * 1_000_000 / Self::freq().0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, T: Instance> Drop for Adc<'d, T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
while !T::regs().sr().read().adons() {}
|
||||||
|
|
||||||
|
T::regs().cr2().modify(|w| w.set_adon(false));
|
||||||
|
|
||||||
|
T::disable();
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
#[cfg(not(adc_f3_v2))]
|
#[cfg(not(adc_f3_v2))]
|
||||||
#[cfg_attr(adc_f1, path = "f1.rs")]
|
#[cfg_attr(adc_f1, path = "f1.rs")]
|
||||||
#[cfg_attr(adc_f3, path = "f3.rs")]
|
#[cfg_attr(adc_f3, path = "f3.rs")]
|
||||||
|
#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
|
||||||
#[cfg_attr(adc_v1, path = "v1.rs")]
|
#[cfg_attr(adc_v1, path = "v1.rs")]
|
||||||
#[cfg_attr(adc_v2, path = "v2.rs")]
|
#[cfg_attr(adc_v2, path = "v2.rs")]
|
||||||
#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
|
#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
|
||||||
@ -26,20 +27,20 @@ use crate::peripherals;
|
|||||||
pub struct Adc<'d, T: Instance> {
|
pub struct Adc<'d, T: Instance> {
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
adc: crate::PeripheralRef<'d, T>,
|
adc: crate::PeripheralRef<'d, T>,
|
||||||
#[cfg(not(adc_f3_v2))]
|
#[cfg(not(any(adc_f3_v2, adc_f3_v1_1)))]
|
||||||
sample_time: SampleTime,
|
sample_time: SampleTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
|
||||||
use embassy_sync::waitqueue::AtomicWaker;
|
use embassy_sync::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
|
||||||
pub struct State {
|
pub struct State {
|
||||||
pub waker: AtomicWaker,
|
pub waker: AtomicWaker,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
|
||||||
impl State {
|
impl State {
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -54,11 +55,11 @@ pub(crate) mod sealed {
|
|||||||
|
|
||||||
pub trait Instance: InterruptableInstance {
|
pub trait Instance: InterruptableInstance {
|
||||||
fn regs() -> crate::pac::adc::Adc;
|
fn regs() -> crate::pac::adc::Adc;
|
||||||
#[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
|
#[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
||||||
fn common_regs() -> crate::pac::adccommon::AdcCommon;
|
fn common_regs() -> crate::pac::adccommon::AdcCommon;
|
||||||
#[cfg(adc_f3)]
|
#[cfg(adc_f3)]
|
||||||
fn frequency() -> crate::time::Hertz;
|
fn frequency() -> crate::time::Hertz;
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
|
||||||
fn state() -> &'static State;
|
fn state() -> &'static State;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,9 +75,9 @@ pub(crate) mod sealed {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0)))]
|
#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
|
||||||
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
|
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
|
||||||
#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_g0))]
|
#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
|
||||||
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
|
pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
|
||||||
|
|
||||||
pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
|
pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
|
||||||
@ -89,7 +90,7 @@ foreach_adc!(
|
|||||||
crate::pac::$inst
|
crate::pac::$inst
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
|
#[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
|
||||||
fn common_regs() -> crate::pac::adccommon::AdcCommon {
|
fn common_regs() -> crate::pac::adccommon::AdcCommon {
|
||||||
return crate::pac::$common_inst
|
return crate::pac::$common_inst
|
||||||
}
|
}
|
||||||
@ -99,7 +100,7 @@ foreach_adc!(
|
|||||||
unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
|
unsafe { crate::rcc::get_freqs() }.$clock.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(adc_f1, adc_f3, adc_v1))]
|
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
|
||||||
fn state() -> &'static sealed::State {
|
fn state() -> &'static sealed::State {
|
||||||
static STATE: sealed::State = sealed::State::new();
|
static STATE: sealed::State = sealed::State::new();
|
||||||
&STATE
|
&STATE
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
|
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
TwelveBit,
|
TwelveBit,
|
||||||
TenBit,
|
TenBit,
|
||||||
@ -9,6 +10,7 @@ pub enum Resolution {
|
|||||||
|
|
||||||
#[cfg(adc_v4)]
|
#[cfg(adc_v4)]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum Resolution {
|
pub enum Resolution {
|
||||||
SixteenBit,
|
SixteenBit,
|
||||||
FourteenBit,
|
FourteenBit,
|
||||||
@ -19,7 +21,7 @@ pub enum Resolution {
|
|||||||
|
|
||||||
impl Default for Resolution {
|
impl Default for Resolution {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
|
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
|
||||||
{
|
{
|
||||||
Self::TwelveBit
|
Self::TwelveBit
|
||||||
}
|
}
|
||||||
@ -40,12 +42,28 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
|
|||||||
Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
|
Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
|
||||||
Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
|
Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
|
||||||
Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
|
Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
|
||||||
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
|
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
|
||||||
Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
|
Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::pac::adc::vals::Res> for Resolution {
|
||||||
|
fn from(res: crate::pac::adc::vals::Res) -> Resolution {
|
||||||
|
match res {
|
||||||
|
#[cfg(adc_v4)]
|
||||||
|
crate::pac::adc::vals::Res::SIXTEENBIT => Resolution::SixteenBit,
|
||||||
|
#[cfg(adc_v4)]
|
||||||
|
crate::pac::adc::vals::Res::FOURTEENBITV => Resolution::FourteenBit,
|
||||||
|
crate::pac::adc::vals::Res::TWELVEBIT => Resolution::TwelveBit,
|
||||||
|
crate::pac::adc::vals::Res::TENBIT => Resolution::TenBit,
|
||||||
|
crate::pac::adc::vals::Res::EIGHTBIT => Resolution::EightBit,
|
||||||
|
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1, adc_f3_v3))]
|
||||||
|
crate::pac::adc::vals::Res::SIXBIT => Resolution::SixBit,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Resolution {
|
impl Resolution {
|
||||||
pub fn to_max_count(&self) -> u32 {
|
pub fn to_max_count(&self) -> u32 {
|
||||||
match self {
|
match self {
|
||||||
@ -56,7 +74,7 @@ impl Resolution {
|
|||||||
Resolution::TwelveBit => (1 << 12) - 1,
|
Resolution::TwelveBit => (1 << 12) - 1,
|
||||||
Resolution::TenBit => (1 << 10) - 1,
|
Resolution::TenBit => (1 << 10) - 1,
|
||||||
Resolution::EightBit => (1 << 8) - 1,
|
Resolution::EightBit => (1 << 8) - 1,
|
||||||
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
|
#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
|
||||||
Resolution::SixBit => (1 << 6) - 1,
|
Resolution::SixBit => (1 << 6) - 1,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ macro_rules! impl_sample_time {
|
|||||||
($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => {
|
($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => {
|
||||||
#[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]
|
#[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
pub enum SampleTime {
|
pub enum SampleTime {
|
||||||
$(
|
$(
|
||||||
#[doc = concat!($doc, " ADC clock cycles.")]
|
#[doc = concat!($doc, " ADC clock cycles.")]
|
||||||
@ -18,6 +19,14 @@ macro_rules! impl_sample_time {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<crate::pac::adc::vals::SampleTime> for SampleTime {
|
||||||
|
fn from(sample_time: crate::pac::adc::vals::SampleTime) -> SampleTime {
|
||||||
|
match sample_time {
|
||||||
|
$(crate::pac::adc::vals::SampleTime::$pac_variant => SampleTime::$variant),*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for SampleTime {
|
impl Default for SampleTime {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::$default
|
Self::$default
|
||||||
@ -121,3 +130,19 @@ impl_sample_time!(
|
|||||||
("601.5", Cycles601_5, CYCLES601_5)
|
("601.5", Cycles601_5, CYCLES601_5)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#[cfg(any(adc_f3_v1_1))]
|
||||||
|
impl_sample_time!(
|
||||||
|
"4",
|
||||||
|
Cycles4,
|
||||||
|
(
|
||||||
|
("4", Cycles4, CYCLES4),
|
||||||
|
("9", Cycles9, CYCLES9),
|
||||||
|
("16", Cycles16, CYCLES16),
|
||||||
|
("24", Cycles24, CYCLES24),
|
||||||
|
("48", Cycles48, CYCLES48),
|
||||||
|
("96", Cycles96, CYCLES96),
|
||||||
|
("192", Cycles192, CYCLES192),
|
||||||
|
("384", Cycles384, CYCLES384)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user