use miniconf::Miniconf; use stm32f4xx_hal::pac::ADC2; use crate::laser_diode::ld_ctrl::LdCtrl; use crate::laser_diode::analog_wdg::{LdAnalogWdg, self}; use core::{marker::PhantomData, f64::NAN}; use uom::si::{ electric_current::milliampere, f64::{ElectricPotential, ElectricCurrent, Power}, }; use uom::{si::{ISQ, SI, Quantity}, typenum::*}; // Volt / Ampere pub type TransimpedanceUnit = Quantity, SI, f64>; // Ampere / Volt type TransconductanceUnit = Quantity, SI, f64>; // Watt / Ampere pub type IToPowerUnit = Quantity, SI, f64>; impl Settings{ pub const DAC_OUT_V_MAX: ElectricPotential = ElectricPotential { dimension: PhantomData, units: PhantomData, value: 4.096, }; // Unit: A/V const PD_MON_TRANSCONDUCTANCE: TransconductanceUnit = TransconductanceUnit { dimension: PhantomData, units: PhantomData, value: 0.001, }; const LD_DRIVE_TRANSIMPEDANCE: TransimpedanceUnit = TransimpedanceUnit { dimension: PhantomData, units: PhantomData, value: 10.0 / 0.75, }; } #[derive(Clone, Debug, Miniconf)] pub struct Settings { ld_drive_current: ElectricCurrent, ld_drive_current_limit: ElectricCurrent, pd_i_to_out_pwr: IToPowerUnit, } impl Default for Settings { fn default() -> Self { Self { ld_drive_current: ElectricCurrent::new::(0.0), ld_drive_current_limit: ElectricCurrent::new::(0.0), pd_i_to_out_pwr: IToPowerUnit {dimension: PhantomData, units: PhantomData, value: NAN} } } } pub struct LdDrive{ ctrl: LdCtrl, settings: Settings, } impl LdDrive{ pub fn new(current_source: LdCtrl, pins_adc: ADC2, phy: analog_wdg::LdAnalogWdgPhy)-> Self { LdAnalogWdg::setup(pins_adc, phy); LdDrive { ctrl: current_source, settings: Settings::default() } } pub fn setup(&mut self) { LdAnalogWdg::pwr_off(); self.ld_set_i(ElectricCurrent::new::(0.0)); self.ld_short(); } pub fn get_ld_drive_current(&mut self) -> ElectricCurrent{ self.settings.ld_drive_current } pub fn set_ld_drive_current_limit(&mut self, i_limit: ElectricCurrent){ self.settings.ld_drive_current_limit = i_limit; } pub fn ld_short(&mut self) { self.ctrl.ld_short_enable(); } pub fn ld_open(&mut self) { self.ctrl.ld_short_disable(); } pub fn power_up(&mut self){ LdAnalogWdg::pwr_on_and_arm_protection(); } pub fn power_down(&mut self){ LdAnalogWdg::pwr_off(); } pub fn get_pd_i(&mut self) -> ElectricCurrent { LdAnalogWdg::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE } pub fn ld_set_i(&mut self, i: ElectricCurrent) -> ElectricCurrent { let ld_i_set = i.min(self.settings.ld_drive_current_limit); let ld_i_set = self.ctrl.set_i(ld_i_set, Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX); self.settings.ld_drive_current = ld_i_set; ld_i_set } // Set the calibrated VDDA value obtained from ADC1 calibration pub fn set_pd_mon_calibrated_vdda(&mut self, val_cal: u32) { LdAnalogWdg::set_calibrated_vdda(val_cal) } pub fn pd_mon_status(&mut self) -> analog_wdg::Status { LdAnalogWdg::get_status() } pub fn pd_mon_clear_alarm(&mut self) { LdAnalogWdg::clear_alarm_status(); } pub fn set_ld_power_limit(&mut self, pwr_limit: Power){ // LdAnalogWdg::set_trigger_threshold_v(convert pwr_limit to raw adc code) unimplemented!() } pub fn set_pd_i_limit(&mut self, i: ElectricCurrent){ LdAnalogWdg::set_trigger_threshold_v(i / Settings::PD_MON_TRANSCONDUCTANCE); } pub fn set_pd_v_limit(&mut self, v: ElectricPotential){ LdAnalogWdg::set_trigger_threshold_v(v); } }