forked from hdoordt/ppk2-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cli.rs
136 lines (120 loc) · 3.64 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
127
128
129
130
131
132
133
134
135
136
use anyhow::Result;
use clap::Parser;
use ppk2::{
measurement::MeasurementMatch,
try_find_ppk2_port,
types::{DevicePower, Level, LogicPortPins, MeasurementMode, SourceVoltage},
Ppk2,
};
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 = ppk2.start_measurement_matching(pins, args.sps)?;
let ctrlc_handler: Box<dyn FnOnce() -> i32 + Send> = Box::new(move || {
info!("Ctrl+C received");
let result = ppk2.end_measurements();
match result {
Ok(_) => 0,
Err(e) => {
error!("Error ending PPK2 measurements!, {}", e);
1
}
}
});
ctrlc_fnonce::set_ctrlc_handler(ctrlc_handler)?;
// 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
}