-
Notifications
You must be signed in to change notification settings - Fork 4
/
cli.rs
126 lines (111 loc) · 3.39 KB
/
cli.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
use anyhow::Result;
use clap::Parser;
use ppk2::{
types::{DevicePower, MeasurementMode, SourceVoltage, LogicPortPins, Level},
Ppk2, try_find_ppk2_port, measurement::MeasurementMatch,
};
use std::{
sync::mpsc::RecvTimeoutError,
time::{Duration, Instant},
};
use tracing::{debug, error, info, Level as LogLevel};
use tracing_subscriber::FmtSubscriber;
#[derive(Parser)]
struct Args {
#[clap(
env,
short = 'p',
long,
help = "The serial port the PPK2 is connected to. If unspecified, will try to find the PPK2 automatically"
)]
serial_port: Option<String>,
#[clap(
env,
short = 'v',
long,
help = "The voltage of the device source in mV",
default_value = "0"
)]
voltage: SourceVoltage,
#[clap(
env,
short = 'e',
long,
help = "Enable power",
default_value = "disabled"
)]
power: DevicePower,
#[clap(
env,
short = 'm',
long,
help = "Measurement mode",
default_value = "source"
)]
mode: MeasurementMode,
#[clap(env, short = 'l', long, help = "The log level", default_value = "info")]
log_level: LogLevel,
#[clap(
env,
short = 's',
long,
help = "The maximum number of samples to be taken per second. Uses averaging of device samples Samples are analyzed in chunks, and as such the actual number of samples per second will deviate",
default_value = "100"
)]
sps: usize,
}
fn main() -> Result<()> {
// Setup stuff
let args = Args::parse();
let subscriber = FmtSubscriber::builder()
.with_max_level(args.log_level)
.finish();
tracing::subscriber::set_global_default(subscriber)?;
let ppk2_port = match args.serial_port {
Some(p) => p,
None => try_find_ppk2_port()?,
};
// Connect to PPK2 and initialize
let mut ppk2 = Ppk2::new(ppk2_port, args.mode)?;
ppk2.set_source_voltage(args.voltage)?;
ppk2.set_device_power(args.power)?;
// Set up pin pattern for matching
// This particular setup will only
// match measurements if pin 0 is low.
let mut levels = [Level::Either; 8];
levels[0] = Level::Low;
let pins = LogicPortPins::with_levels(levels);
// Start measuring.
let (rx, kill) = ppk2.start_measurement_matching(pins, args.sps)?;
// Set up sigkill handler.
let mut kill = Some(kill);
ctrlc::set_handler(move || {
kill.take().unwrap()().unwrap();
})?;
// Receive measurements
let mut count = 0usize;
let start = Instant::now();
let r: Result<()> = loop {
let rcv_res = rx.recv_timeout(Duration::from_millis(2000));
count += 1;
use MeasurementMatch::*;
match rcv_res {
Ok(Match(m)) => {
debug!("Last chunk average: {:.4} μA", m.micro_amps);
}
Ok(NoMatch) => {
debug!("No match in the last chunk of measurements");
}
Err(RecvTimeoutError::Disconnected) => break Ok(()),
Err(e) => {
error!("Error receiving data: {e:?}");
break Err(e)?;
}
}
};
let sample_time = Instant::now().duration_since(start).as_secs() as usize;
info!("Samples per second: {}", count / sample_time);
info!("Stopping measurements and resetting");
info!("Goodbye!");
r
}