#![cfg_attr(not(test), no_main)] #![cfg_attr(not(test), no_std)] use cortex_m_rt::entry; use log::{info, debug}; use stm32f4xx_hal::pac::{CorePeripherals, Peripherals}; mod device; mod laser_diode; mod thermostat; mod net; use device::{boot::bootup, log_setup, sys_timer}; use uom::fmt::DisplayStyle::Abbreviation; use uom::si::electric_potential::volt; use uom::si::electric_current::{ampere, milliampere}; use uom::si::f64::{ElectricPotential, ElectricCurrent}; use stm32f4xx_hal::pac::SCB; // If RTT is used, print panic info through RTT #[cfg(all(feature = "RTT", not(test)))] use {core::panic::PanicInfo, rtt_target::rprintln}; #[cfg(all(feature = "RTT", not(test)))] #[panic_handler] fn panic(info: &PanicInfo) -> ! { rprintln!("{}", info); loop {} } // Otherwise use panic halt #[cfg(all(not(feature = "RTT"), not(test)))] use panic_halt as _; static mut ETH_DATA_BUFFER: [u8; 1024] = [0; 1024]; pub struct DeviceSettings{ report_readings: bool, } #[cfg(not(test))] #[entry] fn main() -> ! { log_setup::init_log(); info!("Kirdy init"); let core_perif = CorePeripherals::take().unwrap(); let perif = Peripherals::take().unwrap(); let (mut wd, mut _flash_store, mut laser, mut thermostat,) = bootup(core_perif, perif); // Demo Fns for reading and writing stm32 Internal Flash /* let key = "test"; info!("Read the Flash Content Stored"); match flash_store.read(key).unwrap() { Some(val) => {info!("Flash Valued Read: {:?}", val)} _ => {info!("Key does not match")} } info!("Erasing Flash"); flash_store.erase().unwrap(); match flash_store.read(key).unwrap() { Some(val) => {info!("Flash Valued Read: {:?}", val)} _ => {info!("Key does not match")} } info!("Writing Flash"); let buf = [1, 2, 3, 4]; flash_store.write(key, &buf).unwrap(); info!("Reading Flash"); match flash_store.read(key).unwrap() { Some(val) => {info!("Val: {:?}", val)} _ => {info!("Key does not match")} }; */ // https://github.com/iliekturtles/uom/blob/master/examples/si.rs let volt_fmt = ElectricPotential::format_args(volt, Abbreviation); let amp_fmt = ElectricCurrent::format_args(ampere, Abbreviation); let milli_amp_fmt = ElectricCurrent::format_args(milliampere, Abbreviation); let mut should_reset = false; let mut device_settings = DeviceSettings { report_readings: false, }; loop { wd.feed(); if !should_reset { let mut eth_is_pending = false; laser.poll_and_update_output_current(); if thermostat.poll_adc_and_update_pid() { if thermostat.get_temp_mon_status().over_temp_alarm { laser.power_down(); thermostat.set_pid_engaged(false); thermostat.power_down(); } info!("curr_dac_vfb: {:?}", volt_fmt.with(thermostat.get_dac_vfb())); info!("curr_vref: {:?}", volt_fmt.with(thermostat.get_vref())); info!("curr_tec_i: {:?}", amp_fmt.with(thermostat.get_tec_i())); info!("curr_tec_v: {:?}", volt_fmt.with(thermostat.get_tec_v())); info!("curr_ld_drive_cuurent: {:?}", milli_amp_fmt.with(laser.get_ld_drive_current())); info!("pd_mon_v: {:?}", volt_fmt.with(laser.pd_mon_status().v)); info!("power_excursion: {:?}", laser.pd_mon_status().pwr_excursion); info!("Termination Status: {:?}", laser.get_term_status()); if net::net::eth_is_socket_active() { if device_settings.report_readings { unsafe { net::cmd_handler::send_status_report(&mut ETH_DATA_BUFFER, &mut laser, &mut thermostat); } } } } if net::net::eth_is_socket_active() { cortex_m::interrupt::free(|cs| { eth_is_pending = net::net::is_pending(cs); } ); if eth_is_pending { unsafe{ cortex_m::interrupt::free(|cs| { net::net::clear_pending(cs); }); let bytes = net::net::eth_recv(&mut ETH_DATA_BUFFER); debug!("Number of bytes recv: {:?}", bytes); (laser, thermostat, should_reset, device_settings) = net::cmd_handler::execute_cmd(&mut ETH_DATA_BUFFER, bytes, laser, thermostat, device_settings); } } } else { device_settings.report_readings = false; } } else { // Should reset, close all TCP sockets. let mut any_socket_alive = false; if net::net::eth_is_socket_active() { net::net::eth_close_socket(); any_socket_alive = true; } // Must let loop run for one more cycle to poll server for RST to be sent, // this makes sure system does not reset right after socket.abort() is called. if !any_socket_alive { SCB::sys_reset(); } } } }