changes to support efuse config
This commit is contained in:
parent
e82bdcca60
commit
30cb39fde5
|
@ -24,4 +24,5 @@ modular-bitfield = "0.11.2"
|
|||
static_assertions = "1.1.0"
|
||||
env_logger="0.9.0"
|
||||
egui-toast="0.3.0"
|
||||
chrono = "0.4.23"
|
||||
nom="7.1.1"
|
|
@ -34,6 +34,8 @@ fn main() {
|
|||
height: icon_h,
|
||||
});
|
||||
native_options.initial_window_size = Some(Vec2::new(1280.0, 720.0));
|
||||
//native_options.initial_window_size = Some(Vec2::new(1024.0, 768.0));
|
||||
//native_options.fullscreen = true;
|
||||
#[cfg(windows)]
|
||||
{
|
||||
native_options.renderer = Renderer::Wgpu;
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use std::fmt::Display;
|
||||
|
||||
use modular_bitfield::{bitfield, BitfieldSpecifier};
|
||||
|
||||
#[bitfield]
|
||||
|
@ -13,6 +15,61 @@ pub struct TcmCoreConfig {
|
|||
pub red_line_dieselrpm: u16,
|
||||
pub red_line_petrolrpm: u16,
|
||||
pub engine_type: EngineType,
|
||||
pub egs_can_type: EgsCanType,
|
||||
// Only for V1,2 and newer PCBs
|
||||
pub shifter_style: ShifterStyle,
|
||||
// Only for V1.3 and newer PCBs
|
||||
pub io_0_usage: IOPinConfig,
|
||||
pub input_sensor_pulses_per_rev: u8,
|
||||
pub output_pulse_width_per_kmh: u8,
|
||||
pub mosfet_purpose: MosfetPurpose
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
#[bits = 8]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum EgsCanType {
|
||||
UNKNOWN = 0,
|
||||
EGS51 = 1,
|
||||
EGS52 = 2,
|
||||
EGS53 = 3,
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
#[bits = 8]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ShifterStyle {
|
||||
EWM_CAN = 0,
|
||||
TRRS = 1,
|
||||
SLR_MCLAREN = 2, // NEEDS TESTING (Need to work out how this works)
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
#[bits = 8]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum IOPinConfig {
|
||||
NotConnected = 0,
|
||||
Input = 1,
|
||||
Output = 2
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
#[bits = 8]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum MosfetPurpose {
|
||||
NotConnected = 0,
|
||||
TorqueCutTrigger = 1,
|
||||
B3BrakeSolenoid = 2
|
||||
}
|
||||
|
||||
#[bitfield]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct TcmEfuseConfig {
|
||||
pub board_ver: BoardType,
|
||||
pub manf_day: u8,
|
||||
pub manf_week: u8,
|
||||
pub manf_month: u8,
|
||||
pub manf_year: u8
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
|
@ -33,3 +90,30 @@ pub enum EngineType {
|
|||
Diesel,
|
||||
Petrol,
|
||||
}
|
||||
|
||||
#[derive(BitfieldSpecifier)]
|
||||
#[bits = 8]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum BoardType {
|
||||
Unknown = 0,
|
||||
V11 = 1,
|
||||
V12 = 2,
|
||||
V13 = 3
|
||||
}
|
||||
|
||||
impl Display for BoardType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
BoardType::Unknown => write!(f, "Unknown"),
|
||||
BoardType::V11 => write!(f, "V1.1 (12/12/21)"),
|
||||
BoardType::V12 => write!(f, "V1.2 (07/07/22)"),
|
||||
BoardType::V13 => write!(f, "V1.3 (UNDER DEVELOPMENT DO NOT SELECT)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for BoardType {
|
||||
fn into(self) -> String {
|
||||
format!("{}", self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,17 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::window::PageAction;
|
||||
use chrono::{Datelike, Weekday};
|
||||
use ecu_diagnostics::{
|
||||
kwp2000::{Kwp2000DiagnosticServer, ResetMode, SessionType},
|
||||
DiagnosticServer,
|
||||
};
|
||||
use eframe::egui::Ui;
|
||||
use eframe::egui::{self, *};
|
||||
use egui_extras::RetainedImage;
|
||||
use image::{ImageFormat, DynamicImage};
|
||||
|
||||
use self::cfg_structs::{DefaultProfile, EngineType, TcmCoreConfig};
|
||||
use self::cfg_structs::{DefaultProfile, EngineType, TcmCoreConfig, TcmEfuseConfig, BoardType, EgsCanType, ShifterStyle, IOPinConfig, MosfetPurpose};
|
||||
|
||||
use super::{status_bar::MainStatusBar, StatusText};
|
||||
|
||||
|
@ -22,15 +25,41 @@ pub struct ConfigPage {
|
|||
bar: MainStatusBar,
|
||||
status: StatusText,
|
||||
scn: Option<TcmCoreConfig>,
|
||||
efuse: Option<TcmEfuseConfig>,
|
||||
show_efuse: bool,
|
||||
show_final_warning: bool,
|
||||
pcb_11_img: RetainedImage,
|
||||
pcb_12_img: RetainedImage,
|
||||
pcb_13_img: RetainedImage
|
||||
}
|
||||
|
||||
fn load_image(image: DynamicImage, name: &str) -> RetainedImage {
|
||||
let size = [image.width() as usize, image.height() as usize];
|
||||
let buffer = image.to_rgba8();
|
||||
let pixels = buffer.as_flat_samples();
|
||||
RetainedImage::from_color_image(name, ColorImage::from_rgba_unmultiplied(size, pixels.as_slice()))
|
||||
}
|
||||
|
||||
impl ConfigPage {
|
||||
pub fn new(server: Arc<Mutex<Kwp2000DiagnosticServer>>, bar: MainStatusBar) -> Self {
|
||||
let red_img = image::load_from_memory_with_format(include_bytes!("../../../res/pcb_11.jpg"), ImageFormat::Jpeg).unwrap();
|
||||
let blk_img = image::load_from_memory_with_format(include_bytes!("../../../res/pcb_12.jpg"), ImageFormat::Jpeg).unwrap();
|
||||
let bet_img = image::load_from_memory_with_format(include_bytes!("../../../res/pcb_13.jpg"), ImageFormat::Jpeg).unwrap();
|
||||
|
||||
let pcb_11_img = load_image(red_img, "V11-PCB");
|
||||
let pcb_12_img = load_image(blk_img, "V12-PCB");
|
||||
let pcb_13_img = load_image(bet_img, "V13-PCB");
|
||||
Self {
|
||||
server,
|
||||
bar,
|
||||
status: StatusText::Ok("".into()),
|
||||
scn: None,
|
||||
efuse: None,
|
||||
show_efuse: false,
|
||||
show_final_warning: false,
|
||||
pcb_11_img,
|
||||
pcb_12_img,
|
||||
pcb_13_img
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -51,11 +80,30 @@ impl crate::window::InterfacePage for ConfigPage {
|
|||
self.status = StatusText::Ok(format!("Read OK!"));
|
||||
}
|
||||
Err(e) => {
|
||||
self.status = StatusText::Err(format!("Error reading configuration: {}", e))
|
||||
self.status = StatusText::Err(format!("Error reading TCM configuration: {}", e))
|
||||
}
|
||||
}
|
||||
match self
|
||||
.server
|
||||
.lock()
|
||||
.unwrap()
|
||||
.read_custom_local_identifier(0xFD)
|
||||
{
|
||||
Ok(res) => {
|
||||
let tmp = TcmEfuseConfig::from_bytes(res.try_into().unwrap());
|
||||
if tmp.board_ver() == BoardType::Unknown {
|
||||
self.show_efuse = true;
|
||||
}
|
||||
self.efuse = Some(tmp);
|
||||
self.status = StatusText::Ok(format!("Read OK!"));
|
||||
}
|
||||
Err(e) => {
|
||||
self.status = StatusText::Err(format!("Error reading TCM EFUSE configuration: {}", e))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let board_ver = self.efuse.clone().map(|x| x.board_ver()).unwrap_or(BoardType::Unknown);
|
||||
if let Some(scn) = self.scn.borrow_mut() {
|
||||
egui::Grid::new("DGS").striped(true).show(ui, |ui| {
|
||||
let mut x = scn.is_large_nag() == 1;
|
||||
|
@ -157,9 +205,89 @@ impl crate::window::InterfacePage for ConfigPage {
|
|||
}
|
||||
ui.end_row();
|
||||
}
|
||||
|
||||
ui.label("EGS CAN Layer: ");
|
||||
let mut can = scn.egs_can_type();
|
||||
egui::ComboBox::from_id_source("can_layer")
|
||||
.width(100.0)
|
||||
.selected_text(format!("{:?}", can))
|
||||
.show_ui(ui, |cb_ui| {
|
||||
let layers = match board_ver {
|
||||
BoardType::Unknown | BoardType::V11 => vec![EgsCanType::UNKNOWN, EgsCanType::EGS52, EgsCanType::EGS53],
|
||||
_ => vec![EgsCanType::UNKNOWN, EgsCanType::EGS51, EgsCanType::EGS52, EgsCanType::EGS53]
|
||||
};
|
||||
for layer in layers {
|
||||
cb_ui.selectable_value(&mut can, layer.clone(), format!("{:?}", layer));
|
||||
}
|
||||
scn.set_egs_can_type(can)
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
if board_ver == BoardType::V12 || board_ver == BoardType::V13 { // 1.2 or 1.3 config
|
||||
ui.label("Shifter style: ");
|
||||
let mut ss = scn.shifter_style();
|
||||
egui::ComboBox::from_id_source("shifter_style")
|
||||
.width(200.0)
|
||||
.selected_text(format!("{:?}", ss))
|
||||
.show_ui(ui, |cb_ui| {
|
||||
let options = vec![ShifterStyle::EWM_CAN, ShifterStyle::TRRS, ShifterStyle::SLR_MCLAREN];
|
||||
for o in options {
|
||||
cb_ui.selectable_value(&mut ss, o.clone(), format!("{:?}", o));
|
||||
}
|
||||
scn.set_shifter_style(ss)
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
|
||||
if board_ver == BoardType::V13 { // Only v1.3 config
|
||||
ui.label("GPIO usage: ");
|
||||
let mut ss = scn.io_0_usage();
|
||||
egui::ComboBox::from_id_source("gpio_usage")
|
||||
.width(200.0)
|
||||
.selected_text(format!("{:?}", ss))
|
||||
.show_ui(ui, |cb_ui| {
|
||||
let options = vec![IOPinConfig::NotConnected, IOPinConfig::Input, IOPinConfig::Output];
|
||||
for o in options {
|
||||
cb_ui.selectable_value(&mut ss, o.clone(), format!("{:?}", o));
|
||||
}
|
||||
scn.set_io_0_usage(ss)
|
||||
});
|
||||
ui.end_row();
|
||||
|
||||
if scn.io_0_usage() == IOPinConfig::Input {
|
||||
let mut t = format!("{}", scn.input_sensor_pulses_per_rev());
|
||||
ui.label("Input sensor pulses/rev");
|
||||
ui.text_edit_singleline(&mut t);
|
||||
if let Ok(prev) = buffer.parse::<u8>() {
|
||||
scn.set_input_sensor_pulses_per_rev(prev);
|
||||
}
|
||||
ui.end_row();
|
||||
} else if scn.io_0_usage() == IOPinConfig::Output {
|
||||
let mut t = format!("{}", scn.output_pulse_width_per_kmh());
|
||||
ui.label("Pulse width (us) per kmh");
|
||||
ui.text_edit_singleline(&mut t);
|
||||
if let Ok(prev) = buffer.parse::<u8>() {
|
||||
scn.set_output_pulse_width_per_kmh(prev);
|
||||
}
|
||||
ui.end_row();
|
||||
}
|
||||
ui.label("General MOSFET usage: ");
|
||||
let mut ss = scn.mosfet_purpose();
|
||||
egui::ComboBox::from_id_source("mosfet_purpose")
|
||||
.width(200.0)
|
||||
.selected_text(format!("{:?}", ss))
|
||||
.show_ui(ui, |cb_ui| {
|
||||
let options = vec![MosfetPurpose::NotConnected, MosfetPurpose::TorqueCutTrigger, MosfetPurpose::B3BrakeSolenoid];
|
||||
for o in options {
|
||||
cb_ui.selectable_value(&mut ss, o.clone(), format!("{:?}", o));
|
||||
}
|
||||
scn.set_mosfet_purpose(ss)
|
||||
});
|
||||
ui.end_row();
|
||||
}
|
||||
});
|
||||
|
||||
if ui.button("Write configuration").clicked() {
|
||||
if ui.button("Write SCN configuration").clicked() {
|
||||
let res = {
|
||||
let mut x: Vec<u8> = vec![0x3B, 0xFE];
|
||||
x.extend_from_slice(&scn.clone().into_bytes());
|
||||
|
@ -179,6 +307,98 @@ impl crate::window::InterfacePage for ConfigPage {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(efuse) = self.efuse.borrow_mut() {
|
||||
if self.show_efuse {
|
||||
|
||||
|
||||
ui.heading("EFUSE CONFIG");
|
||||
ui.label("IMPORTANT! This can only be set once! Be careful!");
|
||||
ui.spacing();
|
||||
ui.horizontal(|row| {
|
||||
row.vertical(|col| {
|
||||
col.label("V1.1 - Red PCB (12/12/21)");
|
||||
col.image(self.pcb_11_img.texture_id(col.ctx()), Vec2::from((200.0, 150.0)));
|
||||
});
|
||||
row.separator();
|
||||
row.vertical(|col| {
|
||||
col.label("V1.2 - Black PCB (07/07/22) with TRRS support");
|
||||
col.image(self.pcb_12_img.texture_id(col.ctx()), Vec2::from((200.0, 150.0)));
|
||||
});
|
||||
row.separator();
|
||||
row.vertical(|col| {
|
||||
col.label("V1.3 - UNDER DEVELOPMENT - DO NOT SELECT!!!!");
|
||||
col.image(self.pcb_13_img.texture_id(col.ctx()), Vec2::from((230.0, 150.0)));
|
||||
});
|
||||
});
|
||||
let mut ver = efuse.board_ver();
|
||||
ui.label("Choose board variant: ");
|
||||
egui::ComboBox::from_id_source("board_ver")
|
||||
.width(100.0)
|
||||
.selected_text(format!("{:?}", efuse.board_ver()))
|
||||
.show_ui(ui, |cb_ui| {
|
||||
let profiles = vec![BoardType::V11, BoardType::V12, BoardType::V13];
|
||||
for (pos, dev) in profiles.iter().enumerate() {
|
||||
cb_ui.selectable_value(&mut ver, dev.clone(), dev.to_string());
|
||||
}
|
||||
efuse.set_board_ver(ver)
|
||||
});
|
||||
}
|
||||
if self.show_efuse && efuse.board_ver() != BoardType::Unknown {
|
||||
if ui.button("Write EFUSE configuration").clicked() {
|
||||
self.show_final_warning = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut tmp = self.show_final_warning;
|
||||
|
||||
let ss = ui.ctx().input().screen_rect();
|
||||
let mut reload = false;
|
||||
egui::Window::new("ARE YOU SURE?")
|
||||
.open(&mut self.show_final_warning)
|
||||
.fixed_pos(Pos2::new(ss.size().x / 2.0,ss.size().y / 2.0))
|
||||
.show(ui.ctx(), |win| {
|
||||
win.label("EFUSE CONFIGURATION CANNOT BE UN-DONE");
|
||||
win.label("Please double check and ensure you have selected the right board variant!");
|
||||
win.horizontal(|row| {
|
||||
if row.button("Take me back").clicked() {
|
||||
tmp = false;
|
||||
}
|
||||
if row.button("Yes, I am sure!").clicked() {
|
||||
let mut efuse = self.efuse.clone().unwrap();
|
||||
let date = chrono::Utc::now().date_naive();
|
||||
efuse.set_manf_day(date.day() as u8);
|
||||
efuse.set_manf_week(date.iso_week().week() as u8);
|
||||
efuse.set_manf_month(date.month() as u8);
|
||||
efuse.set_manf_year((date.year() - 2000) as u8);
|
||||
println!("EFUSE: {:?}", efuse);
|
||||
|
||||
let mut x = vec![0x3Bu8, 0xFD];
|
||||
x.extend_from_slice(&efuse.into_bytes());
|
||||
|
||||
|
||||
self.server
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_diagnostic_session_mode(SessionType::ExtendedDiagnostics);
|
||||
self.server
|
||||
.lock()
|
||||
.unwrap()
|
||||
.send_byte_array_with_response(&x);
|
||||
self.server
|
||||
.lock()
|
||||
.unwrap()
|
||||
.reset_ecu(ResetMode::PowerOnReset);
|
||||
tmp = false;
|
||||
}
|
||||
}
|
||||
)
|
||||
});
|
||||
if reload {
|
||||
*self = Self::new(self.server.clone(), self.bar.clone());
|
||||
}
|
||||
self.show_final_warning = tmp;
|
||||
|
||||
ui.add(self.status.clone());
|
||||
PageAction::None
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ use std::{
|
|||
Arc, Mutex, RwLock,
|
||||
},
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
time::{Duration, Instant}, ops::RangeInclusive,
|
||||
};
|
||||
|
||||
use ecu_diagnostics::kwp2000::{Kwp2000DiagnosticServer, SessionType};
|
||||
use eframe::egui::plot::{Legend, Line, Plot, PlotPoints};
|
||||
use eframe::egui::plot::{Legend, Line, Plot, PlotPoints, Bar, BarChart};
|
||||
|
||||
use crate::{ui::status_bar::MainStatusBar, window::PageAction};
|
||||
|
||||
|
@ -23,6 +23,13 @@ pub struct SolenoidPage {
|
|||
curr_values: Arc<RwLock<Option<DataSolenoids>>>,
|
||||
prev_values: Arc<RwLock<Option<DataSolenoids>>>,
|
||||
time_since_launch: Instant,
|
||||
view_type: ViewType
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ViewType {
|
||||
Pwm,
|
||||
Current
|
||||
}
|
||||
|
||||
impl SolenoidPage {
|
||||
|
@ -74,6 +81,7 @@ impl SolenoidPage {
|
|||
last_update_time: last_update,
|
||||
prev_values: store_old,
|
||||
time_since_launch: launch_time,
|
||||
view_type: ViewType::Pwm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,40 +92,12 @@ const MAX_DUTY: u16 = 0xFFF; // 12bit pwm (4096)
|
|||
const VOLTAGE_HIGH: f64 = 12.0;
|
||||
const VOLTAGE_LOW: f64 = 0.0;
|
||||
|
||||
fn make_line_duty_pwm(duty: f32, freq: u16, x_off: f64, y_off: f64) -> PlotPoints {
|
||||
let num_pulses = freq / GRAPH_TIME_MS as u16;
|
||||
let pulse_width = GRAPH_TIME_MS as f64 / num_pulses as f64;
|
||||
let pulse_on_width = (duty as f64 / 4096.0) * pulse_width;
|
||||
let pulse_off_width = pulse_width - pulse_on_width;
|
||||
fn make_pwm_bar(idx: usize, duty: f32) -> Bar {
|
||||
return Bar::new(idx as f64, (duty as f64 / 4096.0) * 100.0);
|
||||
}
|
||||
|
||||
let mut points: Vec<[f64; 2]> = Vec::new();
|
||||
let mut curr_x_pos = 0f64;
|
||||
|
||||
// Shortcut
|
||||
if duty as u16 == MAX_DUTY {
|
||||
points.push([0.0, VOLTAGE_LOW]);
|
||||
points.push([GRAPH_TIME_MS, VOLTAGE_LOW]);
|
||||
} else if duty as u16 == 0 {
|
||||
points.push([0.0, VOLTAGE_HIGH]);
|
||||
points.push([GRAPH_TIME_MS, VOLTAGE_HIGH]);
|
||||
} else {
|
||||
for i in 0..num_pulses {
|
||||
// Start at 12V (High - Solenoid off)
|
||||
points.push([curr_x_pos, VOLTAGE_HIGH]); // High, left
|
||||
curr_x_pos += pulse_off_width;
|
||||
points.push([curr_x_pos, VOLTAGE_HIGH]); // High, right
|
||||
// Now vertical line
|
||||
points.push([curr_x_pos, VOLTAGE_LOW]);
|
||||
curr_x_pos += pulse_on_width;
|
||||
points.push([curr_x_pos, VOLTAGE_LOW]);
|
||||
// Now draw at 0V (Low - Solenoid on)
|
||||
}
|
||||
}
|
||||
for p in points.iter_mut() {
|
||||
p[0] += x_off;
|
||||
p[1] += y_off;
|
||||
}
|
||||
points.into()
|
||||
fn make_current_bar(idx: usize, c: f32) -> Bar {
|
||||
return Bar::new(idx as f64, c as f64);
|
||||
}
|
||||
|
||||
impl crate::window::InterfacePage for SolenoidPage {
|
||||
|
@ -127,9 +107,14 @@ impl crate::window::InterfacePage for SolenoidPage {
|
|||
frame: &eframe::Frame,
|
||||
) -> crate::window::PageAction {
|
||||
ui.heading("Solenoid live view");
|
||||
ui.horizontal(|row| {
|
||||
row.label("Showing: ");
|
||||
row.selectable_value(&mut self.view_type, ViewType::Pwm, "PWM");
|
||||
row.selectable_value(&mut self.view_type, ViewType::Current, "Current");
|
||||
});
|
||||
|
||||
let mut curr = self.curr_values.read().unwrap().clone().unwrap_or_default();
|
||||
let mut prev = self.prev_values.read().unwrap().clone().unwrap_or_default();
|
||||
let curr = self.curr_values.read().unwrap().clone().unwrap_or_default();
|
||||
let prev = self.prev_values.read().unwrap().clone().unwrap_or_default();
|
||||
|
||||
let ms_since_update = std::cmp::min(
|
||||
UPDATE_DELAY_MS,
|
||||
|
@ -139,7 +124,6 @@ impl crate::window::InterfacePage for SolenoidPage {
|
|||
|
||||
let mut proportion_curr: f32 = (ms_since_update as f32) / UPDATE_DELAY_MS as f32; // Percentage of old value to use
|
||||
let mut proportion_prev: f32 = 1.0 - proportion_curr; // Percentage of curr value to use
|
||||
|
||||
if ms_since_update == 0 {
|
||||
proportion_prev = 0.5;
|
||||
proportion_curr = 0.5;
|
||||
|
@ -147,93 +131,97 @@ impl crate::window::InterfacePage for SolenoidPage {
|
|||
proportion_prev = 0.5;
|
||||
proportion_curr = 0.5;
|
||||
}
|
||||
let mut lines = Vec::new();
|
||||
|
||||
let mut bars = Vec::new();
|
||||
let mut legend = Legend::default();
|
||||
let c_height = (ui.available_height() - 50.0) / 6.0;
|
||||
let x_fmt = |y, _range: &RangeInclusive<f64>| {
|
||||
match y as usize {
|
||||
1 => "MPC",
|
||||
2 => "SPC",
|
||||
3 => "TCC",
|
||||
4 => "Y3",
|
||||
5 => "Y4",
|
||||
6 => "Y5",
|
||||
_ => ""
|
||||
}.to_string()
|
||||
};
|
||||
|
||||
lines.push((
|
||||
"MPC",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.mpc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.mpc_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("MPC")
|
||||
.width(2.0),
|
||||
));
|
||||
lines.push((
|
||||
"SPC",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.spc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.spc_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("SPC")
|
||||
.width(2.0),
|
||||
));
|
||||
lines.push((
|
||||
"TCC",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.tcc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.tcc_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("TCC")
|
||||
.width(2.0),
|
||||
));
|
||||
let mut plot = Plot::new("Solenoid data")
|
||||
.allow_drag(false)
|
||||
.include_y(0)
|
||||
.legend(legend.clone())
|
||||
.x_axis_formatter(x_fmt)
|
||||
.allow_zoom(false)
|
||||
.allow_boxed_zoom(false)
|
||||
.allow_scroll(false)
|
||||
.allow_drag(false);
|
||||
|
||||
lines.push((
|
||||
"Y3",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.y3_pwm() as f32 * proportion_curr) + (prev.y3_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("Y3")
|
||||
.width(2.0),
|
||||
));
|
||||
lines.push((
|
||||
"Y4",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.y4_pwm() as f32 * proportion_curr) + (prev.y4_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("Y4")
|
||||
.width(2.0),
|
||||
));
|
||||
lines.push((
|
||||
"Y5",
|
||||
Line::new(make_line_duty_pwm(
|
||||
(curr.y5_pwm() as f32 * proportion_curr) + (prev.y5_pwm() as f32 * proportion_prev),
|
||||
1000,
|
||||
0.0,
|
||||
0.0,
|
||||
))
|
||||
.name("Y5")
|
||||
.width(2.0),
|
||||
));
|
||||
|
||||
for line in lines {
|
||||
let mut plot = Plot::new(format!("Solenoid {}", line.0))
|
||||
.allow_drag(false)
|
||||
.height(c_height)
|
||||
.legend(legend.clone());
|
||||
plot = plot.include_y(13);
|
||||
plot = plot.include_y(-1);
|
||||
|
||||
plot = plot.include_x(0);
|
||||
plot = plot.include_x(100);
|
||||
plot.show(ui, |plot_ui| plot_ui.line(line.1));
|
||||
if self.view_type == ViewType::Pwm {
|
||||
bars.push(
|
||||
make_pwm_bar(1, (curr.mpc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.mpc_pwm() as f32 * proportion_prev)).name("MPC")
|
||||
);
|
||||
bars.push(
|
||||
make_pwm_bar(2, (curr.spc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.spc_pwm() as f32 * proportion_prev)).name("SPC")
|
||||
);
|
||||
bars.push(
|
||||
make_pwm_bar(3, (curr.tcc_pwm() as f32 * proportion_curr)
|
||||
+ (prev.tcc_pwm() as f32 * proportion_prev)).name("TCC")
|
||||
);
|
||||
bars.push(
|
||||
make_pwm_bar(4, (curr.y3_pwm() as f32 * proportion_curr)
|
||||
+ (prev.y3_pwm() as f32 * proportion_prev)).name("Y3")
|
||||
);
|
||||
bars.push(
|
||||
make_pwm_bar(5, (curr.y4_pwm() as f32 * proportion_curr)
|
||||
+ (prev.y4_pwm() as f32 * proportion_prev)).name("Y4")
|
||||
);
|
||||
bars.push(
|
||||
make_pwm_bar(6, (curr.y5_pwm() as f32 * proportion_curr)
|
||||
+ (prev.y5_pwm() as f32 * proportion_prev)).name("Y5")
|
||||
);
|
||||
let mut y_fmt_pwm = |x, _range: &RangeInclusive<f64>| {
|
||||
format!("{} %", x)
|
||||
};
|
||||
plot = plot.y_axis_formatter( y_fmt_pwm);
|
||||
plot = plot.include_y(100);
|
||||
} else {
|
||||
bars.push(
|
||||
make_current_bar(1, (curr.mpc_current() as f32 * proportion_curr)
|
||||
+ (prev.mpc_current() as f32 * proportion_prev)).name("MPC")
|
||||
);
|
||||
bars.push(
|
||||
make_current_bar(2, (curr.spc_current() as f32 * proportion_curr)
|
||||
+ (prev.spc_current() as f32 * proportion_prev)).name("SPC")
|
||||
);
|
||||
bars.push(
|
||||
make_current_bar(3, (curr.tcc_current() as f32 * proportion_curr)
|
||||
+ (prev.tcc_current() as f32 * proportion_prev)).name("TCC")
|
||||
);
|
||||
bars.push(
|
||||
make_current_bar(4, (curr.y3_current() as f32 * proportion_curr)
|
||||
+ (prev.y3_current() as f32 * proportion_prev)).name("Y3")
|
||||
);
|
||||
bars.push(
|
||||
make_current_bar(5, (curr.y4_current() as f32 * proportion_curr)
|
||||
+ (prev.y4_current() as f32 * proportion_prev)).name("Y4")
|
||||
);
|
||||
bars.push(
|
||||
make_current_bar(6, (curr.y5_current() as f32 * proportion_curr)
|
||||
+ (prev.y5_current() as f32 * proportion_prev)).name("Y5")
|
||||
);
|
||||
let mut y_fmt_current = |x, _range: &RangeInclusive<f64>| {
|
||||
format!("{} mA", x)
|
||||
};
|
||||
plot = plot.y_axis_formatter( y_fmt_current);
|
||||
plot = plot.include_y(2000);
|
||||
}
|
||||
plot.show(ui, |plot_ui| {
|
||||
for bar in bars {
|
||||
plot_ui.bar_chart(BarChart::new(vec![bar]))
|
||||
}
|
||||
});
|
||||
ui.ctx().request_repaint();
|
||||
PageAction::None
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue