2024-02-02 14:07:25 +08:00
|
|
|
use miniconf::Tree;
|
2024-01-24 12:11:35 +08:00
|
|
|
use stm32f4xx_hal::pac::ADC2;
|
2024-01-26 16:36:28 +08:00
|
|
|
use uom::si::electric_current::ampere;
|
2024-02-07 17:18:00 +08:00
|
|
|
use crate::laser_diode::ld_ctrl::{LdCtrl, Impedance};
|
2024-01-26 11:43:53 +08:00
|
|
|
use crate::laser_diode::ld_pwr_exc_protector::{LdPwrExcProtector, self};
|
2024-01-26 12:25:26 +08:00
|
|
|
use crate::laser_diode::pd_responsitivity;
|
2024-01-26 12:10:52 +08:00
|
|
|
use core::marker::PhantomData;
|
2024-01-26 16:36:28 +08:00
|
|
|
use crate::device::sys_timer::sleep;
|
2024-01-09 15:53:24 +08:00
|
|
|
|
|
|
|
use uom::si::{
|
2024-01-09 16:53:34 +08:00
|
|
|
electric_current::milliampere,
|
|
|
|
f64::{ElectricPotential, ElectricCurrent, Power},
|
2024-01-09 15:53:24 +08:00
|
|
|
};
|
2024-01-26 16:36:28 +08:00
|
|
|
use num_traits::Float;
|
2024-01-09 15:53:24 +08:00
|
|
|
|
2024-01-26 16:36:28 +08:00
|
|
|
use uom::{si::{ISQ, SI, Quantity, ratio::ratio}, typenum::*};
|
2024-01-09 15:58:31 +08:00
|
|
|
|
|
|
|
// Volt / Ampere
|
2024-01-09 16:53:34 +08:00
|
|
|
pub type TransimpedanceUnit = Quantity<ISQ<P2, P1, N3, N2, Z0, Z0, Z0>, SI<f64>, f64>;
|
2024-01-09 15:58:31 +08:00
|
|
|
// Ampere / Volt
|
2024-01-09 16:53:34 +08:00
|
|
|
type TransconductanceUnit = Quantity<ISQ<N2, N1, P3, P2, Z0, Z0, Z0>, SI<f64>, f64>;
|
2024-01-09 15:58:31 +08:00
|
|
|
|
|
|
|
impl Settings{
|
|
|
|
pub const DAC_OUT_V_MAX: ElectricPotential = ElectricPotential {
|
|
|
|
dimension: PhantomData,
|
|
|
|
units: PhantomData,
|
|
|
|
value: 4.096,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Unit: A/V
|
2024-01-09 16:53:34 +08:00
|
|
|
const PD_MON_TRANSCONDUCTANCE: TransconductanceUnit = TransconductanceUnit {
|
2024-01-09 15:58:31 +08:00
|
|
|
dimension: PhantomData,
|
|
|
|
units: PhantomData,
|
|
|
|
value: 0.001,
|
|
|
|
};
|
|
|
|
|
2024-01-09 16:53:34 +08:00
|
|
|
const LD_DRIVE_TRANSIMPEDANCE: TransimpedanceUnit = TransimpedanceUnit {
|
2024-01-09 15:58:31 +08:00
|
|
|
dimension: PhantomData,
|
|
|
|
units: PhantomData,
|
|
|
|
value: 10.0 / 0.75,
|
|
|
|
};
|
2024-01-26 16:36:28 +08:00
|
|
|
|
|
|
|
const LD_CURRENT_STEP_SIZE: ElectricCurrent = ElectricCurrent {
|
|
|
|
dimension: PhantomData,
|
|
|
|
units: PhantomData,
|
|
|
|
value: 0.0001,
|
|
|
|
};
|
|
|
|
|
|
|
|
const LD_CURRENT_TIME_STEP_MS: u32 = 1;
|
2024-01-09 15:58:31 +08:00
|
|
|
}
|
|
|
|
|
2024-02-02 14:07:25 +08:00
|
|
|
#[derive(Clone, Debug, Tree)]
|
2024-01-09 15:53:24 +08:00
|
|
|
pub struct Settings {
|
2024-01-09 16:31:58 +08:00
|
|
|
ld_drive_current: ElectricCurrent,
|
2024-01-11 12:51:08 +08:00
|
|
|
ld_drive_current_limit: ElectricCurrent,
|
2024-02-02 14:07:25 +08:00
|
|
|
#[tree]
|
2024-01-26 12:25:26 +08:00
|
|
|
pd_responsitivity: pd_responsitivity::Parameters,
|
2024-01-09 15:53:24 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for Settings {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self {
|
|
|
|
ld_drive_current: ElectricCurrent::new::<milliampere>(0.0),
|
2024-01-11 12:51:08 +08:00
|
|
|
ld_drive_current_limit: ElectricCurrent::new::<milliampere>(0.0),
|
2024-01-26 12:25:26 +08:00
|
|
|
pd_responsitivity: pd_responsitivity::Parameters::default(),
|
2024-01-09 15:53:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-09 16:53:34 +08:00
|
|
|
pub struct LdDrive{
|
2024-01-18 16:13:08 +08:00
|
|
|
ctrl: LdCtrl,
|
2024-01-09 15:53:24 +08:00
|
|
|
settings: Settings,
|
|
|
|
}
|
|
|
|
|
2024-01-09 16:53:34 +08:00
|
|
|
impl LdDrive{
|
2024-01-26 11:43:53 +08:00
|
|
|
pub fn new(current_source: LdCtrl, pins_adc: ADC2, phy: ld_pwr_exc_protector::LdPwrExcProtectorPhy)-> Self {
|
|
|
|
LdPwrExcProtector::setup(pins_adc, phy);
|
2024-01-24 12:11:35 +08:00
|
|
|
|
2024-01-09 16:53:34 +08:00
|
|
|
LdDrive {
|
2024-01-09 15:53:24 +08:00
|
|
|
ctrl: current_source,
|
|
|
|
settings: Settings::default()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-09 16:13:42 +08:00
|
|
|
pub fn setup(&mut self) {
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::pwr_off();
|
2024-01-09 16:13:42 +08:00
|
|
|
self.ld_set_i(ElectricCurrent::new::<milliampere>(0.0));
|
|
|
|
self.ld_short();
|
|
|
|
}
|
|
|
|
|
2024-01-09 16:31:58 +08:00
|
|
|
pub fn get_ld_drive_current(&mut self) -> ElectricCurrent{
|
|
|
|
self.settings.ld_drive_current
|
|
|
|
}
|
|
|
|
|
2024-01-11 12:51:08 +08:00
|
|
|
pub fn set_ld_drive_current_limit(&mut self, i_limit: ElectricCurrent){
|
|
|
|
self.settings.ld_drive_current_limit = i_limit;
|
|
|
|
}
|
|
|
|
|
2024-01-09 15:53:24 +08:00
|
|
|
pub fn ld_short(&mut self) {
|
|
|
|
self.ctrl.ld_short_enable();
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn ld_open(&mut self) {
|
|
|
|
self.ctrl.ld_short_disable();
|
|
|
|
}
|
|
|
|
|
2024-01-26 16:40:54 +08:00
|
|
|
pub fn power_up(&mut self){
|
|
|
|
let _ = self.ctrl.set_i(ElectricCurrent::new::<milliampere>(0.0), Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::pwr_on_and_arm_protection();
|
2024-01-26 16:40:54 +08:00
|
|
|
// Wait for LD Power Supply to start up before driving current to laser diode
|
|
|
|
sleep(30);
|
|
|
|
self.ld_set_i(self.settings.ld_drive_current);
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn power_down(&mut self){
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::pwr_off();
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
2024-01-09 16:11:50 +08:00
|
|
|
pub fn get_pd_i(&mut self) -> ElectricCurrent {
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE
|
2024-01-09 16:11:50 +08:00
|
|
|
}
|
|
|
|
|
2024-01-26 16:36:28 +08:00
|
|
|
// Ramping up or down laser diode current according to preset current step size and time step.
|
2024-01-09 16:02:17 +08:00
|
|
|
pub fn ld_set_i(&mut self, i: ElectricCurrent) -> ElectricCurrent {
|
2024-01-26 16:36:28 +08:00
|
|
|
let mut prev_i_set = self.settings.ld_drive_current;
|
|
|
|
let final_i_set = i.min(self.settings.ld_drive_current_limit).max(ElectricCurrent::new::<ampere>(0.0));
|
|
|
|
|
|
|
|
let num_of_step = ((final_i_set - prev_i_set)/Settings::LD_CURRENT_STEP_SIZE).get::<ratio>().floor() as i32;
|
|
|
|
|
|
|
|
let current_step = if num_of_step.is_positive() {
|
|
|
|
Settings::LD_CURRENT_STEP_SIZE
|
|
|
|
} else {
|
|
|
|
-Settings::LD_CURRENT_STEP_SIZE
|
|
|
|
};
|
|
|
|
|
2024-02-01 16:28:25 +08:00
|
|
|
for _ in 0..num_of_step.abs() {
|
2024-01-26 16:36:28 +08:00
|
|
|
prev_i_set = prev_i_set + current_step;
|
|
|
|
let _ = self.ctrl.set_i(prev_i_set, Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
|
|
|
|
sleep(Settings::LD_CURRENT_TIME_STEP_MS);
|
|
|
|
}
|
|
|
|
let prev_i_set = self.ctrl.set_i(final_i_set, Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
|
|
|
|
|
|
|
|
self.settings.ld_drive_current = prev_i_set;
|
|
|
|
prev_i_set
|
2024-01-09 16:02:17 +08:00
|
|
|
}
|
2024-01-24 12:11:35 +08:00
|
|
|
|
|
|
|
// Set the calibrated VDDA value obtained from ADC1 calibration
|
2024-01-24 17:03:06 +08:00
|
|
|
pub fn set_pd_mon_calibrated_vdda(&mut self, val_cal: u32) {
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::set_calibrated_vdda(val_cal)
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
2024-01-26 11:43:53 +08:00
|
|
|
pub fn pd_mon_status(&mut self) -> ld_pwr_exc_protector::Status {
|
|
|
|
LdPwrExcProtector::get_status()
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn pd_mon_clear_alarm(&mut self) {
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::clear_alarm_status();
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
2024-01-26 12:25:26 +08:00
|
|
|
pub fn set_pd_responsitivity(&mut self, responsitivity: pd_responsitivity::ResponsitivityUnit){
|
2024-01-26 12:10:52 +08:00
|
|
|
self.settings.pd_responsitivity.responsitivity = responsitivity;
|
|
|
|
}
|
|
|
|
|
2024-01-26 12:53:04 +08:00
|
|
|
pub fn set_pd_dark_current(&mut self, i_dark: ElectricCurrent){
|
|
|
|
self.settings.pd_responsitivity.i_dark = i_dark;
|
|
|
|
}
|
|
|
|
|
2024-01-24 17:03:06 +08:00
|
|
|
pub fn set_ld_power_limit(&mut self, pwr_limit: Power){
|
2024-01-26 12:10:52 +08:00
|
|
|
LdPwrExcProtector::set_trigger_threshold_v(self.settings.pd_responsitivity
|
|
|
|
.get_ld_i_from_ld_pwr(pwr_limit) / Settings::PD_MON_TRANSCONDUCTANCE
|
|
|
|
);
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
|
|
|
|
2024-01-24 17:03:06 +08:00
|
|
|
pub fn set_pd_i_limit(&mut self, i: ElectricCurrent){
|
2024-01-26 11:43:53 +08:00
|
|
|
LdPwrExcProtector::set_trigger_threshold_v(i / Settings::PD_MON_TRANSCONDUCTANCE);
|
2024-01-24 12:11:35 +08:00
|
|
|
}
|
2024-01-30 13:01:33 +08:00
|
|
|
|
2024-02-07 17:18:00 +08:00
|
|
|
pub fn get_term_status(&mut self) -> Impedance {
|
|
|
|
self.ctrl.get_lf_mod_in_impedance()
|
2024-01-30 13:01:33 +08:00
|
|
|
}
|
2024-01-24 17:03:06 +08:00
|
|
|
}
|