1 desktop: add LSV point density config, remove auto/manual toggle
This commit is contained in:
parent
a21b014d89
commit
090fcfa2f5
130
cue/src/app.rs
130
cue/src/app.rs
|
|
@ -17,6 +17,25 @@ use crate::protocol::{
|
||||||
use crate::storage::{self, Session, Storage};
|
use crate::storage::{self, Session, Storage};
|
||||||
use crate::udp::UdpEvent;
|
use crate::udp::UdpEvent;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum LsvDensityMode {
|
||||||
|
PtsPerMv,
|
||||||
|
PtsPerSec,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LsvDensityMode {
|
||||||
|
pub const ALL: &[Self] = &[Self::PtsPerMv, Self::PtsPerSec];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for LsvDensityMode {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::PtsPerMv => f.write_str("pts/mV"),
|
||||||
|
Self::PtsPerSec => f.write_str("pts/s"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Tab {
|
pub enum Tab {
|
||||||
Eis,
|
Eis,
|
||||||
|
|
@ -71,6 +90,8 @@ pub enum Message {
|
||||||
LsvStopVChanged(String),
|
LsvStopVChanged(String),
|
||||||
LsvScanRateChanged(String),
|
LsvScanRateChanged(String),
|
||||||
LsvRtiaSelected(LpRtia),
|
LsvRtiaSelected(LpRtia),
|
||||||
|
LsvDensityModeSelected(LsvDensityMode),
|
||||||
|
LsvDensityChanged(String),
|
||||||
StartLsv,
|
StartLsv,
|
||||||
/* Amperometry */
|
/* Amperometry */
|
||||||
AmpVholdChanged(String),
|
AmpVholdChanged(String),
|
||||||
|
|
@ -133,13 +154,22 @@ pub enum Message {
|
||||||
BrowseBack,
|
BrowseBack,
|
||||||
ExportSession(i64),
|
ExportSession(i64),
|
||||||
ImportSession,
|
ImportSession,
|
||||||
/* LSV analysis */
|
|
||||||
LsvToggleManual,
|
|
||||||
/* Misc */
|
/* Misc */
|
||||||
Reconnect,
|
Reconnect,
|
||||||
UdpAddrChanged(String),
|
UdpAddrChanged(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lsv_calc_points(v_start: f32, v_stop: f32, scan_rate: f32, density: f32, mode: LsvDensityMode) -> u16 {
|
||||||
|
let range = (v_stop - v_start).abs();
|
||||||
|
let raw = match mode {
|
||||||
|
LsvDensityMode::PtsPerMv => range * density,
|
||||||
|
LsvDensityMode::PtsPerSec => {
|
||||||
|
if scan_rate.abs() < 0.001 { 2.0 } else { (range / scan_rate.abs()) * density }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
(raw as u16).clamp(2, 500)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
tab: Tab,
|
tab: Tab,
|
||||||
status: String,
|
status: String,
|
||||||
|
|
@ -181,8 +211,9 @@ pub struct App {
|
||||||
lsv_stop_v: String,
|
lsv_stop_v: String,
|
||||||
lsv_scan_rate: String,
|
lsv_scan_rate: String,
|
||||||
lsv_rtia: LpRtia,
|
lsv_rtia: LpRtia,
|
||||||
|
lsv_density_mode: LsvDensityMode,
|
||||||
|
lsv_density: String,
|
||||||
lsv_peaks: Vec<crate::lsv_analysis::LsvPeak>,
|
lsv_peaks: Vec<crate::lsv_analysis::LsvPeak>,
|
||||||
lsv_manual_peaks: bool,
|
|
||||||
lsv_data: text_editor::Content,
|
lsv_data: text_editor::Content,
|
||||||
|
|
||||||
/* Amp */
|
/* Amp */
|
||||||
|
|
@ -426,8 +457,9 @@ impl App {
|
||||||
lsv_stop_v: "500".into(),
|
lsv_stop_v: "500".into(),
|
||||||
lsv_scan_rate: "50".into(),
|
lsv_scan_rate: "50".into(),
|
||||||
lsv_rtia: LpRtia::R10K,
|
lsv_rtia: LpRtia::R10K,
|
||||||
|
lsv_density_mode: LsvDensityMode::PtsPerMv,
|
||||||
|
lsv_density: "1".into(),
|
||||||
lsv_peaks: Vec::new(),
|
lsv_peaks: Vec::new(),
|
||||||
lsv_manual_peaks: false,
|
|
||||||
lsv_data: text_editor::Content::with_text(&fmt_lsv(&[])),
|
lsv_data: text_editor::Content::with_text(&fmt_lsv(&[])),
|
||||||
|
|
||||||
amp_points: Vec::new(),
|
amp_points: Vec::new(),
|
||||||
|
|
@ -659,9 +691,7 @@ impl App {
|
||||||
if let Some(sid) = self.current_session {
|
if let Some(sid) = self.current_session {
|
||||||
self.save_lsv(sid);
|
self.save_lsv(sid);
|
||||||
}
|
}
|
||||||
if !self.lsv_manual_peaks {
|
self.lsv_peaks = crate::lsv_analysis::detect_peaks(&self.lsv_points);
|
||||||
self.lsv_peaks = crate::lsv_analysis::detect_peaks(&self.lsv_points);
|
|
||||||
}
|
|
||||||
let mut st = format!("LSV complete: {} points", self.lsv_points.len());
|
let mut st = format!("LSV complete: {} points", self.lsv_points.len());
|
||||||
if let (Some(s), Some(o)) = (self.ph_slope, self.ph_offset) {
|
if let (Some(s), Some(o)) = (self.ph_slope, self.ph_offset) {
|
||||||
if let Some(peak) = crate::lsv_analysis::detect_qhq_peak(&self.lsv_points) {
|
if let Some(peak) = crate::lsv_analysis::detect_qhq_peak(&self.lsv_points) {
|
||||||
|
|
@ -850,20 +880,22 @@ impl App {
|
||||||
Message::LsvStopVChanged(s) => self.lsv_stop_v = s,
|
Message::LsvStopVChanged(s) => self.lsv_stop_v = s,
|
||||||
Message::LsvScanRateChanged(s) => self.lsv_scan_rate = s,
|
Message::LsvScanRateChanged(s) => self.lsv_scan_rate = s,
|
||||||
Message::LsvRtiaSelected(r) => self.lsv_rtia = r,
|
Message::LsvRtiaSelected(r) => self.lsv_rtia = r,
|
||||||
|
Message::LsvDensityModeSelected(m) => {
|
||||||
|
self.lsv_density_mode = m;
|
||||||
|
self.lsv_density = match m {
|
||||||
|
LsvDensityMode::PtsPerMv => "1".into(),
|
||||||
|
LsvDensityMode::PtsPerSec => "100".into(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Message::LsvDensityChanged(s) => self.lsv_density = s,
|
||||||
Message::StartLsv => {
|
Message::StartLsv => {
|
||||||
let vs = self.lsv_start_v.parse::<f32>().unwrap_or(0.0);
|
let vs = self.lsv_start_v.parse::<f32>().unwrap_or(0.0);
|
||||||
let ve = self.lsv_stop_v.parse::<f32>().unwrap_or(500.0);
|
let ve = self.lsv_stop_v.parse::<f32>().unwrap_or(500.0);
|
||||||
let sr = self.lsv_scan_rate.parse::<f32>().unwrap_or(50.0);
|
let sr = self.lsv_scan_rate.parse::<f32>().unwrap_or(50.0);
|
||||||
|
let density = self.lsv_density.parse::<f32>().unwrap_or(1.0);
|
||||||
|
let n = lsv_calc_points(vs, ve, sr, density, self.lsv_density_mode);
|
||||||
self.send_cmd(&protocol::build_sysex_get_temp());
|
self.send_cmd(&protocol::build_sysex_get_temp());
|
||||||
self.send_cmd(&protocol::build_sysex_start_lsv(vs, ve, sr, self.lsv_rtia));
|
self.send_cmd(&protocol::build_sysex_start_lsv(vs, ve, sr, self.lsv_rtia, n));
|
||||||
}
|
|
||||||
Message::LsvToggleManual => {
|
|
||||||
self.lsv_manual_peaks = !self.lsv_manual_peaks;
|
|
||||||
if self.lsv_manual_peaks {
|
|
||||||
self.lsv_peaks.clear();
|
|
||||||
} else {
|
|
||||||
self.lsv_peaks = crate::lsv_analysis::detect_peaks(&self.lsv_points);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* Amp */
|
/* Amp */
|
||||||
Message::AmpVholdChanged(s) => self.amp_v_hold = s,
|
Message::AmpVholdChanged(s) => self.amp_v_hold = s,
|
||||||
|
|
@ -1540,31 +1572,47 @@ impl App {
|
||||||
.align_y(iced::Alignment::End)
|
.align_y(iced::Alignment::End)
|
||||||
.into(),
|
.into(),
|
||||||
|
|
||||||
Tab::Lsv => row![
|
Tab::Lsv => {
|
||||||
column![
|
let vs = self.lsv_start_v.parse::<f32>().unwrap_or(0.0);
|
||||||
text("Start mV").size(12),
|
let ve = self.lsv_stop_v.parse::<f32>().unwrap_or(500.0);
|
||||||
text_input("0", &self.lsv_start_v).on_input(Message::LsvStartVChanged).width(80),
|
let sr = self.lsv_scan_rate.parse::<f32>().unwrap_or(50.0);
|
||||||
].spacing(2),
|
let d = self.lsv_density.parse::<f32>().unwrap_or(1.0);
|
||||||
column![
|
let n = lsv_calc_points(vs, ve, sr, d, self.lsv_density_mode);
|
||||||
text("Stop mV").size(12),
|
row![
|
||||||
text_input("500", &self.lsv_stop_v).on_input(Message::LsvStopVChanged).width(80),
|
column![
|
||||||
].spacing(2),
|
text("Start mV").size(12),
|
||||||
column![
|
text_input("0", &self.lsv_start_v).on_input(Message::LsvStartVChanged).width(80),
|
||||||
text("Scan mV/s").size(12),
|
].spacing(2),
|
||||||
text_input("50", &self.lsv_scan_rate).on_input(Message::LsvScanRateChanged).width(80),
|
column![
|
||||||
].spacing(2),
|
text("Stop mV").size(12),
|
||||||
column![
|
text_input("500", &self.lsv_stop_v).on_input(Message::LsvStopVChanged).width(80),
|
||||||
text("RTIA").size(12),
|
].spacing(2),
|
||||||
pick_list(LpRtia::ALL, Some(self.lsv_rtia), Message::LsvRtiaSelected).width(Length::Shrink),
|
column![
|
||||||
].spacing(2),
|
text("Scan mV/s").size(12),
|
||||||
button(text("Start LSV").size(13))
|
text_input("50", &self.lsv_scan_rate).on_input(Message::LsvScanRateChanged).width(80),
|
||||||
.style(style_action())
|
].spacing(2),
|
||||||
.padding([6, 16])
|
column![
|
||||||
.on_press(Message::StartLsv),
|
text("RTIA").size(12),
|
||||||
button(text(if self.lsv_manual_peaks { "Manual" } else { "Auto" }).size(13))
|
pick_list(LpRtia::ALL, Some(self.lsv_rtia), Message::LsvRtiaSelected).width(Length::Shrink),
|
||||||
.padding([6, 12])
|
].spacing(2),
|
||||||
.on_press(Message::LsvToggleManual),
|
column![
|
||||||
]
|
text("Density").size(12),
|
||||||
|
pick_list(LsvDensityMode::ALL, Some(self.lsv_density_mode), Message::LsvDensityModeSelected).width(Length::Shrink),
|
||||||
|
].spacing(2),
|
||||||
|
column![
|
||||||
|
text("Value").size(12),
|
||||||
|
text_input("1", &self.lsv_density).on_input(Message::LsvDensityChanged).width(60),
|
||||||
|
].spacing(2),
|
||||||
|
column![
|
||||||
|
text("Points").size(12),
|
||||||
|
text(format!("{}", n)).size(13),
|
||||||
|
].spacing(2),
|
||||||
|
button(text("Start LSV").size(13))
|
||||||
|
.style(style_action())
|
||||||
|
.padding([6, 16])
|
||||||
|
.on_press(Message::StartLsv),
|
||||||
|
]
|
||||||
|
}
|
||||||
.spacing(10)
|
.spacing(10)
|
||||||
.align_y(iced::Alignment::End)
|
.align_y(iced::Alignment::End)
|
||||||
.into(),
|
.into(),
|
||||||
|
|
|
||||||
|
|
@ -465,12 +465,13 @@ pub fn build_sysex_get_config() -> Vec<u8> {
|
||||||
vec![0xF0, SYSEX_MFR, CMD_GET_CONFIG, 0xF7]
|
vec![0xF0, SYSEX_MFR, CMD_GET_CONFIG, 0xF7]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_sysex_start_lsv(v_start: f32, v_stop: f32, scan_rate: f32, lp_rtia: LpRtia) -> Vec<u8> {
|
pub fn build_sysex_start_lsv(v_start: f32, v_stop: f32, scan_rate: f32, lp_rtia: LpRtia, num_points: u16) -> Vec<u8> {
|
||||||
let mut sx = vec![0xF0, SYSEX_MFR, CMD_START_LSV];
|
let mut sx = vec![0xF0, SYSEX_MFR, CMD_START_LSV];
|
||||||
sx.extend_from_slice(&encode_float(v_start));
|
sx.extend_from_slice(&encode_float(v_start));
|
||||||
sx.extend_from_slice(&encode_float(v_stop));
|
sx.extend_from_slice(&encode_float(v_stop));
|
||||||
sx.extend_from_slice(&encode_float(scan_rate));
|
sx.extend_from_slice(&encode_float(scan_rate));
|
||||||
sx.push(lp_rtia.as_byte());
|
sx.push(lp_rtia.as_byte());
|
||||||
|
sx.extend_from_slice(&encode_u16(num_points));
|
||||||
sx.push(0xF7);
|
sx.push(0xF7);
|
||||||
sx
|
sx
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue