use super::hal::{
adc,
gpio::{gpioa::*, gpiob::*, gpioc::*, gpiof::*, Analog},
hal::blocking::delay::DelayUs,
prelude::*,
rcc::{rec, CoreClocks},
stm32::{ADC1, ADC2, ADC3},
};
use super::{
dac::{R_SENSE, VREF_TEC},
OutputChannelIdx,
};
const V_REF: f32 = 3.0;
pub enum Supply {
P3v3Voltage,
P5vVoltage,
P12vVoltage,
P12vCurrent,
}
pub enum AdcChannel {
OutputVoltage(OutputChannelIdx),
OutputCurrent(OutputChannelIdx),
OutputVref(OutputChannelIdx),
Supply(Supply),
}
pub struct AdcInternalPins {
pub output_voltage: (PC3<Analog>, PA0<Analog>, PA3<Analog>, PA4<Analog>),
pub output_current: (PA5<Analog>, PA6<Analog>, PB0<Analog>, PB1<Analog>),
pub output_vref: (PF3<Analog>, PF4<Analog>, PF5<Analog>, PF6<Analog>),
pub p3v3_voltage: PF7<Analog>,
pub p5v_voltage: PC0<Analog>,
pub p12v_voltage: PC2<Analog>,
pub p12v_current: PF8<Analog>,
}
pub struct AdcInternal {
adc1: adc::Adc<ADC1, adc::Enabled>,
adc3: adc::Adc<ADC3, adc::Enabled>,
pins: AdcInternalPins,
}
impl AdcInternal {
pub fn new(
delay: &mut impl DelayUs<u8>,
clocks: &CoreClocks,
adc_rcc: (rec::Adc12, rec::Adc3),
adc: (ADC1, ADC2, ADC3),
pins: AdcInternalPins,
) -> Self {
let (adc1, _adc2) = adc::adc12(adc.0, adc.1, delay, adc_rcc.0, clocks);
let adc3 = adc::Adc::adc3(adc.2, delay, adc_rcc.1, clocks);
let mut adc1 = adc1.enable();
adc1.set_resolution(adc::Resolution::SIXTEENBIT);
let mut adc3 = adc3.enable();
adc3.set_resolution(adc::Resolution::SIXTEENBIT);
AdcInternal { adc1, adc3, pins }
}
pub fn read(&mut self, ch: AdcChannel) -> f32 {
match ch {
AdcChannel::OutputVoltage(ch) => self.read_output_voltage(ch),
AdcChannel::OutputCurrent(ch) => self.read_output_current(ch),
AdcChannel::OutputVref(ch) => self.read_output_vref(ch),
AdcChannel::Supply(ch) => self.read_supply(ch),
}
}
pub fn read_output_voltage(&mut self, ch: OutputChannelIdx) -> f32 {
let p = &mut self.pins.output_voltage;
let code: u32 = match ch {
OutputChannelIdx::Zero => self.adc1.read(&mut p.0),
OutputChannelIdx::One => self.adc1.read(&mut p.1),
OutputChannelIdx::Two => self.adc1.read(&mut p.2),
OutputChannelIdx::Three => self.adc1.read(&mut p.3),
}
.unwrap();
const SCALE: f32 = -V_REF * 20.0 / 5.0; const OFFSET: f32 = -VREF_TEC / V_REF; (code as f32 / self.adc1.slope() as f32 + OFFSET) * SCALE
}
pub fn read_output_current(&mut self, ch: OutputChannelIdx) -> f32 {
let p = &mut self.pins.output_current;
let code: u32 = match ch {
OutputChannelIdx::Zero => self.adc1.read(&mut p.0),
OutputChannelIdx::One => self.adc1.read(&mut p.1),
OutputChannelIdx::Two => self.adc1.read(&mut p.2),
OutputChannelIdx::Three => self.adc1.read(&mut p.3),
}
.unwrap();
const SCALE: f32 = V_REF / R_SENSE / 8.0; const OFFSET: f32 = -VREF_TEC / V_REF; (code as f32 / self.adc1.slope() as f32 + OFFSET) * SCALE
}
pub fn read_output_vref(&mut self, ch: OutputChannelIdx) -> f32 {
let p = &mut self.pins.output_vref;
let code: u32 = match ch {
OutputChannelIdx::Zero => self.adc3.read(&mut p.0),
OutputChannelIdx::One => self.adc3.read(&mut p.1),
OutputChannelIdx::Two => self.adc3.read(&mut p.2),
OutputChannelIdx::Three => self.adc3.read(&mut p.3),
}
.unwrap();
const SCALE: f32 = V_REF;
code as f32 / self.adc3.slope() as f32 * SCALE
}
pub fn read_supply(&mut self, ch: Supply) -> f32 {
match ch {
Supply::P3v3Voltage => self.read_p3v3_voltage(),
Supply::P5vVoltage => self.read_p5v_voltage(),
Supply::P12vVoltage => self.read_p12v_voltage(),
Supply::P12vCurrent => self.read_p12v_current(),
}
}
pub fn read_p3v3_voltage(&mut self) -> f32 {
const DIV: f32 = 6.8 / (1.6 + 6.8); let code: u32 = self.adc3.read(&mut self.pins.p3v3_voltage).unwrap();
code as f32 / self.adc3.slope() as f32 * (V_REF / DIV)
}
pub fn read_p5v_voltage(&mut self) -> f32 {
const DIV: f32 = 6.8 / (10.0 + 6.8); let code: u32 = self.adc1.read(&mut self.pins.p5v_voltage).unwrap();
code as f32 / self.adc1.slope() as f32 * (V_REF / DIV)
}
pub fn read_p12v_voltage(&mut self) -> f32 {
const DIV: f32 = 1.6 / (1.6 + 6.8); let code: u32 = self.adc1.read(&mut self.pins.p12v_voltage).unwrap();
code as f32 / self.adc1.slope() as f32 * (V_REF / DIV)
}
pub fn read_p12v_current(&mut self) -> f32 {
const GAIN: f32 = 0.005 * (10000.0 / 100.0); let code: u32 = self.adc3.read(&mut self.pins.p12v_current).unwrap();
code as f32 / self.adc3.slope() as f32 * (V_REF / GAIN)
}
}