mirror of
https://github.com/alemidev/scope-tui.git
synced 2024-11-23 14:14:48 +01:00
feat: add log y axis to spectroscope (togglable)
also fixed spectroscope bugging when paused
This commit is contained in:
parent
253ceafb2a
commit
ab2d4a0af8
3 changed files with 27 additions and 15 deletions
|
@ -18,7 +18,6 @@ pub enum CurrentDisplayMode {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pause: bool,
|
|
||||||
channels: u8,
|
channels: u8,
|
||||||
graph: GraphConfig,
|
graph: GraphConfig,
|
||||||
oscilloscope: Oscilloscope,
|
oscilloscope: Oscilloscope,
|
||||||
|
@ -41,6 +40,7 @@ impl From::<&crate::ScopeArgs> for App {
|
||||||
references: !args.no_reference,
|
references: !args.no_reference,
|
||||||
show_ui: !args.no_ui,
|
show_ui: !args.no_ui,
|
||||||
scatter: args.scatter,
|
scatter: args.scatter,
|
||||||
|
pause: false,
|
||||||
marker_type: if args.no_braille {
|
marker_type: if args.no_braille {
|
||||||
Marker::Dot
|
Marker::Dot
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,7 +56,6 @@ impl From::<&crate::ScopeArgs> for App {
|
||||||
graph, oscilloscope, vectorscope, spectroscope,
|
graph, oscilloscope, vectorscope, spectroscope,
|
||||||
mode: CurrentDisplayMode::Oscilloscope,
|
mode: CurrentDisplayMode::Oscilloscope,
|
||||||
channels: args.channels,
|
channels: args.channels,
|
||||||
pause: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +74,7 @@ impl App {
|
||||||
let data = source.recv()
|
let data = source.recv()
|
||||||
.ok_or(io::Error::new(io::ErrorKind::BrokenPipe, "data source returned null"))?;
|
.ok_or(io::Error::new(io::ErrorKind::BrokenPipe, "data source returned null"))?;
|
||||||
|
|
||||||
if !self.pause {
|
if !self.graph.pause {
|
||||||
channels = fmt.oscilloscope(data, self.channels);
|
channels = fmt.oscilloscope(data, self.channels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +97,7 @@ impl App {
|
||||||
let mut size = f.size();
|
let mut size = f.size();
|
||||||
if self.graph.show_ui {
|
if self.graph.show_ui {
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
make_header(&self.graph, &self.current_display().header(&self.graph), self.current_display().mode_str(), framerate, self.pause),
|
make_header(&self.graph, &self.current_display().header(&self.graph), self.current_display().mode_str(), framerate, self.graph.pause),
|
||||||
Rect { x: size.x, y: size.y, width: size.width, height:1 } // a 1px line at the top
|
Rect { x: size.x, y: size.y, width: size.width, height:1 } // a 1px line at the top
|
||||||
);
|
);
|
||||||
size.height -= 1;
|
size.height -= 1;
|
||||||
|
@ -157,7 +156,7 @@ impl App {
|
||||||
KeyCode::Right => update_value_i(&mut self.graph.samples, true, 25, magnitude, 0..self.graph.width*2),
|
KeyCode::Right => update_value_i(&mut self.graph.samples, true, 25, magnitude, 0..self.graph.width*2),
|
||||||
KeyCode::Left => update_value_i(&mut self.graph.samples, false, 25, magnitude, 0..self.graph.width*2),
|
KeyCode::Left => update_value_i(&mut self.graph.samples, false, 25, magnitude, 0..self.graph.width*2),
|
||||||
KeyCode::Char('q') => quit = true,
|
KeyCode::Char('q') => quit = true,
|
||||||
KeyCode::Char(' ') => self.pause = !self.pause,
|
KeyCode::Char(' ') => self.graph.pause = !self.graph.pause,
|
||||||
KeyCode::Char('s') => self.graph.scatter = !self.graph.scatter,
|
KeyCode::Char('s') => self.graph.scatter = !self.graph.scatter,
|
||||||
KeyCode::Char('h') => self.graph.show_ui = !self.graph.show_ui,
|
KeyCode::Char('h') => self.graph.show_ui = !self.graph.show_ui,
|
||||||
KeyCode::Char('r') => self.graph.references = !self.graph.references,
|
KeyCode::Char('r') => self.graph.references = !self.graph.references,
|
||||||
|
|
|
@ -11,6 +11,7 @@ pub enum Dimension {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GraphConfig {
|
pub struct GraphConfig {
|
||||||
|
pub pause: bool,
|
||||||
pub samples: u32,
|
pub samples: u32,
|
||||||
pub sampling_rate: u32,
|
pub sampling_rate: u32,
|
||||||
pub scale: u32,
|
pub scale: u32,
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub struct Spectroscope {
|
||||||
pub average: u32,
|
pub average: u32,
|
||||||
pub buf: Vec<VecDeque<Vec<f64>>>,
|
pub buf: Vec<VecDeque<Vec<f64>>>,
|
||||||
pub window: bool,
|
pub window: bool,
|
||||||
|
pub log_y: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn magnitude(c: Complex<f64>) -> f64 {
|
fn magnitude(c: Complex<f64>) -> f64 {
|
||||||
|
@ -43,6 +44,7 @@ impl DisplayMode for Spectroscope {
|
||||||
buffer_size: args.buffer / (2 * args.channels as u32),
|
buffer_size: args.buffer / (2 * args.channels as u32),
|
||||||
average: 1, buf: Vec::new(),
|
average: 1, buf: Vec::new(),
|
||||||
window: false,
|
window: false,
|
||||||
|
log_y: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +78,10 @@ impl DisplayMode for Spectroscope {
|
||||||
fn axis(&self, cfg: &GraphConfig, dimension: Dimension) -> Axis {
|
fn axis(&self, cfg: &GraphConfig, dimension: Dimension) -> Axis {
|
||||||
let (name, bounds) = match dimension {
|
let (name, bounds) = match dimension {
|
||||||
Dimension::X => ("frequency -", [20.0f64.ln(), ((cfg.samples as f64 / cfg.width as f64) * 20000.0).ln()]),
|
Dimension::X => ("frequency -", [20.0f64.ln(), ((cfg.samples as f64 / cfg.width as f64) * 20000.0).ln()]),
|
||||||
Dimension::Y => ("| level", [0.0, cfg.scale as f64 / 10.0]), // TODO super arbitraty! wtf
|
Dimension::Y => (
|
||||||
|
if self.log_y { "| level" } else { "| amplitude" },
|
||||||
|
[0.0, if self.log_y { (cfg.scale as f64 / 10.0).ln() } else { cfg.scale as f64 / 10.0 }]),
|
||||||
|
// TODO super arbitraty! wtf! also ugly inline ifs, get this thing together!
|
||||||
};
|
};
|
||||||
let mut a = Axis::default();
|
let mut a = Axis::default();
|
||||||
if cfg.show_ui { // TODO don't make it necessary to check show_ui inside here
|
if cfg.show_ui { // TODO don't make it necessary to check show_ui inside here
|
||||||
|
@ -87,6 +92,7 @@ impl DisplayMode for Spectroscope {
|
||||||
|
|
||||||
fn process(&mut self, cfg: &GraphConfig, data: &Vec<Vec<f64>>) -> Vec<DataSet> {
|
fn process(&mut self, cfg: &GraphConfig, data: &Vec<Vec<f64>>) -> Vec<DataSet> {
|
||||||
if self.average == 0 { self.average = 1 } // otherwise fft breaks
|
if self.average == 0 { self.average = 1 } // otherwise fft breaks
|
||||||
|
if !cfg.pause {
|
||||||
for (i, chan) in data.iter().enumerate() {
|
for (i, chan) in data.iter().enumerate() {
|
||||||
if self.buf.len() <= i {
|
if self.buf.len() <= i {
|
||||||
self.buf.push(VecDeque::new());
|
self.buf.push(VecDeque::new());
|
||||||
|
@ -96,6 +102,7 @@ impl DisplayMode for Spectroscope {
|
||||||
self.buf[i].pop_front();
|
self.buf[i].pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut out = Vec::new();
|
let mut out = Vec::new();
|
||||||
let mut planner: FftPlanner<f64> = FftPlanner::new();
|
let mut planner: FftPlanner<f64> = FftPlanner::new();
|
||||||
|
@ -113,7 +120,11 @@ impl DisplayMode for Spectroscope {
|
||||||
fft.process(tmp.as_mut_slice());
|
fft.process(tmp.as_mut_slice());
|
||||||
out.push(DataSet::new(
|
out.push(DataSet::new(
|
||||||
self.channel_name(n),
|
self.channel_name(n),
|
||||||
tmp[..=tmp.len() / 2].iter().enumerate().map(|(i,x)| ((i as f64 * resolution).ln(), magnitude(*x))).collect(),
|
tmp[..=tmp.len() / 2]
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i,x)| ((i as f64 * resolution).ln(), if self.log_y { magnitude(*x).ln() } else { magnitude(*x) }))
|
||||||
|
.collect(),
|
||||||
cfg.marker_type,
|
cfg.marker_type,
|
||||||
if cfg.scatter { GraphType::Scatter } else { GraphType::Line },
|
if cfg.scatter { GraphType::Scatter } else { GraphType::Line },
|
||||||
cfg.palette(n),
|
cfg.palette(n),
|
||||||
|
@ -129,13 +140,14 @@ impl DisplayMode for Spectroscope {
|
||||||
KeyCode::PageUp => update_value_i(&mut self.average, true, 1, 1., 1..65535),
|
KeyCode::PageUp => update_value_i(&mut self.average, true, 1, 1., 1..65535),
|
||||||
KeyCode::PageDown => update_value_i(&mut self.average, false, 1, 1., 1..65535),
|
KeyCode::PageDown => update_value_i(&mut self.average, false, 1, 1., 1..65535),
|
||||||
KeyCode::Char('w') => self.window = !self.window,
|
KeyCode::Char('w') => self.window = !self.window,
|
||||||
|
KeyCode::Char('l') => self.log_y = !self.log_y,
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
|
fn references(&self, cfg: &GraphConfig) -> Vec<DataSet> {
|
||||||
let s = cfg.scale as f64 / 10.0;
|
let s = if self.log_y { (cfg.scale as f64 / 10.0).ln() } else { cfg.scale as f64 / 10.0 };
|
||||||
vec![
|
vec![
|
||||||
DataSet::new("".into(), vec![(0.0, 0.0), ((cfg.samples as f64).ln(), 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color),
|
DataSet::new("".into(), vec![(0.0, 0.0), ((cfg.samples as f64).ln(), 0.0)], cfg.marker_type, GraphType::Line, cfg.axis_color),
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue