kirdy/src/laser_diode/laser_diode.rs

256 lines
8.5 KiB
Rust
Raw Normal View History

use miniconf::Tree;
use stm32f4xx_hal::timer::CounterUs;
use stm32f4xx_hal::pac::{ADC3, TIM2};
use uom::si::electric_current::ampere;
use uom::si::power::milliwatt;
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;
use crate::laser_diode::ld_current_out_ctrl_timer::LdCurrentOutCtrlTimer;
use core::marker::PhantomData;
use crate::device::sys_timer::sleep;
2024-02-19 15:08:00 +08:00
use serde::{Deserialize, Serialize};
use uom::si::{
2024-01-09 16:53:34 +08:00
electric_current::milliampere,
f32::{ElectricPotential, ElectricCurrent, Power},
};
use uom::{si::{ISQ, SI, Quantity}, typenum::*};
// Volt / Ampere
pub type TransimpedanceUnit = Quantity<ISQ<P2, P1, N3, N2, Z0, Z0, Z0>, SI<f32>, f32>;
// Ampere / Volt
type TransconductanceUnit = Quantity<ISQ<N2, N1, P3, P2, Z0, Z0, Z0>, SI<f32>, f32>;
impl Settings{
pub const LD_CURRENT_MAX: ElectricCurrent = ElectricCurrent {
dimension: PhantomData,
units: PhantomData,
value: 0.3,
};
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 {
dimension: PhantomData,
units: PhantomData,
value: 0.001,
};
2024-01-09 16:53:34 +08:00
const LD_DRIVE_TRANSIMPEDANCE: TransimpedanceUnit = TransimpedanceUnit {
dimension: PhantomData,
units: PhantomData,
value: 10.0 / 0.75,
};
}
#[derive(Deserialize, Serialize, Clone, Copy, Debug, Tree)]
struct Settings {
pwr_on: bool,
default_pwr_on: bool,
ld_drive_current: ElectricCurrent,
2024-01-11 12:51:08 +08:00
ld_drive_current_limit: ElectricCurrent,
2024-01-26 12:25:26 +08:00
pd_responsitivity: pd_responsitivity::Parameters,
ld_pwr_limit: Power,
}
impl Default for Settings {
fn default() -> Self {
Self {
pwr_on: false,
default_pwr_on: false,
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(),
ld_pwr_limit: Power::new::<milliwatt>(0.0),
}
}
}
2024-02-19 15:08:00 +08:00
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
pub struct StatusReport {
pwr_on: bool,
2024-02-19 15:08:00 +08:00
pwr_excursion: bool,
ld_i_set: ElectricCurrent,
pd_i: ElectricCurrent,
pd_pwr: Power,
term_status: Impedance,
}
2024-01-09 16:53:34 +08:00
pub struct LdDrive{
2024-01-18 16:13:08 +08:00
ctrl: LdCtrl,
settings: Settings,
}
2024-01-09 16:53:34 +08:00
impl LdDrive{
pub fn new(current_source: LdCtrl, pins_adc: ADC3, tim2: CounterUs<TIM2>, phy: ld_pwr_exc_protector::LdPwrExcProtectorPhy)-> Self {
2024-01-26 11:43:53 +08:00
LdPwrExcProtector::setup(pins_adc, phy);
LdCurrentOutCtrlTimer::setup(tim2);
2024-01-09 16:53:34 +08:00
LdDrive {
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();
self.ctrl.set_i(ElectricCurrent::new::<milliampere>(0.0), Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
self.set_ld_drive_current_limit(Settings::LD_CURRENT_MAX);
LdCurrentOutCtrlTimer::reset();
2024-01-09 16:13:42 +08:00
self.ld_short();
}
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.min(Settings::LD_CURRENT_MAX);
2024-01-11 12:51:08 +08:00
}
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){
let prev_i_set = self.settings.ld_drive_current;
LdCurrentOutCtrlTimer::reset();
let _ = self.ctrl.set_i(ElectricCurrent::new::<milliampere>(0.0), Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
// Wait for the DAC to reset its voltage back to 0V
sleep(35);
2024-01-26 11:43:53 +08:00
LdPwrExcProtector::pwr_on_and_arm_protection();
// Wait for LD Power Supply to start up before driving current to laser diode
sleep(30);
self.ld_set_i(prev_i_set);
self.settings.pwr_on = true;
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();
self.settings.pwr_on = false;
2024-01-24 12:11:35 +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-02-19 15:08:00 +08:00
pub fn get_pd_pwr(&mut self) -> Power {
self.settings.pd_responsitivity.get_ld_pwr_from_ld_i(LdPwrExcProtector::get_status().v * Settings::PD_MON_TRANSCONDUCTANCE)
}
pub fn ld_set_i(&mut self, i: ElectricCurrent){
self.settings.ld_drive_current = i;
LdCurrentOutCtrlTimer::set_target_i_and_listen_irq(i, self.ctrl.get_i_set());
}
pub fn poll_and_update_output_current(&mut self) -> ElectricCurrent {
match LdCurrentOutCtrlTimer::get_irq_status() {
Some(i_set) => {
let i_set = self.ctrl.set_i(i_set, Settings::LD_DRIVE_TRANSIMPEDANCE, Settings::DAC_OUT_V_MAX);
LdCurrentOutCtrlTimer::clear_alarm_and_resume_listening();
i_set
}
None => {
ElectricCurrent::new::<ampere>(0.0)
}
}
}
2024-01-24 12:11:35 +08:00
// Set the calibrated VDDA value obtained from ADC1 calibration
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
}
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-02-22 16:44:45 +08:00
self.settings.pd_responsitivity.set(responsitivity);
}
2024-01-26 12:53:04 +08:00
pub fn set_pd_dark_current(&mut self, i_dark: ElectricCurrent){
2024-02-22 16:44:45 +08:00
self.settings.pd_responsitivity.set_i_dark(i_dark);
2024-01-26 12:53:04 +08:00
}
pub fn set_ld_power_limit(&mut self, pwr_limit: Power){
LdPwrExcProtector::set_trigger_threshold_v(self.settings.pd_responsitivity
.get_ld_i_from_ld_pwr(pwr_limit) / Settings::PD_MON_TRANSCONDUCTANCE
);
2024-04-03 10:47:01 +08:00
self.settings.ld_pwr_limit = pwr_limit;
2024-01-24 12:11:35 +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
}
pub fn set_default_pwr_on(&mut self, pwr_on: bool){
self.settings.default_pwr_on = pwr_on;
}
pub fn get_term_status(&mut self) -> Impedance {
self.ctrl.get_lf_mod_in_impedance()
}
2024-02-19 15:08:00 +08:00
pub fn get_status_report(&mut self) -> StatusReport {
let ld_i_set = if LdPwrExcProtector::get_status().pwr_engaged {
self.ctrl.get_i_set()
} else {
ElectricCurrent::new::<ampere>(0.0)
};
2024-02-19 15:08:00 +08:00
StatusReport {
pwr_on: LdPwrExcProtector::get_status().pwr_engaged,
2024-02-19 15:08:00 +08:00
pwr_excursion: LdPwrExcProtector::get_status().pwr_excursion,
ld_i_set: ld_i_set,
2024-02-19 15:08:00 +08:00
pd_i: self.get_pd_i(),
pd_pwr: self.get_pd_pwr(),
term_status: self.get_term_status(),
}
}
pub fn get_settings_summary(&mut self) -> LdSettingsSummary {
let settings = self.settings;
LdSettingsSummary {
default_pwr_on: self.settings.default_pwr_on,
ld_drive_current: LdSettingsSummaryField { value: settings.ld_drive_current, max: Settings::LD_CURRENT_MAX},
ld_drive_current_limit: LdSettingsSummaryField { value: settings.ld_drive_current_limit, max: Settings::LD_CURRENT_MAX},
pd_responsitivity: settings.pd_responsitivity,
ld_pwr_limit: settings.ld_pwr_limit,
}
}
pub fn load_settings_from_summary(&mut self, settings: LdSettingsSummary) {
self.power_down();
self.settings.ld_drive_current = settings.ld_drive_current.value;
self.settings.ld_drive_current_limit = settings.ld_drive_current_limit.value;
self.settings.pd_responsitivity = settings.pd_responsitivity;
self.settings.ld_pwr_limit = settings.ld_pwr_limit;
if settings.default_pwr_on {
self.power_up();
} else {
self.power_down();
}
}
}
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
pub struct LdSettingsSummary {
default_pwr_on: bool,
ld_drive_current: LdSettingsSummaryField<ElectricCurrent>,
ld_drive_current_limit: LdSettingsSummaryField<ElectricCurrent>,
pd_responsitivity: pd_responsitivity::Parameters,
ld_pwr_limit: Power,
}
#[derive(Deserialize, Serialize, Copy, Clone, Debug, Tree)]
pub struct LdSettingsSummaryField<T> {
value: T,
max: T,
}