forked from M-Labs/kirdy
laser diode: Add Analog Watchdog initial commit
- rm pid_state for laser diode
This commit is contained in:
parent
095fe8ea69
commit
c02181c80c
|
@ -0,0 +1,208 @@
|
||||||
|
// stm32f4xx_hal does not provide config and driver for analog watchdog yet
|
||||||
|
use stm32f4xx_hal::{
|
||||||
|
pac::{ADC2, NVIC},
|
||||||
|
gpio::{Analog, Output, PushPull, gpioa::PA3, gpiod::PD9},
|
||||||
|
interrupt,
|
||||||
|
};
|
||||||
|
use uom::si::electric_potential::millivolt;
|
||||||
|
use uom::si::f64::ElectricPotential;
|
||||||
|
|
||||||
|
// 12 bit Resolution
|
||||||
|
const MAX_SAMPLE: u16 = 4095;
|
||||||
|
|
||||||
|
pub type LdPwrEnPinType = PD9<Output<PushPull>>;
|
||||||
|
pub type PdMonAdcPinType = PA3<Analog>;
|
||||||
|
|
||||||
|
static mut ANALOG_WDG: Option<LdAnalogWdg> = None;
|
||||||
|
|
||||||
|
pub struct LdAnalogWdgPhy {
|
||||||
|
// To make sure PA3 is configured to Analog mode
|
||||||
|
pub _pd_mon_ch0: PdMonAdcPinType,
|
||||||
|
pub pwr_en_ch0: LdPwrEnPinType,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AlarmStatus {
|
||||||
|
alarm: bool,
|
||||||
|
val: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LdAnalogWdg {
|
||||||
|
pac: ADC2,
|
||||||
|
phy: LdAnalogWdgPhy,
|
||||||
|
alarm_status: AlarmStatus,
|
||||||
|
//Calibrated VDDA in millivolt from Adc<ADC1>.calibrate()
|
||||||
|
calibrated_vdda: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LdAnalogWdg {
|
||||||
|
/// ADC interrupt is disabled and continuous conversion is started by default
|
||||||
|
pub fn setup(pac: ADC2, phy: LdAnalogWdgPhy){
|
||||||
|
unsafe { ANALOG_WDG = Some(LdAnalogWdg{
|
||||||
|
pac: pac,
|
||||||
|
phy: phy,
|
||||||
|
alarm_status: AlarmStatus {
|
||||||
|
alarm: false,
|
||||||
|
val: 0x0000,
|
||||||
|
},
|
||||||
|
calibrated_vdda: 3300,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.pac.cr1.write(|w| w
|
||||||
|
// 12 Bit Resolution
|
||||||
|
.res().twelve_bit()
|
||||||
|
// Enable Analog Watchdog on Single Regular Channel
|
||||||
|
.awden().enabled()
|
||||||
|
.awdsgl().single_channel()
|
||||||
|
.jawden().disabled()
|
||||||
|
// Disable Analog Watchdog Interrupt
|
||||||
|
.awdie().disabled()
|
||||||
|
// Select Analog Watchdog Channel 3 (PA3) on ADC2
|
||||||
|
.awdch().bits(0x03)
|
||||||
|
);
|
||||||
|
wdg.pac.cr2.write(|w| w
|
||||||
|
// Continous Conversion mode
|
||||||
|
.cont().set_bit()
|
||||||
|
// Enable ADC
|
||||||
|
.adon().set_bit()
|
||||||
|
// Start ADC Conversion
|
||||||
|
.swstart().set_bit()
|
||||||
|
);
|
||||||
|
// Set Sampling Time for Channel 3 to 480 Cycle
|
||||||
|
wdg.pac.smpr2.write(|w| w
|
||||||
|
.smp3().cycles480()
|
||||||
|
);
|
||||||
|
// Set the high threshold to be max value initially
|
||||||
|
wdg.pac.htr.write(|w| w.bits(0xFFFF_FFFF));
|
||||||
|
// Set the high threshold to be min value initially
|
||||||
|
wdg.pac.ltr.write(|w| w.bits(0x0000_0000));
|
||||||
|
// Set the Conversion Sequence to only have Channel 3 (PA3)
|
||||||
|
wdg.pac.sqr3.write(|w| w
|
||||||
|
.sq1().bits(0x03)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get() -> Option<&'static mut Self> {
|
||||||
|
unsafe { ANALOG_WDG.as_mut() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This fn accepts the calibrated vdda value from Adc<ADC1>.calibrate()
|
||||||
|
pub fn set_calibrated_vdda(val: u32) {
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.calibrated_vdda = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_pd_v() -> ElectricPotential {
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
let sample = wdg.pac.dr.read().data().bits();
|
||||||
|
|
||||||
|
return ElectricPotential::new::<millivolt>(((u32::from(sample) * wdg.calibrated_vdda) / u32::from(MAX_SAMPLE)) as f64)
|
||||||
|
}
|
||||||
|
ElectricPotential::new::<millivolt>(0.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_alarm(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.alarm_status = AlarmStatus {
|
||||||
|
alarm: true,
|
||||||
|
val: wdg.pac.dr.read().data().bits(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_alarm_status() -> AlarmStatus {
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
return wdg.alarm_status.clone()
|
||||||
|
}
|
||||||
|
AlarmStatus {
|
||||||
|
alarm: false,
|
||||||
|
val: 0x0000,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn clear_alarm_status(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.alarm_status = AlarmStatus {
|
||||||
|
alarm: false,
|
||||||
|
val: 0x0000,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set ADC Watchdog Higher threshold register
|
||||||
|
/// Interrupt is triggered when ADC value is ABOVE the value set
|
||||||
|
pub fn set_htr(htr: u32){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.pac.htr.write(|w| unsafe {w.bits(htr)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set ADC Watchdog Lower threshold register
|
||||||
|
/// Interrupt is triggered when ADC value is BELOW the value set
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn set_ltr(ltr:u32){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.pac.ltr.write(|w| unsafe {w.bits(ltr)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn enable_watchdog_interrupt(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.pac.cr1.modify(|_, w| w
|
||||||
|
.awdie().set_bit()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn disable_watchdog_interrupt(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.pac.cr1.modify(|_, w| w
|
||||||
|
.awdie().clear_bit()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear_interrupt_bit(){
|
||||||
|
unsafe{
|
||||||
|
NVIC::unmask(interrupt::ADC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_pwr_engaged() -> bool{
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
return wdg.phy.pwr_en_ch0.is_set_high()
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pwr_engage(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.phy.pwr_en_ch0.set_high()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pwr_disengage(){
|
||||||
|
if let Some(ref mut wdg ) = LdAnalogWdg::get() {
|
||||||
|
wdg.phy.pwr_en_ch0.set_low()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interrupt]
|
||||||
|
fn ADC(){
|
||||||
|
cortex_m::interrupt::free(|_| {
|
||||||
|
LdAnalogWdg::set_alarm();
|
||||||
|
LdAnalogWdg::pwr_disengage();
|
||||||
|
// Disable interrupt to avoid getting stuck in infinite interrupt loop
|
||||||
|
LdAnalogWdg::disable_watchdog_interrupt();
|
||||||
|
LdAnalogWdg::clear_interrupt_bit();
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod ld_ctrl;
|
pub mod ld_ctrl;
|
||||||
pub mod max5719;
|
pub mod max5719;
|
||||||
pub mod laser_diode;
|
pub mod laser_diode;
|
||||||
pub mod pid_state;
|
|
||||||
pub mod pd_mon;
|
pub mod pd_mon;
|
||||||
|
pub mod analog_wdg;
|
Loading…
Reference in New Issue