From e656b6303e5d75d4c97e7ac3a2c04a3ce2bb3d22 Mon Sep 17 00:00:00 2001 From: alemidev Date: Mon, 2 Jan 2023 01:18:07 +0100 Subject: [PATCH] feat: trigger threshold, better heading remade heading with table widgets, added triggering threshold controlled with arrows and PgUp/PgDwn, small fixes --- src/app.rs | 63 +++++++++++++++++++++++++++++------------------------ src/main.rs | 19 ++++++++++------ 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/src/app.rs b/src/app.rs index 7b9fe2d..4a34a58 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,10 +1,10 @@ use std::{io::{self, ErrorKind}, time::{Duration, Instant}}; use tui::{ - style::Color, widgets::GraphType, symbols, + style::Color, widgets::{GraphType, Table, Row, Cell}, symbols, backend::Backend, - widgets::{Block, Chart, Axis, Dataset}, - Terminal, text::Span, style::{Style, Modifier}, layout::Alignment + widgets::{Chart, Axis, Dataset}, + Terminal, text::Span, style::{Style, Modifier}, layout::{Rect, Constraint} }; use crossterm::event::{self, Event, KeyCode, KeyModifiers}; @@ -190,7 +190,7 @@ pub fn run_app(args: Args, terminal: &mut Terminal) -> Result<() if let Some(ch) = channels.get(0) { let mut discard = 0; for i in 0..ch.len() { // seek to first sample rising through threshold - if i + 1 < ch.len() && ch[i] <= 0.0 && ch[i+1] > 0.0 { // triggered + if i + 1 < ch.len() && ch[i] <= app.cfg.threshold && ch[i+1] > app.cfg.threshold { // triggered break; } else { discard += 1; @@ -202,6 +202,8 @@ pub fn run_app(args: Args, terminal: &mut Terminal) -> Result<() } } + let samples = channels.iter().map(|x| x.len()).max().unwrap_or(0); + let mut measures; if app.cfg.vectorscope { @@ -226,10 +228,13 @@ pub fn run_app(args: Args, terminal: &mut Terminal) -> Result<() } let mut datasets = vec![]; + let trigger_pt; if app.cfg.references { + trigger_pt = [(0.0, app.cfg.threshold)]; datasets.push(data_set("", &app.references.x, app.cfg.marker_type, GraphType::Line, app.cfg.axis_color)); datasets.push(data_set("", &app.references.y, app.cfg.marker_type, GraphType::Line, app.cfg.axis_color)); + datasets.push(data_set("T", &trigger_pt, app.cfg.marker_type, GraphType::Scatter, Color::Cyan)); } let ds_names = if app.cfg.vectorscope { vec!["1", "2"] } else { vec!["R", "L"] }; @@ -248,9 +253,29 @@ pub fn run_app(args: Args, terminal: &mut Terminal) -> Result<() } terminal.draw(|f| { - let size = f.size(); + let mut size = f.size(); + if app.cfg.references { + let heading = Table::new( + vec![ + Row::new( + vec![ + Cell::from(format!("TUI {}", if app.cfg.vectorscope { "Vectorscope" } else { "Oscilloscope" })).style(Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)), + Cell::from(format!("{}{} mode", if app.cfg.triggering { "triggered " } else { "" }, if app.scatter() { "scatter" } else { "line" })), + Cell::from(format!("range +-{}", app.cfg.scale)), + Cell::from(format!("{} smpl", samples as u32)), + Cell::from(format!("{:.1} kHz", args.sample_rate as f32 / 1000.0)), + Cell::from(format!("{} fps", framerate)), + ] + ) + ] + ) + .style(Style::default().fg(Color::Cyan)) + .widths(&[Constraint::Length(50), Constraint::Length(25), Constraint::Length(15), Constraint::Length(10), Constraint::Length(10), Constraint::Length(10)]); + f.render_widget(heading, Rect { x: size.x, y: size.y, width: size.width, height:1 }); + size.height -= 1; + size.y += 1; + } let chart = Chart::new(datasets) - .block(block(&app, args.sample_rate as f32, framerate)) .x_axis(axis(&app, Dimension::X)) // TODO allow to have axis sometimes? .y_axis(axis(&app, Dimension::Y)); f.render_widget(chart, size) @@ -276,8 +301,10 @@ pub fn run_app(args: Args, terminal: &mut Terminal) -> Result<() KeyCode::Char('s') => app.set_scatter(!app.scatter()), // TODO no funcs KeyCode::Char('h') => app.cfg.references = !app.cfg.references, KeyCode::Char('t') => app.cfg.triggering = !app.cfg.triggering, - KeyCode::Up => {}, - KeyCode::Down => {}, + KeyCode::Up => app.cfg.threshold += 100.0, + KeyCode::Down => app.cfg.threshold -= 100.0, + KeyCode::PageUp => app.cfg.threshold += 1000.0, + KeyCode::PageDown => app.cfg.threshold -= 1000.0, _ => {}, } } @@ -323,23 +350,3 @@ fn axis(app: &App, dim: Dimension) -> Axis { a.style(Style::default().fg(app.cfg.axis_color)) .bounds(app.bounds(&dim)) } - -fn block(app: &App, sample_rate: f32, framerate: u32) -> Block { - let mut b = Block::default(); - - if app.cfg.references { - b = b.title( - Span::styled( - format!( - "TUI {} -- {}{} mode -- range {} -- {} samples -- {:.1} kHz -- {} fps", - if app.cfg.vectorscope { "Vectorscope" } else { "Oscilloscope" }, - if app.cfg.triggering { "triggered " } else { "" }, - if app.scatter() { "scatter" } else { "line" }, - app.cfg.scale, app.cfg.width, sample_rate / 1000.0, framerate, - ), - Style::default().add_modifier(Modifier::BOLD).fg(Color::Yellow)) - ).title_alignment(Alignment::Center); - } - - b -} diff --git a/src/main.rs b/src/main.rs index 1e5d7c6..2bf9333 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,6 +56,10 @@ pub struct Args { #[arg(long, default_value_t = false)] triggering: bool, + /// Threshold value for triggering + #[arg(long, default_value_t = 0.0)] + threshold: f64, + /// Don't draw reference line #[arg(long, default_value_t = false)] no_reference: bool, @@ -87,12 +91,7 @@ fn main() -> Result<(), std::io::Error> { let mut terminal = Terminal::new(backend)?; terminal.hide_cursor()?; - match run_app(args, &mut terminal) { - Ok(()) => {}, - Err(e) => { - println!("[!] Error executing app: {:?}", e); - } - } + let res = run_app(args, &mut terminal); // restore terminal disable_raw_mode()?; @@ -103,5 +102,11 @@ fn main() -> Result<(), std::io::Error> { )?; terminal.show_cursor()?; - Ok(()) + match res { + Ok(()) => Ok(()), + Err(e) => { + eprintln!("[!] Error executing app: {:?}", e); + Err(e) + } + } }