f189ctrl/
rawmea.rs

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/// Raw Measurement information block
16#[derive(Debug, Clone, Default)]
17pub struct RawInfo {
18    /// 1 on AutoHOLD
19    pub f_autohold2: bool,
20    /// 1 on HOLD or AutoHOLD
21    pub f_hold2: bool,
22    /// 1 on logging mode
23    pub f_log_mode: bool,
24    /// 1 on AVG
25    pub f_avg: bool,
26    /// 1 on MAX
27    pub f_max: bool,
28    /// 1 on MIN
29    pub f_min: bool,
30    /// 1 on Fast-Min/Max
31    pub f_fast_mode: bool,
32    /// 1 on low battery
33    pub f_low_bat: bool,
34    /// 1 on Dangerous voltage (bolt), also on Setup or ViewMem screen
35    pub f_bolt: bool,
36    /// 1 on Delta (rel.), 0 on Delta%
37    pub f_delta: bool,
38    /// 1 on Delta%, 0 on Delta
39    pub f_delta_pct: bool,
40    /// 3 if saves or logs in ViewMem screen, otherwise 0, 1 if Clr? is displayed
41    pub f_mem_clear: u8,
42    /// 1 on Auto Range
43    pub f_auto_range: bool,
44    /// 1 on Manual Range
45    pub f_man_range: bool,
46    /// 1 on shift sign on screen (yellow button pressed)
47    pub f_shift_sign: bool,
48    /// Measurement mode (dial switch + blue button, A/mA pins)
49    pub f_mea_mode: u8,
50    /// 1 on Hz, 2 on DutyCycle%, 3 on ms
51    pub f_hz_mode: u8,
52    /// 1 on Min/Max mode
53    pub f_mn_mx_mode: bool,
54    /// 1 on Fast mode
55    pub f_fast_mode2: bool,
56    /// Unknown
57    pub f_ubit1: bool,
58    /// 1 on Max, 2 on Min, 3 on AVG
59    pub f_minmaxavg: u8,
60    /// Unknown
61    pub f_ubit2: bool,
62    /// 1 on rising etch
63    pub f_rising_etch: bool,
64    /// 1 on falling etch
65    pub f_fall_etch: bool,
66    /// Substates V mV mA uA (DC Mode only?)
67    pub f_sub_acdc: u8,
68    /// Unknown
69    pub f_ubit3: bool,
70    /// 1 on HOLD (0 on AutoHOLD)
71    pub f_hold: bool,
72    /// 1 on AutoHOLD (0 on HOLD)
73    pub f_auto_hold: bool,
74    /// Unknown
75    pub f_ubit4: bool,
76    /// 1 on dBV, 0 on dBm
77    pub f_db_v_or_m: bool,
78    /// 1 on C, 0 on F
79    pub f_temp_c_or_f: bool,
80    /// 1 on Delta (rel. mode)
81    pub f_delta2: bool,
82    /// 1 on Delta%
83    pub f_delta_pct2: bool,
84    /// Unknown
85    pub f_ubit5: bool,
86    /// Sub-mode for dBm/V (AC) views
87    pub f_ac_db_mode: u8,
88    /// 1 on 4 digits, 0 on 5 digits
89    pub f_digits: bool,
90    /// 1 on Range displayed (TODO: check on C/F)
91    pub f_range_disp: bool,
92    /// Selected range
93    pub selected_range: u8,
94    /// Current view
95    pub current_view: u8,
96    /// dBm reference
97    pub dbm_ref: u16,
98}
99
100pub(crate) const RAW_INFO_LEN: usize = 10;
101
102/// Raw information block
103impl 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_unit_db_ac  = get_bits16(0b0000_1000_0000_0000, flags3) > 0;
151        //let f_unit_ac_db  = get_bits16(0b0001_0000_0000_0000, flags3) > 0;
152        //let f_unit_hz_db  = get_bits16(0b0010_0000_0000_0000, flags3) > 0;
153        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_unit_ac_db | self.f_unit_db_ac | self.f_unit_hz_db
201        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        //println!("fun: {}, {}, {:?}, {}, {}, {}", value.f_mea_mode, value.f_hz_mode, dc_mode, value.f_unit_ac_db, value.f_unit_db_ac, value.f_unit_hz_db);
266        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            // V/AC = 1
271            (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            // mV/AC = 2
308            (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            // V/DC = 3
355            (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            // V/DC ac+dc = 5
374            (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            // mV/DC = 4
394            (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            // mV/DC ac+dc = 6
416            (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            // Ohm = 9
436            (DeviceMode::OHMS, _) => (Function::OHMS, Unit::Ohm, Function::None, Unit::None),
437
438            // Beeper = 11
439            (DeviceMode::CONTINUITY, _) => {
440                (Function::CONTINUITY, Unit::None, Function::OHMS, Unit::Ohm)
441            }
442
443            // Siemens = 10
444            (DeviceMode::CONDUCTANCE, _) => (
445                Function::CONDUCTANCE,
446                Unit::Siemens,
447                Function::None,
448                Unit::None,
449            ),
450
451            // Capacitor = 12
452            (DeviceMode::CAPACITANCE, _) => (
453                Function::CAPACITANCE,
454                Unit::Farad,
455                Function::None,
456                Unit::None,
457            ),
458
459            // Diode = 13
460            (DeviceMode::DIODE_TEST, _) => (
461                Function::DIODE_TEST,
462                Unit::VoltDC,
463                Function::None,
464                Unit::None,
465            ),
466
467            // Temp.C = 26
468            (DeviceMode::TEMPERATURE_C, _) => {
469                (Function::TEMPERATURE, Unit::CEL, Function::None, Unit::CEL)
470            }
471            // Temp.F = 27
472            (DeviceMode::TEMPERATURE_F, _) => (
473                Function::TEMPERATURE,
474                Unit::Fahrenheit,
475                Function::None,
476                Unit::Fahrenheit,
477            ),
478
479            // A/AC = 14
480            (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            // mA/AC = 15
501            (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            // µA/AC = 16
522            (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            // A/DC = 17
543            (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            // mA/DC = 18
565            (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            // A/DC ac+dc = 20
587            (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            // mA/DC ac+dc = 21
606            (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            // µA/DC = 19
626            (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            // µA/DC ac+dc = 22
648            (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/// Raw measurement
700///
701/// Internal representation of measurements
702#[derive(Debug, Clone, Default)]
703pub struct RawMeasurement {
704    /// 1/10 seconds since reference
705    pub clock: u32,
706    /// Primary reading value
707    pub pri_value: i32,
708    /// Primary reading scale
709    pub pri_scale: u8,
710    /// Primary reading SI unit multiplier, 1 = 10^3, 2 = 10^6, 3 = 10^9, -1 = 10^-3 etc.
711    pub pri_si: i8,
712    /// Secondary reading value
713    pub sec_value: i32,
714    /// Secondary reading scale
715    pub sec_scale: u8,
716    /// Primary reading SI unit multiplier, 1 = 10^3, 2 = 10^6, 3 = 10^9, -1 = 10^-3 etc.
717    pub sec_si: i8,
718    /// Secondary reading value, 2. occour.
719    pub sec2_value: i32,
720    /// Clock, 2. occour., maybe it's read start and read-stop clock?
721    pub clock2: u32,
722    /// Primary reading value, 2. occour.
723    pub pri2_value: i32,
724    /// Primary reading scale, 2. occour.
725    pub pri2_scale: u8,
726    /// Primary reading scale, 2. occour.
727    pub pri2_si: i8,
728    /// Reading information
729    pub info: RawInfo,
730    /// Unknown byte 0
731    pub byte0: u8,
732    /// Unknown byte 1
733    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        //eprintln!("clock1:{clock} {pri_value:011}/{pri_scale:03} pri_si:{pri_si:03} {sec_value:011}/{sec_scale:03} sec_si:{sec_si:03} sec2:{sec2_value:011} clock2:{clock2} pri2:{pri2_value:011}/{pri2_scale:04} si:{pri2_si:03} flags1:{flags1:#018b} db:{dbref:04} flags2:{flags2:#018b} flags3:{flags3:#018b} range:0x{selected_range:x} view:{current_view}");
773
774        //eprintln!("IN: {:?}", &value[2+26..]);
775        //eprintln!("IN: {:?}", &value[2..]);
776
777        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/// Raw saved measurement
798#[derive(Debug, Clone)]
799pub struct RawSavedMeasurement {
800    /// 1/10 seconds since reference
801    pub clock: u32,
802    /// Primary reading value
803    pub pri_value: i32,
804    /// Primary reading scale
805    pub pri_scale: u8,
806    /// Primary reading SI unit multiplier, 1 = 10^3, 2 = 10^6, 3 = 10^9, -1 = 10^-3 etc.
807    pub pri_si: i8,
808    /// Secondary reading value
809    pub sec_value: i32,
810    /// Secondary reading scale
811    pub sec_scale: u8,
812    /// Primary reading SI unit multiplier, 1 = 10^3, 2 = 10^6, 3 = 10^9, -1 = 10^-3 etc.
813    pub sec_si: i8,
814    /// Secondary reading value, 2. occour.
815    pub sec2_value: i32,
816    /// Clock, 2. occour., maybe it's read start and read-stop clock?
817    pub clock2: u32,
818    /// Primary reading value, 2. occour.
819    pub pri2_value: i32,
820    /// Primary reading scale, 2. occour.
821    pub pri2_scale: u8,
822    /// Primary reading scale, 2. occour.
823    pub pri2_si: i8,
824    /// Reading information
825    pub info: RawInfo,
826    /// Unknown byte 0
827    pub byte0: u8,
828    /// Unknown byte 1
829    pub byte1: u8,
830}
831
832/// Raw recording
833#[derive(Debug, Clone)]
834pub struct RawRecording {
835    /// 1/10 seconds since reference
836    pub clock_begin: u32,
837    /// Primary reading scale
838    pub pri_scale: u8,
839    /// Primary reading SI unit multiplier, 1 = 10^3, 2 = 10^6, 3 = 10^9, -1 = 10^-3 etc.
840    pub pri_si: i8,
841    /// Min reading value
842    pub min_value: i32,
843    /// Max reading value
844    pub max_value: i32,
845    /// Summed reading value
846    pub sum_value: i32,
847    /// Unknown
848    pub int0: i32,
849    /// Count of values included in sum_value
850    pub sum_count: u32,
851    /// Status
852    pub status: u8,
853    /// Unknown
854    pub byte1: u8,
855    /// 1/10 seconds since reference
856    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/// Raw recording session
893#[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
929/// Helper function to extract bits
930fn get_bits16(mask: u16, value: u16) -> u16 {
931    assert_ne!(mask, 0);
932    let shift = mask.trailing_zeros();
933    (value & mask) >> shift
934}