diff --git a/src/app.rs b/src/app.rs index d8f8274..70870f8 100644 --- a/src/app.rs +++ b/src/app.rs @@ -19,7 +19,7 @@ use egui_plot::{Corner, GridInput, GridMark, Legend, Line, Plot, PlotPoint, Poin use egui_dock::{DockArea, DockState, Style}; use egui_extras::{TableBuilder, Column}; -use crate::state::{AppState, ControlCommand, HardwareConnected, HardwareState, MeasurementDataState}; +use crate::state::{AppState, ControlCommand, HardwareConnected, HardwareState, MeasurementDataState, Mode}; use crate::logging::LoggingStates; use crate::plot::{TimeSeriesPlot, BodePlot}; @@ -56,9 +56,7 @@ pub struct App { tree: DockState, tab_viewer: TabViewer, tab_active: TabActive, - run_impedancemeter_tx: mpsc::Sender, log_tx: mpsc::Sender, - pub on: Arc>, pub gui_logging_state: Arc>, log_filename: String, log_marker_modal: bool, @@ -70,7 +68,6 @@ pub struct App { } struct TabViewer { - on: Arc>, show_settings: bool, show_settings_toggle: Option, measurement_data: Arc, @@ -148,8 +145,8 @@ impl TabViewer { let settings = CollapsingHeader::new("Settings") .open(self.show_settings_toggle) .show(ui, |ui| { - if let Ok(on) = self.on.lock() { - ui.add_enabled_ui(!*on, |ui| { + if let running = self.hardware_state_rx.borrow().running { + ui.add_enabled_ui(!running, |ui| { ui.horizontal(|ui| { ui.label("Lead Mode:"); @@ -180,7 +177,7 @@ impl TabViewer { ui.horizontal(|ui| { // Show lead configuration ui.label("Lead Configuration:"); - let hardware_connected = self.hardware_state_rx.borrow().connected; + let hardware_connected = self.hardware_state_rx.borrow().hardware_connected; let lead_mode = self.app_state_rx.borrow().lead_mode; let mut settings = self.app_state_rx.borrow().electrode_settings; @@ -206,7 +203,7 @@ impl TabViewer { } }); }); - ui.add_enabled_ui(!*on, |ui| { + ui.add_enabled_ui(!running, |ui| { ui.horizontal(|ui| { ui.label("Single Frequency:"); let mut freq = self.app_state_rx.borrow().single_frequency; @@ -232,10 +229,10 @@ impl TabViewer { }; }); }); - ui.add_enabled_ui(*on, |ui| { + ui.add_enabled_ui(running, |ui| { ui.horizontal(|ui| { ui.label("Periods per DFT:"); - match (*on, self.hardware_state_rx.borrow().periods_per_dft) { + match (running, self.hardware_state_rx.borrow().periods_per_dft) { (true, Some(periods)) => { ui.add(Label::new(format!("{:.2}", periods))); }, @@ -306,8 +303,8 @@ impl TabViewer { let settings = CollapsingHeader::new("Settings") .open(self.show_settings_toggle) .show(ui, |ui| { - if let Ok(on) = self.on.lock() { - ui.add_enabled_ui(!*on, |ui| { + if let running = self.hardware_state_rx.borrow().running { + ui.add_enabled_ui(!running, |ui| { ui.horizontal(|ui| { ui.label("Lead Mode:"); @@ -338,7 +335,7 @@ impl TabViewer { ui.horizontal(|ui| { // Show lead configuration ui.label("Lead Configuration:"); - let hardware_connected = self.hardware_state_rx.borrow().connected; + let hardware_connected = self.hardware_state_rx.borrow().hardware_connected; let lead_mode = self.app_state_rx.borrow().lead_mode; let mut settings = self.app_state_rx.borrow().electrode_settings; @@ -363,7 +360,7 @@ impl TabViewer { } }); }); - ui.add_enabled_ui(!*on, |ui| { + ui.add_enabled_ui(!running, |ui| { ui.horizontal(|ui| { ui.label("Measurement Points:"); let mut measurement_points = self.app_state_rx.borrow().sweep_points; @@ -381,7 +378,7 @@ impl TabViewer { } }); }); - ui.add_enabled_ui(*on, |ui| { + ui.add_enabled_ui(running, |ui| { let (freq, periods_per_dft_vec) = self.hardware_state_rx.borrow().periods_per_dft_sweep.clone(); fn format_frequency(freq: u32) -> String { @@ -598,14 +595,12 @@ impl egui_dock::TabViewer for TabViewer { } impl App { - pub fn new(run_impedancemeter_tx: mpsc::Sender, - log_tx: mpsc::Sender, + pub fn new(log_tx: mpsc::Sender, measurement_data: Arc, control_tx: mpsc::Sender, app_state_rx: watch::Receiver, hardware_state_rx: watch::Receiver) -> Self { // Step 1: Initialize shared fields first - let on = Arc::new(Mutex::new(true)); let tab_active = TabActive::Single; // Step 2: Now we can initialize tab_viewer @@ -613,7 +608,6 @@ impl App { let app_state_clone = app_state_rx.clone(); let hardware_state_clone = hardware_state_rx.clone(); let tab_viewer = TabViewer { measurement_data: measurement_data.clone(), - on: on.clone(), show_settings: false, show_settings_toggle: None, control_tx: control_tx_clone, @@ -626,9 +620,7 @@ impl App { tree: DockState::new(vec!["Single".to_string(), "Sweep".to_string(), "Shortcuts".to_string()]), tab_viewer, tab_active, - run_impedancemeter_tx, log_tx, - on, gui_logging_state: Arc::new(Mutex::new(LoggingStates::Idle)), log_filename: format!("log_{}_single.csv", Local::now().format("%Y%m%d")), log_marker_modal: false, @@ -657,31 +649,20 @@ impl App { // app.bode_plot.lock().unwrap().update_magnitudes(MeasurementPointSet::Eighteen, magnitudes); // app.bode_plot.lock().unwrap().update_phases(MeasurementPointSet::Eighteen, phases); - app.update_start_stop(); + app.toggle_start_stop(); app } - pub fn update_start_stop(&self) { - match (self.tab_active, *self.on.lock().unwrap()) { - (TabActive::Single, true) => { - let lead_mode = self.app_state_rx.borrow().lead_mode; - let electrode_config = self.app_state_rx.borrow().electrode_settings.to_electrode_config(self.hardware_state_rx.borrow().connected, lead_mode); - if let Err(e) = self.run_impedancemeter_tx.try_send( - StartStopSignal::StartSingle(self.app_state_rx.borrow().single_frequency, lead_mode, electrode_config, self.app_state_rx.borrow().dft_num)) { - error!("Failed to send start command: {:?}", e); - } + pub fn toggle_start_stop(&self) { + match (self.tab_active, self.hardware_state_rx.borrow().running) { + (TabActive::Single, false) => { + self.control_tx.try_send(ControlCommand::Start(Mode::Single)).unwrap(); }, - (TabActive::Sweep, true) => { - let lead_mode = self.app_state_rx.borrow().lead_mode; - let electrode_config = self.app_state_rx.borrow().electrode_settings.to_electrode_config(self.hardware_state_rx.borrow().connected, lead_mode); - if let Err(e) = self.run_impedancemeter_tx.try_send(StartStopSignal::StartSweep(lead_mode, electrode_config, self.app_state_rx.borrow().sweep_points)) { - error!("Failed to send start command: {:?}", e); - } + (TabActive::Sweep, false) => { + self.control_tx.try_send(ControlCommand::Start(Mode::Sweep)).unwrap(); }, - (_, false) => { - if let Err(e) = self.run_impedancemeter_tx.try_send(StartStopSignal::Stop) { - error!("Failed to send stop command: {:?}", e); - } + (_, true) => { + self.control_tx.try_send(ControlCommand::Stop).unwrap(); }, (_, _) => {} } @@ -698,7 +679,7 @@ impl eframe::App for App { // Egui add a top bar egui::TopBottomPanel::top("top_bar").show(ctx, |ui| { egui::MenuBar::new().ui(ui, |ui| { - let is_connected = self.hardware_state_rx.borrow().connected != HardwareConnected::None; + let is_connected = self.hardware_state_rx.borrow().hardware_connected != HardwareConnected::None; egui::widgets::global_theme_preference_switch(ui); ui.separator(); @@ -707,9 +688,9 @@ impl eframe::App for App { ui.separator(); - let on = *self.on.lock().unwrap(); + let running = self.hardware_state_rx.borrow().running; - let (color, text) = match on { + let (color, text) = match running { true => (Color32::DARK_RED, "Stop"), false => (Color32::DARK_GREEN, "Start"), }; @@ -724,8 +705,7 @@ impl eframe::App for App { .frame(true); if ui.add_enabled(is_connected, start_stop_button).clicked() { - *self.on.lock().unwrap() = !on; - self.update_start_stop(); + self.toggle_start_stop(); } ui.separator(); @@ -742,7 +722,7 @@ impl eframe::App for App { let mut logging_enabled = !matches!(gui_logging_state, LoggingStates::Idle); - if ui.add_enabled(is_connected, toggle_start_stop(&mut logging_enabled)).changed() { + if ui.add_enabled(is_connected, custom_toggle_widget(&mut logging_enabled)).changed() { let signal = match gui_logging_state { LoggingStates::Idle => LoggingSignal::StartFileLogging(self.log_filename.clone()), LoggingStates::Starting | LoggingStates::Logging => LoggingSignal::StopFileLogging, @@ -818,7 +798,7 @@ impl eframe::App for App { // Spacer to push the LED to the right ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { ui.scope(|ui| { - let (color, tooltip) = match self.hardware_state_rx.borrow().connected { + let (color, tooltip) = match self.hardware_state_rx.borrow().hardware_connected { HardwareConnected::None => { (Color32::DARK_RED, "Disconnected") }, @@ -863,8 +843,7 @@ impl eframe::App for App { "Single" => { if self.tab_active != TabActive::Single { self.tab_active = TabActive::Single; - *self.on.lock().unwrap() = false; - self.update_start_stop(); + self.control_tx.try_send(ControlCommand::Stop).unwrap(); if *self.gui_logging_state.lock().unwrap() == LoggingStates::Logging { self.log_tx.try_send(LoggingSignal::StopFileLogging).unwrap_or_else(|e| { error!("Failed to send logging logging signal: {:?}", e); @@ -877,8 +856,7 @@ impl eframe::App for App { "Sweep" => { if self.tab_active != TabActive::Sweep { self.tab_active = TabActive::Sweep; - *self.on.lock().unwrap() = false; - self.update_start_stop(); + self.control_tx.try_send(ControlCommand::Stop).unwrap(); if *self.gui_logging_state.lock().unwrap() == LoggingStates::Logging { self.log_tx.try_send(LoggingSignal::StopFileLogging).unwrap_or_else(|e| { error!("Failed to send logging logging signal: {:?}", e); @@ -917,15 +895,12 @@ impl eframe::App for App { // Space to start/stop measurement if ctx.input(|i| i.key_pressed(Key::Space)) { - let value = *self.on.lock().unwrap(); - *self.on.lock().unwrap() = !value; - self.update_start_stop(); + self.toggle_start_stop(); } // Send stop command when the window is closed if ctx.input(|i| i.viewport().close_requested()) { - *self.on.lock().unwrap() = false; - self.update_start_stop(); + self.toggle_start_stop(); } // Reset view @@ -1007,6 +982,6 @@ fn toggle_ui_start_stop(ui: &mut egui::Ui, on: &mut bool) -> egui::Response { response } -pub fn toggle_start_stop(on: &mut bool) -> impl egui::Widget + '_ { +pub fn custom_toggle_widget(on: &mut bool) -> impl egui::Widget + '_ { move |ui: &mut egui::Ui| toggle_ui_start_stop(ui, on) } \ No newline at end of file diff --git a/src/bin/main_gui.rs b/src/bin/main_gui.rs index 8b9f2fc..eff2ce3 100644 --- a/src/bin/main_gui.rs +++ b/src/bin/main_gui.rs @@ -17,7 +17,7 @@ use bioz_host_rs::signals::StartStopSignal; use bioz_host_rs::logging::log_data; use bioz_host_rs::state::{AppState, ControlCommand, HardwareState, MeasurementDataState}; -use bioz_host_rs::control::control_loop; +use bioz_host_rs::control::app_control_loop; #[tokio::main] async fn main() { @@ -28,21 +28,21 @@ async fn main() { // Enter the runtime so that `tokio::spawn` is available immediately. // let _enter = rt.enter(); - // Init watch for hardware state + // Init watches for hardware state and app state let (hardware_state_tx, hardware_state_rx) = watch::channel(HardwareState::default()); - - // Channel to communicate with the communication task. - let (run_impedancemeter_tx, run_impedancemeter_rx) = mpsc::channel::(2); - let run_impedancemeter_tx_clone = run_impedancemeter_tx.clone(); - - // Control layer - let (control_tx, control_rx) = mpsc::channel::(32); let (app_state_tx, app_state_rx) = watch::channel(AppState::default()); - let control_tx_clone = control_tx.clone(); + // Init control channels to update hardware and app + let (hardware_control_tx, hardware_control_rx) = mpsc::channel::(2); + let (app_control_tx, app_control_rx) = mpsc::channel::(32); + + // let run_impedancemeter_tx_clone = run_impedancemeter_tx.clone(); + let hardware_state_rx_clone = hardware_state_rx.clone(); + let hardware_control_tx_clone = hardware_control_tx.clone(); + let app_control_tx_clone = app_control_tx.clone(); tokio::spawn(async move { - control_loop(control_rx, app_state_tx).await; + app_control_loop(app_control_rx, app_state_tx, hardware_state_rx, hardware_control_tx_clone).await; }); // Init measurement data state @@ -54,7 +54,8 @@ async fn main() { let measurement_data_clone = measurement_data.clone(); - let app = App::new(run_impedancemeter_tx, log_tx, measurement_data_clone, control_tx_clone, app_state_rx, hardware_state_rx); + + let app = App::new(log_tx, measurement_data_clone, app_control_tx_clone, app_state_rx, hardware_state_rx_clone); let gui_logging_state_1 = app.gui_logging_state.clone(); let gui_logging_state_2 = app.gui_logging_state.clone(); @@ -63,18 +64,19 @@ async fn main() { tokio::spawn(async move { log_data(log_rx, gui_logging_state_1).await }); // TCP command server in separate thread - let rt = Runtime::new().expect("Unable to create Runtime"); - let tcp_run_impedancemeter_tx = run_impedancemeter_tx_clone.clone(); - std::thread::spawn(move || { - rt.block_on(bioz_host_rs::tcp::tcp_command_server(tcp_run_impedancemeter_tx)); - }); + // let rt = Runtime::new().expect("Unable to create Runtime"); + + // let tcp_run_impedancemeter_tx = hardware_control_tx.clone(); + // std::thread::spawn(move || { + // rt.block_on(bioz_host_rs::tcp::tcp_command_server(tcp_run_impedancemeter_tx)); + // }); // Execute the runtime in its own thread. let rt = Runtime::new().expect("Unable to create Runtime"); std::thread::spawn(move || { rt.block_on(communicate_with_hardware( - run_impedancemeter_rx, - run_impedancemeter_tx_clone, + hardware_control_rx, + hardware_control_tx, measurement_data, hardware_state_tx, gui_logging_state_2, diff --git a/src/communication.rs b/src/communication.rs index a965182..aa359bd 100644 --- a/src/communication.rs +++ b/src/communication.rs @@ -6,7 +6,6 @@ use tokio::select; use tokio::sync::{watch, mpsc::{Receiver, Sender}}; use std::sync::atomic::{AtomicU32, Ordering}; -use atomic_float::AtomicF32; use std::sync::{Arc, Mutex}; @@ -18,15 +17,14 @@ use crate::icd; use crate::client::WorkbookClient; use crate::logging::LoggingStates; -use crate::plot::{TimeSeriesPlot, BodePlot}; use crate::signals::{LoggingSignal, StartStopSignal}; use crate::state::HardwareConnected; pub async fn communicate_with_hardware( - mut run_impedancemeter_rx: Receiver, - run_impedancemeter_tx: Sender, + mut hardware_control_rx: Receiver, + hardware_control_tx: Sender, measurement_data: Arc, hardware_state_tx: watch::Sender, gui_logging_state: Arc>, @@ -57,16 +55,16 @@ pub async fn communicate_with_hardware( Ok(client) => { info!("Connected to hardware successfully."); if let Some(mode) = settings.lock().unwrap().mode { - run_impedancemeter_tx.send(mode).await.unwrap(); + hardware_control_tx.send(mode).await.unwrap(); } match client.get_device_info().await.unwrap() { MultiplexerCapability::Absent => { - hardware_state.connected = HardwareConnected::WithoutMultiplexer; + hardware_state.hardware_connected = HardwareConnected::WithoutMultiplexer; hardware_state_tx.send(hardware_state.clone()).unwrap(); info!("Connected device: Without Multiplexer"); }, MultiplexerCapability::Present => { - hardware_state.connected = HardwareConnected::WithMultiplexer; + hardware_state.hardware_connected = HardwareConnected::WithMultiplexer; hardware_state_tx.send(hardware_state.clone()).unwrap(); info!("Connected device: With Multiplexer"); }, @@ -189,13 +187,14 @@ pub async fn communicate_with_hardware( let log_tx_clone = log_tx.clone(); loop { select! { - Some(frequency) = run_impedancemeter_rx.recv() => { + Some(frequency) = hardware_control_rx.recv() => { match frequency { StartStopSignal::StartSingle(freq, lead_mode, electrode_config, dft_num) => { match workbook_client.start_impedancemeter_single(freq, lead_mode, electrode_config, dft_num).await { Ok(Ok(periods)) => { info!("Impedance meter started at frequency: {} with periods per DFT: {}", freq, periods); settings.lock().unwrap().mode = Some(StartStopSignal::StartSingle(freq, lead_mode, electrode_config, dft_num)); + hardware_state.running = true; hardware_state.periods_per_dft = Some(periods); hardware_state_tx.send(hardware_state.clone()).unwrap(); @@ -208,11 +207,13 @@ pub async fn communicate_with_hardware( }, Ok(Err(e)) => { error!("Failed to init on hardware: {:?}", e); + hardware_state.running = false; hardware_state.periods_per_dft = None; hardware_state_tx.send(hardware_state.clone()).unwrap(); }, Err(e) => { error!("Communication error when starting impedancemeter: {:?}", e); + hardware_state.running = false; hardware_state.periods_per_dft = None; hardware_state_tx.send(hardware_state.clone()).unwrap(); } @@ -221,8 +222,9 @@ pub async fn communicate_with_hardware( StartStopSignal::StartSweep(lead_mode, electrode_config, num_points) => { match workbook_client.start_impedancemeter_sweep(lead_mode, electrode_config, num_points).await { Ok(Ok(periods)) => { - settings.lock().unwrap().mode = Some(StartStopSignal::StartSweep(lead_mode, electrode_config, num_points)); info!("Sweep Impedancemeter started."); + settings.lock().unwrap().mode = Some(StartStopSignal::StartSweep(lead_mode, electrode_config, num_points)); + hardware_state.running = true; match num_points { SweepPoints::Eight => { hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), Some(periods.periods_per_dft_8.into_iter().collect())); @@ -245,11 +247,13 @@ pub async fn communicate_with_hardware( Ok(Err(e)) => { error!("Failed to sweep-init on hardware: {:?}", e); hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), None); + hardware_state.running = false; hardware_state_tx.send(hardware_state.clone()).unwrap(); }, Err(e) => { error!("Communication error when starting impedancemeter: {:?}", e); hardware_state.periods_per_dft_sweep = (num_points.values().iter().copied().collect(), None); + hardware_state.running = false; hardware_state_tx.send(hardware_state.clone()).unwrap(); } } @@ -259,6 +263,7 @@ pub async fn communicate_with_hardware( error!("Failed to stop impedancemeter: {:?}", e); } else { settings.lock().unwrap().mode = Some(StartStopSignal::Stop); + hardware_state.running = false; hardware_state.periods_per_dft = None; let (freq, _) = hardware_state.periods_per_dft_sweep.clone(); hardware_state.periods_per_dft_sweep = (freq, None); @@ -282,7 +287,7 @@ pub async fn communicate_with_hardware( } } info!("Communication with hardware ended."); - hardware_state.connected = HardwareConnected::None; + hardware_state.hardware_connected = HardwareConnected::None; hardware_state_tx.send(hardware_state).unwrap(); tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; } diff --git a/src/control.rs b/src/control.rs index ae022d9..7a383c4 100644 --- a/src/control.rs +++ b/src/control.rs @@ -1,11 +1,16 @@ use log::info; -use tokio::sync::{mpsc::Receiver, watch::Sender}; -use crate::{state::{AppState, ControlCommand}}; +use tokio::sync::{mpsc, watch}; +use crate::{signals::StartStopSignal, state::{AppState, ControlCommand, HardwareConnected, HardwareState}}; -pub async fn control_loop(mut rx: Receiver, tx: Sender) { +use crate::state::Mode; + +pub async fn app_control_loop(mut app_control_rx: mpsc::Receiver, + app_state_tx: watch::Sender, + hardware_state_rx: watch::Receiver, + hardware_control_tx: mpsc::Sender) { let mut state = AppState::default(); - while let Some(cmd) = rx.recv().await { + while let Some(cmd) = app_control_rx.recv().await { match cmd { ControlCommand::SetFrequency(freq) => { state.single_frequency = freq; @@ -27,14 +32,46 @@ pub async fn control_loop(mut rx: Receiver, tx: Sender state.sweep_points = sweep_points; info!("Sweep points changed to {:?}!", sweep_points); } - ControlCommand::Start => { - info!("Starting impedance hardware..."); + ControlCommand::Start(mode) => { + state.mode = mode; + info!("Starting impedance hardware with mode {:?}...", mode); + + match (mode, hardware_state_rx.borrow().hardware_connected) { + (Mode::Single, HardwareConnected::WithoutMultiplexer) => { + info!("Starting single measurement..."); + hardware_control_tx.try_send(StartStopSignal::StartSingle( + state.single_frequency, state.lead_mode, None, state.dft_num)).unwrap(); + } + (Mode::Single, HardwareConnected::WithMultiplexer) => { + info!("Starting single measurement..."); + let electrode_config = state.electrode_settings.to_electrode_config(hardware_state_rx.borrow().hardware_connected, state.lead_mode); + hardware_control_tx.try_send(StartStopSignal::StartSingle( + state.single_frequency, state.lead_mode, electrode_config, state.dft_num)).unwrap(); + } + (Mode::Sweep, HardwareConnected::WithoutMultiplexer) => { + info!("Starting sweep measurement..."); + hardware_control_tx.try_send(StartStopSignal::StartSweep( + state.lead_mode, None, state.sweep_points)).unwrap(); + } + (Mode::Sweep, HardwareConnected::WithMultiplexer) => { + info!("Starting sweep measurement..."); + let electrode_config = state.electrode_settings.to_electrode_config(hardware_state_rx.borrow().hardware_connected, state.lead_mode); + hardware_control_tx.try_send(StartStopSignal::StartSweep( + state.lead_mode, electrode_config, state.sweep_points)).unwrap(); + } + (_, HardwareConnected::None) => { + info!("Cannot start measurement: No hardware connected!"); + } + } } ControlCommand::Stop => { info!("Stopping impedance hardware..."); + if let Err(e) = hardware_control_tx.try_send(StartStopSignal::Stop) { + info!("Failed to send stop command: {:?}", e); + } } } - tx.send(state.clone()).unwrap(); + app_state_tx.send(state.clone()).unwrap(); } } \ No newline at end of file diff --git a/src/state.rs b/src/state.rs index d9ca3d6..e16305d 100644 --- a/src/state.rs +++ b/src/state.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, Mutex}; use crate::icd::{BioImpedanceLeadMode, IcdDftNum, SweepPoints, ElectrodeConfiguration, ElectrodeOptionsWithMultiplexer}; +use crate::logging::LoggingStates; use crate::plot::{TimeSeriesPlot, BodePlot}; use atomic_float::AtomicF32; @@ -44,7 +45,7 @@ pub enum ControlCommand { ChangeDftNum(IcdDftNum), ChangeElectrodeSettings(ElectrodeSettings), ChangeSweepPoints(SweepPoints), - Start, + Start(Mode), Stop, } @@ -92,24 +93,33 @@ impl ElectrodeSettings { } } +#[derive(Clone, Copy, Debug)] +pub enum Mode { + Single, + Sweep, +} // Application state that can be shared across the app and updated by the control loop #[derive(Clone, Copy, Debug)] pub struct AppState { + pub mode: Mode, pub single_frequency: u32, pub lead_mode: BioImpedanceLeadMode, pub dft_num: IcdDftNum, pub electrode_settings: ElectrodeSettings, pub sweep_points: SweepPoints, + pub logging: LoggingStates, } impl Default for AppState { fn default() -> Self { Self { + mode: Mode::Single, single_frequency: 50000, - lead_mode: BioImpedanceLeadMode::TwoLead, + lead_mode: BioImpedanceLeadMode::FourLead, dft_num: IcdDftNum::Num2048, electrode_settings: ElectrodeSettings::new(), sweep_points: SweepPoints::Eighteen, + logging: LoggingStates::Idle, } } } @@ -117,8 +127,8 @@ impl Default for AppState { // Hardware state that can be shared across the app and updated by the hardware loop #[derive(Clone, Debug)] pub struct HardwareState { - pub connected: HardwareConnected, - // pub running: bool, + pub hardware_connected: HardwareConnected, + pub running: bool, pub periods_per_dft: Option, pub periods_per_dft_sweep: (Vec, Option>), } @@ -126,10 +136,11 @@ pub struct HardwareState { impl Default for HardwareState { fn default() -> Self { Self { - connected: HardwareConnected::None, - // running: false, + hardware_connected: HardwareConnected::None, + running: false, periods_per_dft: None, periods_per_dft_sweep: (SweepPoints::Eighteen.values().to_vec(), None), } } -} \ No newline at end of file +} +