use embedded_hal::adc::{Channel, OneShot};
use crate::gpio::Analog;
use crate::gpio::{gpioa, gpiob, gpioc};
use crate::rcc::APB2;
use crate::stm32::ADC1;
#[cfg(any(
feature = "stm32f103",
))]
use crate::stm32::ADC2;
pub struct Adc<ADC> {
rb: ADC,
sample_time: AdcSampleTime,
align: AdcAlign,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[allow(non_camel_case_types)]
pub enum AdcSampleTime {
T_1,
T_7,
T_13,
T_28,
T_41,
T_55,
T_71,
T_239,
}
impl AdcSampleTime {
pub fn default() -> Self {
AdcSampleTime::T_28
}
}
impl From<AdcSampleTime> for u8 {
fn from(val: AdcSampleTime) -> Self {
match val {
AdcSampleTime::T_1 => 0,
AdcSampleTime::T_7 => 1,
AdcSampleTime::T_13 => 2,
AdcSampleTime::T_28 => 3,
AdcSampleTime::T_41 => 4,
AdcSampleTime::T_55 => 5,
AdcSampleTime::T_71 => 6,
AdcSampleTime::T_239 => 7,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum AdcAlign {
Right,
Left,
}
impl AdcAlign {
pub fn default() -> Self {
AdcAlign::Right
}
}
impl From<AdcAlign> for u8 {
fn from(val: AdcAlign) -> Self {
match val {
AdcAlign::Right => 0,
AdcAlign::Left => 1,
}
}
}
impl From<AdcAlign> for bool {
fn from(val: AdcAlign) -> Self {
match val {
AdcAlign::Right => false,
AdcAlign::Left => true,
}
}
}
macro_rules! adc_pins {
($ADC:ident, $($pin:ty => $chan:expr),+ $(,)*) => {
$(
impl Channel<$ADC> for $pin {
type ID = u8;
fn channel() -> u8 { $chan }
}
)+
};
}
adc_pins!(ADC1,
gpioa::PA0<Analog> => 0_u8,
gpioa::PA1<Analog> => 1_u8,
gpioa::PA2<Analog> => 2_u8,
gpioa::PA3<Analog> => 3_u8,
gpioa::PA4<Analog> => 4_u8,
gpioa::PA5<Analog> => 5_u8,
gpioa::PA6<Analog> => 6_u8,
gpioa::PA7<Analog> => 7_u8,
gpiob::PB0<Analog> => 8_u8,
gpiob::PB1<Analog> => 9_u8,
gpioc::PC0<Analog> => 10_u8,
gpioc::PC1<Analog> => 11_u8,
gpioc::PC2<Analog> => 12_u8,
gpioc::PC3<Analog> => 13_u8,
gpioc::PC4<Analog> => 14_u8,
gpioc::PC5<Analog> => 15_u8,
);
#[cfg(any(
feature = "stm32f103",
))]
adc_pins!(ADC2,
gpioa::PA0<Analog> => 0_u8,
gpioa::PA1<Analog> => 1_u8,
gpioa::PA2<Analog> => 2_u8,
gpioa::PA3<Analog> => 3_u8,
gpioa::PA4<Analog> => 4_u8,
gpioa::PA5<Analog> => 5_u8,
gpioa::PA6<Analog> => 6_u8,
gpioa::PA7<Analog> => 7_u8,
gpiob::PB0<Analog> => 8_u8,
gpiob::PB1<Analog> => 9_u8,
gpioc::PC0<Analog> => 10_u8,
gpioc::PC1<Analog> => 11_u8,
gpioc::PC2<Analog> => 12_u8,
gpioc::PC3<Analog> => 13_u8,
gpioc::PC4<Analog> => 14_u8,
gpioc::PC5<Analog> => 15_u8,
);
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct StoredConfig(AdcSampleTime, AdcAlign);
macro_rules! adc_hal {
($(
$ADC:ident: (
$init:ident,
$adcxen:ident,
$adcxrst:ident
),
)+) => {
$(
impl Adc<$ADC> {
pub fn $init(adc: $ADC, apb2: &mut APB2) -> Self {
let mut s = Self {
rb: adc,
sample_time: AdcSampleTime::default(),
align: AdcAlign::default(),
};
s.enable_clock(apb2);
s.power_down();
s.reset(apb2);
s.setup_oneshot();
s.power_up();
s.calibrate();
s
}
pub fn save_cfg(&mut self) -> StoredConfig {
StoredConfig(self.sample_time, self.align)
}
pub fn restore_cfg(&mut self, cfg: StoredConfig) {
self.sample_time = cfg.0;
self.align = cfg.1;
}
pub fn default_cfg(&mut self) -> StoredConfig {
let cfg = self.save_cfg();
self.sample_time = AdcSampleTime::default();
self.align = AdcAlign::default();
cfg
}
pub fn set_sample_time(&mut self, t_samp: AdcSampleTime) {
self.sample_time = t_samp;
}
pub fn set_align(&mut self, align: AdcAlign) {
self.align = align;
}
pub fn max_sample(&self) -> u16 {
match self.align {
AdcAlign::Left => u16::max_value(),
AdcAlign::Right => (1 << 12) - 1,
}
}
fn power_up(&mut self) {
self.rb.cr2.modify(|_, w| w.adon().set_bit());
}
fn power_down(&mut self) {
self.rb.cr2.modify(|_, w| w.adon().clear_bit());
}
fn reset(&mut self, apb2: &mut APB2) {
apb2.rstr().modify(|_, w| w.$adcxrst().set_bit());
apb2.rstr().modify(|_, w| w.$adcxrst().clear_bit());
}
fn enable_clock(&mut self, apb2: &mut APB2) {
apb2.enr().modify(|_, w| w.$adcxen().set_bit());
}
fn calibrate(&mut self) {
self.rb.cr2.modify(|_, w| w.rstcal().set_bit());
while self.rb.cr2.read().rstcal().bit_is_set() {}
self.rb.cr2.modify(|_, w| w.cal().set_bit());
while self.rb.cr2.read().cal().bit_is_set() {}
}
fn setup_oneshot(&mut self) {
self.rb.cr2.modify(|_, w| w.cont().clear_bit());
self.rb.cr2.modify(|_, w| w.exttrig().set_bit());
self.rb.cr2.modify(|_, w| unsafe { w.extsel().bits(0b111) });
self.rb.cr1.modify(|_, w| w.scan().clear_bit());
self.rb.cr1.modify(|_, w| w.discen().set_bit());
self.rb.sqr1.modify(|_, w| unsafe { w.l().bits(0b0) });
}
fn set_chan_smps(&mut self, chan: u8) {
match chan {
0 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp0().bits(self.sample_time.into()) }),
1 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp1().bits(self.sample_time.into()) }),
2 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp2().bits(self.sample_time.into()) }),
3 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp3().bits(self.sample_time.into()) }),
4 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp4().bits(self.sample_time.into()) }),
5 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp5().bits(self.sample_time.into()) }),
6 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp6().bits(self.sample_time.into()) }),
7 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp7().bits(self.sample_time.into()) }),
8 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp8().bits(self.sample_time.into()) }),
9 => self
.rb
.smpr2
.modify(|_, w| unsafe { w.smp9().bits(self.sample_time.into()) }),
10 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp10().bits(self.sample_time.into()) }),
11 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp11().bits(self.sample_time.into()) }),
12 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp12().bits(self.sample_time.into()) }),
13 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp13().bits(self.sample_time.into()) }),
14 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp14().bits(self.sample_time.into()) }),
15 => self
.rb
.smpr1
.modify(|_, w| unsafe { w.smp15().bits(self.sample_time.into()) }),
_ => unreachable!(),
}
return;
}
fn convert(&mut self, chan: u8) -> u16 {
self.rb.cr2.modify(|_, w| w.align().bit(self.align.into()));
self.set_chan_smps(chan);
self.rb.sqr3.modify(|_, w| unsafe { w.sq1().bits(chan) });
self.rb.cr2.modify(|_, w| w.swstart().set_bit());
while self.rb.cr2.read().swstart().bit_is_set() {}
while self.rb.sr.read().eoc().bit_is_clear() {}
let res = self.rb.dr.read().data().bits();
res
}
}
impl<WORD, PIN> OneShot<$ADC, WORD, PIN> for Adc<$ADC>
where
WORD: From<u16>,
PIN: Channel<$ADC, ID = u8>,
{
type Error = ();
fn read(&mut self, _pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
self.power_up();
let res = self.convert(PIN::channel());
self.power_down();
Ok(res.into())
}
}
)+
}
}
#[cfg(any(
feature = "stm32f100",
feature = "stm32f101",
))]
adc_hal! {
ADC1: (
adc1,
adc1en,
adc1rst
),
}
#[cfg(any(
feature = "stm32f103",
))]
adc_hal! {
ADC1: (
adc1,
adc1en,
adc1rst
),
ADC2: (
adc2,
adc2en,
adc2rst
),
}