1use byteorder::{LittleEndian, ReadBytesExt};
2use num_enum::TryFromPrimitive;
3use std::io;
4use std::io::Cursor;
5use std::io::Read;
6
7use crate::measurement::Attribute;
8use crate::measurement::DcMode;
9use crate::measurement::DeviceMode;
10use crate::measurement::Function;
11use crate::measurement::Unit;
12use crate::measurement::VoltAcSubMode;
13use crate::measurement::{MinMaxMode, Mode, Modes, RangeSelection};
14
15#[derive(Debug, Clone, Default)]
17pub struct RawInfo {
18 pub f_autohold2: bool,
20 pub f_hold2: bool,
22 pub f_log_mode: bool,
24 pub f_avg: bool,
26 pub f_max: bool,
28 pub f_min: bool,
30 pub f_fast_mode: bool,
32 pub f_low_bat: bool,
34 pub f_bolt: bool,
36 pub f_delta: bool,
38 pub f_delta_pct: bool,
40 pub f_mem_clear: u8,
42 pub f_auto_range: bool,
44 pub f_man_range: bool,
46 pub f_shift_sign: bool,
48 pub f_mea_mode: u8,
50 pub f_hz_mode: u8,
52 pub f_mn_mx_mode: bool,
54 pub f_fast_mode2: bool,
56 pub f_ubit1: bool,
58 pub f_minmaxavg: u8,
60 pub f_ubit2: bool,
62 pub f_rising_etch: bool,
64 pub f_fall_etch: bool,
66 pub f_sub_acdc: u8,
68 pub f_ubit3: bool,
70 pub f_hold: bool,
72 pub f_auto_hold: bool,
74 pub f_ubit4: bool,
76 pub f_db_v_or_m: bool,
78 pub f_temp_c_or_f: bool,
80 pub f_delta2: bool,
82 pub f_delta_pct2: bool,
84 pub f_ubit5: bool,
86 pub f_ac_db_mode: u8,
88 pub f_digits: bool,
90 pub f_range_disp: bool,
92 pub selected_range: u8,
94 pub current_view: u8,
96 pub dbm_ref: u16,
98}
99
100pub(crate) const RAW_INFO_LEN: usize = 10;
101
102impl RawInfo {
104 #[rustfmt::skip]
105 pub(crate) fn new(cur: &mut impl Read) -> io::Result<Self> {
106 let flags1 = cur.read_u16::<LittleEndian>()?;
107 let dbm_ref = cur.read_u16::<LittleEndian>()?;
108 let flags2 = cur.read_u16::<LittleEndian>()?;
109 let flags3 = cur.read_u16::<LittleEndian>()?;
110 let selected_range = cur.read_u8()?;
111 let current_view = cur.read_u8()?;
112
113 let f_autohold2 = get_bits16(0b0000_0000_0000_0001, flags1) > 0;
114 let f_hold2 = get_bits16(0b0000_0000_0000_0010, flags1) > 0;
115 let f_log_mode = get_bits16(0b0000_0000_0000_0100, flags1) > 0;
116 let f_avg = get_bits16(0b0000_0000_0000_1000, flags1) > 0;
117 let f_max = get_bits16(0b0000_0000_0001_0000, flags1) > 0;
118 let f_min = get_bits16(0b0000_0000_0010_0000, flags1) > 0;
119 let f_fast_mode = get_bits16(0b0000_0000_0100_0000, flags1) > 0;
120 let f_low_bat = get_bits16(0b0000_0000_1000_0000, flags1) > 0;
121 let f_bolt = get_bits16(0b0000_0001_0000_0000, flags1) > 0;
122 let f_delta2 = get_bits16(0b0000_0010_0000_0000, flags1) > 0;
123 let f_delta_pct2 = get_bits16(0b0000_0100_0000_0000, flags1) > 0;
124 let f_mem_clear = get_bits16(0b0001_1000_0000_0000, flags1) as u8;
125 let f_auto_range = get_bits16(0b0010_0000_0000_0000, flags1) > 0;
126 let f_man_range = get_bits16(0b0100_0000_0000_0000, flags1) > 0;
127 let f_shift_sign = get_bits16(0b1000_0000_0000_0000, flags1) > 0;
128
129 let f_mea_mode = get_bits16(0b0000_0000_0011_1111, flags2) as u8;
130 let f_hz_mode = get_bits16(0b0000_0000_1100_0000, flags2) as u8;
131 let f_mn_mx_mode = get_bits16(0b0000_0001_0000_0000, flags2) > 0;
132 let f_fast_mode2 = get_bits16(0b0000_0010_0000_0000, flags2) > 0;
133 let f_ubit1 = get_bits16(0b0000_0100_0000_0000, flags2) > 0;
134 let f_minmaxavg = get_bits16(0b0001_1000_0000_0000, flags2) as u8;
135 let f_ubit2 = get_bits16(0b0010_0000_0000_0000, flags2) > 0;
136 let f_rising_etch = get_bits16(0b0100_0000_0000_0000, flags2) > 0;
137 let f_fall_etch = get_bits16(0b1000_0000_0000_0000, flags2) > 0;
138
139 let f_sub_acdc = get_bits16(0b0000_0000_0000_0011, flags3) as u8;
140 let f_ubit3 = get_bits16(0b0000_0000_0000_0100, flags3) > 0;
141 let f_hold = get_bits16(0b0000_0000_0000_1000, flags3) > 0;
142 let f_auto_hold = get_bits16(0b0000_0000_0001_0000, flags3) > 0;
143 let f_ubit4 = get_bits16(0b0000_0000_0010_0000, flags3) > 0;
144 let f_db_v_or_m = get_bits16(0b0000_0000_0100_0000, flags3) > 0;
145 let f_temp_c_or_f = get_bits16(0b0000_0000_1000_0000, flags3) > 0;
146 let f_delta = get_bits16(0b0000_0001_0000_0000, flags3) > 0;
147 let f_delta_pct = get_bits16(0b0000_0010_0000_0000, flags3) > 0;
148 let f_ubit5 = get_bits16(0b0000_0100_0000_0000, flags3) > 0;
149 let f_ac_db_mode = get_bits16(0b0011_1000_0000_0000, flags3) as u8;
150 let f_digits = get_bits16(0b0100_0000_0000_0000, flags3) > 0;
154 let f_range_disp = get_bits16(0b1000_0000_0000_0000, flags3) > 0;
155
156 Ok(Self {
157 f_autohold2,
158 f_hold2,
159 f_log_mode,
160 f_avg,
161 f_max,
162 f_min,
163 f_fast_mode,
164 f_low_bat,
165 f_bolt,
166 f_delta,
167 f_delta_pct,
168 f_mem_clear,
169 f_auto_range,
170 f_man_range,
171 f_shift_sign,
172 f_mea_mode,
173 f_hz_mode,
174 f_mn_mx_mode,
175 f_fast_mode2,
176 f_ubit1,
177 f_minmaxavg,
178 f_ubit2,
179 f_rising_etch,
180 f_fall_etch,
181 f_sub_acdc,
182 f_ubit3,
183 f_hold,
184 f_auto_hold,
185 f_ubit4,
186 f_db_v_or_m,
187 f_temp_c_or_f,
188 f_delta2,
189 f_delta_pct2,
190 f_ubit5,
191 f_ac_db_mode,
192 f_digits,
193 f_range_disp,
194 dbm_ref,
195 selected_range,
196 current_view,
197 })
198 }
199 pub fn db_mode(&self) -> bool {
200 self.f_ac_db_mode != 0
202 }
203
204 pub fn range(&self) -> io::Result<RangeSelection> {
205 RangeSelection::try_from_primitive(self.selected_range)
206 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
207 }
208
209 pub fn attribute(&self) -> io::Result<Option<Attribute>> {
210 Ok(if self.f_rising_etch {
211 Some(Attribute::PositiveEdge)
212 } else if self.f_fall_etch {
213 Some(Attribute::NegativeEdge)
214 } else {
215 None
216 })
217 }
218
219 pub fn volt_ac_submode(&self) -> io::Result<VoltAcSubMode> {
220 VoltAcSubMode::try_from_primitive(self.f_ac_db_mode)
221 .map_err(|_| std::io::Error::new(io::ErrorKind::InvalidData, "Unknown V/AC sub-mode"))
222 }
223
224 pub fn modes(&self) -> io::Result<Modes> {
225 let minmax = MinMaxMode::try_from_primitive(self.f_minmaxavg)
226 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
227
228 let mut modes = Modes::default();
229 if self.f_auto_range {
230 modes.add(Mode::AutoRange);
231 }
232 if self.f_fast_mode {
233 modes.add(Mode::FastMode);
234 }
235 if self.f_mn_mx_mode {
236 modes.add(Mode::MinMaxAvg(minmax));
237 }
238 if self.f_auto_hold {
239 modes.add(Mode::AutoHold);
240 }
241 if self.f_hold {
242 modes.add(Mode::Hold);
243 }
244 if self.f_log_mode {
245 modes.add(Mode::Logging);
246 }
247 if self.f_delta {
248 modes.add(Mode::Rel);
249 }
250 if self.f_delta_pct {
251 modes.add(Mode::RelPercent);
252 }
253 Ok(modes)
254 }
255
256 pub fn get_functions(&self) -> (Function, Unit, Function, Unit, Unit) {
257 let dbm_or_v = || {
258 if self.f_db_v_or_m {
259 Unit::dBV
260 } else {
261 Unit::dBm
262 }
263 };
264 let dc_mode: DcMode = DcMode::try_from(self.f_sub_acdc).expect("Error");
265 let mea_mode = DeviceMode::try_from_primitive(self.f_mea_mode).unwrap_or_default();
267 let vac_sm = self.volt_ac_submode().unwrap();
268 let (pri_f, pri_unit, sec_f, sec_unit) = match (mea_mode, self.f_hz_mode) {
269 (DeviceMode::None, _) => (Function::None, Unit::None, Function::None, Unit::None),
270 (DeviceMode::V_AC, 0) if vac_sm == VoltAcSubMode::Normal => {
272 (Function::V_AC, Unit::VoltAC, Function::None, Unit::None)
273 }
274 (DeviceMode::V_AC, 0) if vac_sm == VoltAcSubMode::AcOverDb => {
275 (Function::V_AC, Unit::VoltAC, Function::V_AC_DB, dbm_or_v())
276 }
277 (DeviceMode::V_AC, 0) if vac_sm == VoltAcSubMode::DbOverAc => {
278 (Function::V_AC_DB, dbm_or_v(), Function::V_AC, Unit::VoltAC)
279 }
280 (DeviceMode::V_AC, 1) if vac_sm == VoltAcSubMode::Normal => {
281 (Function::V_AC_HZ, Unit::Hertz, Function::V_AC, Unit::VoltAC)
282 }
283 (DeviceMode::V_AC, 1) if vac_sm == VoltAcSubMode::HzOverDb => (
284 Function::V_AC_HZ,
285 Unit::Hertz,
286 Function::V_AC_DB,
287 dbm_or_v(),
288 ),
289 (DeviceMode::V_AC, 1) if vac_sm == VoltAcSubMode::DbOverHz => (
290 Function::V_AC_DB,
291 dbm_or_v(),
292 Function::V_AC_HZ,
293 Unit::Hertz,
294 ),
295 (DeviceMode::V_AC, 2) => (
296 Function::V_AC_DUTYCYCLE,
297 Unit::Percent,
298 Function::V_AC_HZ,
299 Unit::Hertz,
300 ),
301 (DeviceMode::V_AC, 3) => (
302 Function::V_AC_DUTYCYCLE,
303 Unit::Seconds,
304 Function::V_AC_HZ,
305 Unit::Hertz,
306 ),
307 (DeviceMode::MV_AC, 0) if vac_sm == VoltAcSubMode::Normal => {
309 (Function::MV_AC, Unit::VoltAC, Function::None, Unit::None)
310 }
311 (DeviceMode::MV_AC, 0) if vac_sm == VoltAcSubMode::AcOverDb => (
312 Function::MV_AC,
313 Unit::VoltAC,
314 Function::MV_AC_DB,
315 dbm_or_v(),
316 ),
317 (DeviceMode::MV_AC, 0) if vac_sm == VoltAcSubMode::DbOverAc => (
318 Function::MV_AC_DB,
319 dbm_or_v(),
320 Function::MV_AC,
321 Unit::VoltAC,
322 ),
323 (DeviceMode::MV_AC, 1) if vac_sm == VoltAcSubMode::Normal => (
324 Function::MV_AC_HZ,
325 Unit::Hertz,
326 Function::MV_AC,
327 Unit::VoltAC,
328 ),
329 (DeviceMode::MV_AC, 1) if vac_sm == VoltAcSubMode::HzOverDb => (
330 Function::MV_AC_HZ,
331 Unit::Hertz,
332 Function::MV_AC_DB,
333 dbm_or_v(),
334 ),
335 (DeviceMode::MV_AC, 1) if vac_sm == VoltAcSubMode::DbOverHz => (
336 Function::MV_AC_DB,
337 dbm_or_v(),
338 Function::MV_AC_HZ,
339 Unit::Hertz,
340 ),
341 (DeviceMode::MV_AC, 2) => (
342 Function::MV_AC_DUTYCYCLE,
343 Unit::Percent,
344 Function::MV_AC_HZ,
345 Unit::Hertz,
346 ),
347 (DeviceMode::MV_AC, 3) => (
348 Function::MV_AC_DUTYCYCLE,
349 Unit::Seconds,
350 Function::MV_AC_HZ,
351 Unit::Hertz,
352 ),
353
354 (DeviceMode::V_DC, 0) if dc_mode == DcMode::DC => {
356 (Function::V_DC, Unit::VoltDC, Function::None, Unit::None)
357 }
358 (DeviceMode::V_DC, 1) if dc_mode == DcMode::DC => {
359 (Function::V_DC_HZ, Unit::Hertz, Function::V_DC, Unit::VoltDC)
360 }
361 (DeviceMode::V_DC, 2) if dc_mode == DcMode::DC => (
362 Function::V_DC_DUTYCYCLE,
363 Unit::Percent,
364 Function::V_DC_HZ,
365 Unit::Hertz,
366 ),
367 (DeviceMode::V_DC, 3) if dc_mode == DcMode::DC => (
368 Function::V_DC_DUTYCYCLE,
369 Unit::Seconds,
370 Function::V_DC_HZ,
371 Unit::Hertz,
372 ),
373 (DeviceMode::V_DC_AC_PLUS_DC, _) if dc_mode == DcMode::DC_OVER_AC => (
375 Function::V_DC_OVER_AC,
376 Unit::VoltDC,
377 Function::V_AC,
378 Unit::VoltAC,
379 ),
380 (DeviceMode::V_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_OVER_DC => (
381 Function::V_AC_OVER_DC,
382 Unit::VoltAC,
383 Function::V_DC,
384 Unit::VoltDC,
385 ),
386 (DeviceMode::V_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_PLUS_DC => (
387 Function::V_AC_PLUS_DC,
388 Unit::Volt,
389 Function::None,
390 Unit::None,
391 ),
392
393 (DeviceMode::MV_DC, 0) if dc_mode == DcMode::DC => {
395 (Function::MV_DC, Unit::VoltDC, Function::None, Unit::None)
396 }
397 (DeviceMode::MV_DC, 1) if dc_mode == DcMode::DC => (
398 Function::MV_DC_HZ,
399 Unit::Hertz,
400 Function::MV_DC,
401 Unit::VoltDC,
402 ),
403 (DeviceMode::MV_DC, 2) if dc_mode == DcMode::DC => (
404 Function::MV_DC_DUTYCYCLE,
405 Unit::Percent,
406 Function::MV_DC_HZ,
407 Unit::Hertz,
408 ),
409 (DeviceMode::MV_DC, 3) if dc_mode == DcMode::DC => (
410 Function::MV_DC_DUTYCYCLE,
411 Unit::Seconds,
412 Function::MV_DC_HZ,
413 Unit::Hertz,
414 ),
415 (DeviceMode::MV_DC_AC_PLUS_DC, _) if dc_mode == DcMode::DC_OVER_AC => (
417 Function::MV_DC_OVER_AC,
418 Unit::VoltDC,
419 Function::MV_AC,
420 Unit::VoltAC,
421 ),
422 (DeviceMode::MV_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_OVER_DC => (
423 Function::MV_AC_OVER_DC,
424 Unit::VoltAC,
425 Function::MV_DC,
426 Unit::VoltDC,
427 ),
428 (DeviceMode::MV_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_PLUS_DC => (
429 Function::MV_AC_PLUS_DC,
430 Unit::Volt,
431 Function::None,
432 Unit::None,
433 ),
434
435 (DeviceMode::OHMS, _) => (Function::OHMS, Unit::Ohm, Function::None, Unit::None),
437
438 (DeviceMode::CONTINUITY, _) => {
440 (Function::CONTINUITY, Unit::None, Function::OHMS, Unit::Ohm)
441 }
442
443 (DeviceMode::CONDUCTANCE, _) => (
445 Function::CONDUCTANCE,
446 Unit::Siemens,
447 Function::None,
448 Unit::None,
449 ),
450
451 (DeviceMode::CAPACITANCE, _) => (
453 Function::CAPACITANCE,
454 Unit::Farad,
455 Function::None,
456 Unit::None,
457 ),
458
459 (DeviceMode::DIODE_TEST, _) => (
461 Function::DIODE_TEST,
462 Unit::VoltDC,
463 Function::None,
464 Unit::None,
465 ),
466
467 (DeviceMode::TEMPERATURE_C, _) => {
469 (Function::TEMPERATURE, Unit::CEL, Function::None, Unit::CEL)
470 }
471 (DeviceMode::TEMPERATURE_F, _) => (
473 Function::TEMPERATURE,
474 Unit::Fahrenheit,
475 Function::None,
476 Unit::Fahrenheit,
477 ),
478
479 (DeviceMode::A_AC, 0) => (Function::A_AC, Unit::AmpereAC, Function::None, Unit::None),
481 (DeviceMode::A_AC, 1) => (
482 Function::A_AC_HZ,
483 Unit::Hertz,
484 Function::A_AC,
485 Unit::AmpereAC,
486 ),
487 (DeviceMode::A_AC, 2) => (
488 Function::A_AC_DUTYCYCLE,
489 Unit::Percent,
490 Function::A_AC_HZ,
491 Unit::Hertz,
492 ),
493 (DeviceMode::A_AC, 3) => (
494 Function::A_AC_DUTYCYCLE,
495 Unit::Seconds,
496 Function::A_AC_HZ,
497 Unit::Hertz,
498 ),
499
500 (DeviceMode::MA_AC, 0) => (Function::MA_AC, Unit::AmpereAC, Function::None, Unit::None),
502 (DeviceMode::MA_AC, 1) => (
503 Function::MA_AC_HZ,
504 Unit::Hertz,
505 Function::MA_AC,
506 Unit::AmpereAC,
507 ),
508 (DeviceMode::MA_AC, 2) => (
509 Function::MA_AC_DUTYCYCLE,
510 Unit::Percent,
511 Function::MA_AC_HZ,
512 Unit::Hertz,
513 ),
514 (DeviceMode::MA_AC, 3) => (
515 Function::MA_AC_DUTYCYCLE,
516 Unit::Seconds,
517 Function::MA_AC_HZ,
518 Unit::Hertz,
519 ),
520
521 (DeviceMode::UA_AC, 0) => (Function::UA_AC, Unit::AmpereAC, Function::None, Unit::None),
523 (DeviceMode::UA_AC, 1) => (
524 Function::UA_AC_HZ,
525 Unit::Hertz,
526 Function::UA_AC,
527 Unit::AmpereAC,
528 ),
529 (DeviceMode::UA_AC, 2) => (
530 Function::UA_AC_DUTYCYCLE,
531 Unit::Percent,
532 Function::UA_AC_HZ,
533 Unit::Hertz,
534 ),
535 (DeviceMode::UA_AC, 3) => (
536 Function::UA_AC_DUTYCYCLE,
537 Unit::Seconds,
538 Function::UA_AC_HZ,
539 Unit::Hertz,
540 ),
541
542 (DeviceMode::A_DC, 0) if dc_mode == DcMode::DC => {
544 (Function::A_DC, Unit::AmpereDC, Function::None, Unit::None)
545 }
546 (DeviceMode::A_DC, 1) if dc_mode == DcMode::DC => (
547 Function::A_DC_HZ,
548 Unit::Hertz,
549 Function::A_DC,
550 Unit::AmpereDC,
551 ),
552 (DeviceMode::A_DC, 2) if dc_mode == DcMode::DC => (
553 Function::A_DC_DUTYCYCLE,
554 Unit::Percent,
555 Function::A_DC_HZ,
556 Unit::Hertz,
557 ),
558 (DeviceMode::A_DC, 3) if dc_mode == DcMode::DC => (
559 Function::A_DC_DUTYCYCLE,
560 Unit::Seconds,
561 Function::A_DC_HZ,
562 Unit::Hertz,
563 ),
564 (DeviceMode::MA_DC, 0) if dc_mode == DcMode::DC => {
566 (Function::MA_DC, Unit::AmpereDC, Function::None, Unit::None)
567 }
568 (DeviceMode::MA_DC, 1) if dc_mode == DcMode::DC => (
569 Function::MA_DC_HZ,
570 Unit::Hertz,
571 Function::MA_DC,
572 Unit::AmpereDC,
573 ),
574 (DeviceMode::MA_DC, 2) if dc_mode == DcMode::DC => (
575 Function::MA_DC_DUTYCYCLE,
576 Unit::Percent,
577 Function::MA_DC_HZ,
578 Unit::Hertz,
579 ),
580 (DeviceMode::MA_DC, 3) if dc_mode == DcMode::DC => (
581 Function::MA_DC_DUTYCYCLE,
582 Unit::Seconds,
583 Function::MA_DC_HZ,
584 Unit::Hertz,
585 ),
586 (DeviceMode::A_DC_AC_PLUS_DC, _) if dc_mode == DcMode::DC_OVER_AC => (
588 Function::A_DC_OVER_AC,
589 Unit::AmpereDC,
590 Function::A_AC,
591 Unit::AmpereAC,
592 ),
593 (DeviceMode::A_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_OVER_DC => (
594 Function::A_AC_OVER_DC,
595 Unit::AmpereAC,
596 Function::A_DC,
597 Unit::AmpereDC,
598 ),
599 (DeviceMode::A_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_PLUS_DC => (
600 Function::A_AC_PLUS_DC,
601 Unit::Ampere,
602 Function::None,
603 Unit::None,
604 ),
605 (DeviceMode::MA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::DC_OVER_AC => (
607 Function::MA_DC_OVER_AC,
608 Unit::AmpereDC,
609 Function::MA_AC,
610 Unit::AmpereAC,
611 ),
612 (DeviceMode::MA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_OVER_DC => (
613 Function::MA_AC_OVER_DC,
614 Unit::AmpereAC,
615 Function::MA_DC,
616 Unit::AmpereDC,
617 ),
618 (DeviceMode::MA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_PLUS_DC => (
619 Function::MA_AC_PLUS_DC,
620 Unit::Ampere,
621 Function::None,
622 Unit::None,
623 ),
624
625 (DeviceMode::UA_DC, 0) if dc_mode == DcMode::DC => {
627 (Function::UA_DC, Unit::AmpereDC, Function::None, Unit::None)
628 }
629 (DeviceMode::UA_DC, 1) if dc_mode == DcMode::DC => (
630 Function::UA_DC_HZ,
631 Unit::Hertz,
632 Function::UA_DC,
633 Unit::AmpereDC,
634 ),
635 (DeviceMode::UA_DC, 2) if dc_mode == DcMode::DC => (
636 Function::UA_DC_DUTYCYCLE,
637 Unit::Percent,
638 Function::UA_DC_HZ,
639 Unit::Hertz,
640 ),
641 (DeviceMode::UA_DC, 3) if dc_mode == DcMode::DC => (
642 Function::UA_DC_DUTYCYCLE,
643 Unit::Seconds,
644 Function::UA_DC_HZ,
645 Unit::Hertz,
646 ),
647 (DeviceMode::UA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::DC_OVER_AC => (
649 Function::UA_DC_OVER_AC,
650 Unit::AmpereDC,
651 Function::UA_AC,
652 Unit::AmpereAC,
653 ),
654 (DeviceMode::UA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_OVER_DC => (
655 Function::UA_AC_OVER_DC,
656 Unit::AmpereAC,
657 Function::UA_DC,
658 Unit::AmpereDC,
659 ),
660 (DeviceMode::UA_DC_AC_PLUS_DC, _) if dc_mode == DcMode::AC_PLUS_DC => (
661 Function::UA_AC_PLUS_DC,
662 Unit::Ampere,
663 Function::None,
664 Unit::None,
665 ),
666
667 _ => {
668 eprintln!(
669 "Unknown function: {}, {}, {:?}, {}",
670 self.f_mea_mode, self.f_hz_mode, dc_mode, self.f_ac_db_mode,
671 );
672 (Function::None, Unit::None, Function::None, Unit::None)
673 }
674 };
675
676 let ter_unit = match (self.f_mea_mode, self.f_hz_mode, self.db_mode()) {
677 (1, 0, true) => Unit::Ohm,
678 (1, 1, true) => Unit::Ohm,
679 (2, 0, true) => Unit::Ohm,
680 (2, 1, true) => Unit::Ohm,
681 _ => Unit::None,
682 };
683
684 if (self.f_auto_hold || self.f_hold || self.f_delta || self.f_fast_mode)
685 && !self.f_delta_pct
686 && !self.db_mode()
687 && sec_f == Function::None
688 && (dc_mode == DcMode::DC || dc_mode == DcMode::AC_PLUS_DC)
689 {
690 (pri_f, pri_unit, pri_f, pri_unit, ter_unit)
691 } else if (self.f_delta_pct) && !self.db_mode() {
692 (pri_f, Unit::Percent, pri_f, pri_unit, ter_unit)
693 } else {
694 (pri_f, pri_unit, sec_f, sec_unit, ter_unit)
695 }
696 }
697}
698
699#[derive(Debug, Clone, Default)]
703pub struct RawMeasurement {
704 pub clock: u32,
706 pub pri_value: i32,
708 pub pri_scale: u8,
710 pub pri_si: i8,
712 pub sec_value: i32,
714 pub sec_scale: u8,
716 pub sec_si: i8,
718 pub sec2_value: i32,
720 pub clock2: u32,
722 pub pri2_value: i32,
724 pub pri2_scale: u8,
726 pub pri2_si: i8,
728 pub info: RawInfo,
730 pub byte0: u8,
732 pub byte1: u8,
734}
735
736impl RawMeasurement {
737 pub fn db_mode(&self) -> bool {
738 self.info.db_mode()
739 }
740
741 pub fn low_battery(&self) -> bool {
742 self.info.f_low_bat
743 }
744}
745
746impl TryFrom<&[u8]> for RawMeasurement {
747 type Error = std::io::Error;
748
749 fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
750 assert!(value.len() >= 32 + RAW_INFO_LEN);
751 let mut cur = Cursor::new(value);
752 let clock = cur.read_u32::<LittleEndian>()?;
753 let pri_value = cur.read_i32::<LittleEndian>()?;
754 let pri_scale = cur.read_u8()?;
755
756 let pri_si = cur.read_i8()?;
757 let sec_value = cur.read_i32::<LittleEndian>()?;
758 let sec_scale = cur.read_u8()?;
759
760 let sec_si = cur.read_i8()?;
761 let sec2_value = cur.read_i32::<LittleEndian>()?;
762 let clock2 = cur.read_u32::<LittleEndian>()?;
763 let pri2_value = cur.read_i32::<LittleEndian>()?;
764 let pri2_scale = cur.read_u8()?;
765 let pri2_si = cur.read_i8()?;
766
767 let info = RawInfo::new(&mut cur)?;
768
769 let byte0 = cur.read_u8()?;
770 let byte1 = cur.read_u8()?;
771
772 Ok(Self {
778 pri_value,
779 pri_scale,
780 sec_value,
781 sec_scale,
782 info,
783 clock,
784 pri_si,
785 sec_si,
786 sec2_value,
787 clock2,
788 pri2_value,
789 pri2_scale,
790 pri2_si,
791 byte0,
792 byte1,
793 })
794 }
795}
796
797#[derive(Debug, Clone)]
799pub struct RawSavedMeasurement {
800 pub clock: u32,
802 pub pri_value: i32,
804 pub pri_scale: u8,
806 pub pri_si: i8,
808 pub sec_value: i32,
810 pub sec_scale: u8,
812 pub sec_si: i8,
814 pub sec2_value: i32,
816 pub clock2: u32,
818 pub pri2_value: i32,
820 pub pri2_scale: u8,
822 pub pri2_si: i8,
824 pub info: RawInfo,
826 pub byte0: u8,
828 pub byte1: u8,
830}
831
832#[derive(Debug, Clone)]
834pub struct RawRecording {
835 pub clock_begin: u32,
837 pub pri_scale: u8,
839 pub pri_si: i8,
841 pub min_value: i32,
843 pub max_value: i32,
845 pub sum_value: i32,
847 pub int0: i32,
849 pub sum_count: u32,
851 pub status: u8,
853 pub byte1: u8,
855 pub clock_end: u32,
857}
858
859impl TryFrom<&[u8]> for RawRecording {
860 type Error = std::io::Error;
861
862 fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
863 assert_eq!(value.len(), 32);
864 let mut cur = Cursor::new(value);
865 let clock_begin = cur.read_u32::<LittleEndian>()?;
866 let pri_scale = cur.read_u8()?;
867 let pri_si = cur.read_i8()?;
868 let min_value = cur.read_i32::<LittleEndian>()?;
869 let max_value = cur.read_i32::<LittleEndian>()?;
870 let sum_value = cur.read_i32::<LittleEndian>()?;
871 let int0 = cur.read_i32::<LittleEndian>()?;
872 let sum_count = cur.read_u32::<LittleEndian>()?;
873 let status = cur.read_u8()?;
874 let byte1 = cur.read_u8()?;
875 let clock_end = cur.read_u32::<LittleEndian>()?;
876 Ok(Self {
877 clock_begin,
878 pri_scale,
879 pri_si,
880 min_value,
881 max_value,
882 sum_value,
883 int0,
884 sum_count,
885 status,
886 byte1,
887 clock_end,
888 })
889 }
890}
891
892#[derive(Debug, Clone)]
894pub struct RawRecordingSession {
895 pub recordings: Vec<RawRecording>,
896 pub init_value: i32,
897 pub init_scale: u8,
898 pub init_prefix: i8,
899 pub info: RawInfo,
900}
901
902impl TryFrom<&[u8]> for RawRecordingSession {
903 type Error = std::io::Error;
904
905 fn try_from(value: &[u8]) -> std::result::Result<Self, Self::Error> {
906 const REC_SIZE: usize = 32;
907 let mut cur = Cursor::new(value);
908 let data_count = cur.read_u16::<LittleEndian>()?;
909 let init_value = cur.read_i32::<LittleEndian>()?;
910 let init_scale = cur.read_u8()?;
911 let init_prefix = cur.read_i8()?;
912 let info = RawInfo::new(&mut cur)?;
913 let mut recordings = Vec::with_capacity(data_count as usize);
914 let mut buf = [0; REC_SIZE];
915 for _ in 0..data_count {
916 cur.read_exact(&mut buf)?;
917 recordings.push(RawRecording::try_from(&buf[..])?);
918 }
919 Ok(Self {
920 recordings,
921 init_value,
922 init_scale,
923 init_prefix,
924 info,
925 })
926 }
927}
928
929fn get_bits16(mask: u16, value: u16) -> u16 {
931 assert_ne!(mask, 0);
932 let shift = mask.trailing_zeros();
933 (value & mask) >> shift
934}