Skip to content

Commit 4b45cca

Browse files
committed
Add type for indicating whether any measurement in the last chunk matched
1 parent 4ee1ad8 commit 4b45cca

File tree

4 files changed

+39
-36
lines changed

4 files changed

+39
-36
lines changed

cli/src/main.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use anyhow::Result;
22
use clap::Parser;
33
use ppk2::{
44
types::{DevicePower, MeasurementMode, SourceVoltage, LogicPortPins, Level},
5-
Ppk2, try_find_ppk2_port,
5+
Ppk2, try_find_ppk2_port, measurement::MeasurementMatch,
66
};
77

88
use std::{
@@ -94,14 +94,14 @@ fn main() -> Result<()> {
9494
let r: Result<()> = loop {
9595
let rcv_res = rx.recv_timeout(Duration::from_millis(2000));
9696
count += 1;
97-
let now = Instant::now();
98-
if now.duration_since(start) > Duration::from_secs(10) {
99-
break Ok(());
100-
}
97+
use MeasurementMatch::*;
10198
match rcv_res {
102-
Ok(m) => {
99+
Ok(Match(m)) => {
103100
debug!("Last: {:.4} μA", m.micro_amps);
104101
}
102+
Ok(NoMatch) => {
103+
debug!("No match");
104+
}
105105
Err(RecvTimeoutError::Disconnected) => break Ok(()),
106106
Err(e) => {
107107
error!("Error receiving data: {e:?}");

ppk2/src/lib.rs

+5-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![doc = include_str!("../../README.md")]
22
#![deny(missing_docs)]
33

4-
use measurement::{Measurement, MeasurementAccumulator, MeasurementIterExt};
4+
use measurement::{Measurement, MeasurementAccumulator, MeasurementIterExt, MeasurementMatch};
55
use serialport::{ClearBuffer::Input, FlowControl, SerialPort};
66
use std::str::Utf8Error;
77
use std::sync::mpsc::{self, Receiver, SendError, TryRecvError};
@@ -39,7 +39,7 @@ pub enum Error {
3939
#[error("Parse error in \"{0}\"")]
4040
Parse(String),
4141
#[error("Error sending measurement: {0}")]
42-
SendMeasurement(#[from] SendError<Measurement>),
42+
SendMeasurement(#[from] SendError<MeasurementMatch>),
4343
#[error("Error sending stop signal: {0}")]
4444
SendStopSignal(#[from] SendError<()>),
4545
#[error("Worker thread signal error: {0}")]
@@ -114,15 +114,12 @@ impl Ppk2 {
114114
mut self,
115115
pins: LogicPortPins,
116116
sps: usize,
117-
) -> Result<(
118-
Receiver<measurement::Measurement>,
119-
impl FnOnce() -> Result<Self>,
120-
)> {
117+
) -> Result<(Receiver<MeasurementMatch>, impl FnOnce() -> Result<Self>)> {
121118
// Stuff needed to communicate with the main thread
122119
// ready allows main thread to signal worker when serial input buf is cleared.
123120
let ready = Arc::new((Mutex::new(false), Condvar::new()));
124121
// This channel is for sending measurements to the main thread.
125-
let (meas_tx, meas_rx) = mpsc::channel::<measurement::Measurement>();
122+
let (meas_tx, meas_rx) = mpsc::channel::<MeasurementMatch>();
126123
// This channel allows the main thread to notify that the worker thread can stop
127124
// parsing data.
128125
let (sig_tx, sig_rx) = mpsc::channel::<()>();
@@ -145,7 +142,6 @@ impl Ppk2 {
145142
let mut buf = [0u8; 1024];
146143
let mut measurement_buf = VecDeque::with_capacity(SPS_MAX);
147144
let mut missed = 0;
148-
let mut did_get_matches = false;
149145
loop {
150146
// Check whether the main thread has signaled
151147
// us to stop
@@ -161,17 +157,7 @@ impl Ppk2 {
161157
let len = measurement_buf.len();
162158
if len >= SPS_MAX / sps {
163159
let measurement = measurement_buf.drain(..).combine_matching(missed, pins);
164-
match measurement {
165-
Some(m) => {
166-
meas_tx.send(m)?;
167-
did_get_matches = true;
168-
}
169-
None if did_get_matches => {
170-
break Ok(());
171-
},
172-
_ => {/* No matching measurements yet, wait for them to come up */},
173-
}
174-
160+
meas_tx.send(measurement)?;
175161
missed = 0;
176162
}
177163
}

ppk2/src/measurement.rs

+19-9
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::collections::VecDeque;
44

5-
use crate::types::{LogicPortPins, Metadata};
5+
use crate::{types::{LogicPortPins, Metadata}};
66

77
const ADC_MULTIPLIER: f32 = 1.8 / 163840.;
88
const SPIKE_FILTER_ALPHA: f32 = 0.18;
@@ -86,7 +86,7 @@ impl MeasurementAccumulator {
8686
}
8787

8888
let adc_result = get_adc(raw) * 4;
89-
let bits = get_logic(raw).into();
89+
let pins = get_logic(raw).into();
9090
let micro_amps = get_adc_result(
9191
&self.metadata,
9292
&mut self.state,
@@ -99,7 +99,7 @@ impl MeasurementAccumulator {
9999

100100
buf.push_back(Measurement {
101101
micro_amps,
102-
pins: bits,
102+
pins,
103103
})
104104
}
105105
self.buf.drain(..end);
@@ -165,17 +165,27 @@ fn get_adc_result(
165165
adc
166166
}
167167

168+
169+
/// Indicates whether a set of [Measurement]s matched
170+
#[derive(Debug)]
171+
pub enum MeasurementMatch {
172+
/// A set of [Measurement]s did match
173+
Match(Measurement),
174+
/// No matching [Measurement]s in the last chunk
175+
NoMatch,
176+
}
177+
168178
/// Extension trait for VecDeque<Measurement>
169179
pub trait MeasurementIterExt {
170180
/// Combine items into a single [Measurement], if there are items.
171-
fn combine(self, missed: usize) -> Option<Measurement>;
181+
fn combine(self, missed: usize) -> MeasurementMatch;
172182

173183
/// Combine items with matching logic port pins into a single [Measurement], if any.
174-
fn combine_matching(self, missed: usize, matching_pins: LogicPortPins) -> Option<Measurement>;
184+
fn combine_matching(self, missed: usize, matching_pins: LogicPortPins) -> MeasurementMatch;
175185
}
176186

177187
impl<I: Iterator<Item = Measurement>> MeasurementIterExt for I {
178-
fn combine(self, missed: usize) -> Option<Measurement> {
188+
fn combine(self, missed: usize) -> MeasurementMatch {
179189
let mut pin_high_count = [0usize; 8];
180190
let mut count = 0;
181191
let mut sum = 0f32;
@@ -192,7 +202,7 @@ impl<I: Iterator<Item = Measurement>> MeasurementIterExt for I {
192202

193203
if count == 0 {
194204
// No measurements
195-
return None;
205+
return MeasurementMatch::NoMatch;
196206
}
197207

198208
let mut pins = [false; 8];
@@ -203,13 +213,13 @@ impl<I: Iterator<Item = Measurement>> MeasurementIterExt for I {
203213
.for_each(|(i, _)| pins[i] = true);
204214
let avg = sum / (count - missed) as f32;
205215

206-
Some(Measurement {
216+
MeasurementMatch::Match(Measurement {
207217
micro_amps: avg,
208218
pins: pins.into(),
209219
})
210220
}
211221

212-
fn combine_matching(self, missed: usize, matching_pins: LogicPortPins) -> Option<Measurement> {
222+
fn combine_matching(self, missed: usize, matching_pins: LogicPortPins) -> MeasurementMatch {
213223
let iter = self.filter(|m| {
214224
m.pins
215225
.inner()

ppk2/src/types.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,14 @@ impl FromStr for DevicePower {
137137
}
138138

139139
/// Logic level for logic port pins
140-
#[derive(Debug, Clone, Copy)]
140+
#[derive(Debug, Clone, Copy, Default)]
141141
pub enum Level {
142142
/// Low level
143143
Low,
144144
/// High level
145145
High,
146146
/// Either level. Used for matching only.
147+
#[default]
147148
Either,
148149
}
149150

@@ -181,12 +182,18 @@ impl Level {
181182
}
182183

183184
/// Logic port state
184-
#[derive(Debug, Clone, Copy)]
185+
#[derive(Debug, Clone, Copy, Default)]
185186
pub struct LogicPortPins {
186187
pin_levels: [Level; 8],
187188
}
188189

189190
impl LogicPortPins {
191+
/// Set a pin level
192+
pub fn set_level(mut self, pin: usize, level: Level) -> Self {
193+
self.pin_levels[pin] = level;
194+
self
195+
}
196+
190197
/// Set up a new [LogicPortPins] with given [Level]s
191198
pub fn with_levels(pin_levels: [Level; 8]) -> Self {
192199
Self { pin_levels }

0 commit comments

Comments
 (0)