]> sigrok.org Git - libsigrok.git/blob - src/dmm/eev121gw.c
Doxygen: Properly mark a few symbols as private.
[libsigrok.git] / src / dmm / eev121gw.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2018 Gerhard Sittig <gerhard.sittig@gmx.net>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * @file
22  *
23  * EEVblog 121GW 19-bytes binary protocol parser.
24  *
25  * Note that this protocol is different from other meters. We need not
26  * decode the LCD presentation (segments a-g and dot of seven segment
27  * displays). Neither need we decode a textual presentation consisting
28  * of number strings with decimals, and scale/quantity suffixes. Instead
29  * a binary packet is received which contains an unsigned mantissa for
30  * the value, and a number of boolean flags as well as bitfields for modes
31  * and ranges.
32  *
33  * But the protocol is also similar to the four-display variant of the
34  * metex14 protocol. A single DMM packet contains information for two
35  * displays and a bargraph, as well as several flags corresponding to
36  * display indicators and global device state. The vendor's documentation
37  * refers to these sections as "main", "sub", "bar", and "icon".
38  *
39  * It's essential to understand that the serial-dmm API is only able to
40  * communicate a single float value (including its precision and quantity
41  * details) in a single parse call. Which is why we keep a channel index
42  * in the 'info' structure, and run the parse routine several times upon
43  * reception of a single packet. This approach is shared with the metex14
44  * parser.
45  *
46  * The parse routine here differs from other DMM parsers which typically
47  * are split into routines which parse a value (get a number and exponent),
48  * parse flags, and handle flags which were parsed before. The 121GW
49  * meter's packets don't fit this separation naturally, getting the value
50  * and related flags heavily depends on which display shall get inspected,
51  * thus should be done at the same time. Filling in an 'info' structure
52  * from packet content first, and mapping this 'info' to the 'analog'
53  * details then still is very useful for maintainability.
54  *
55  * TODO:
56  * - The meter is feature packed. This implementation does support basic
57  *   operation (voltage, current, power, resistance, continuity, diode,
58  *   capacitance, temperature). Support for remaining modes, previously
59  *   untested ranges, and advanced features (DC+AC, VA power, dB gain,
60  *   burden voltage) may be missing or incomplete. Ranges support and
61  *   value scaling should be considered "under development" in general
62  *   until test coverage was increased. Some flags are not evaluated
63  *   correctly yet, or not at all (min/max/avg, memory).
64  * - Test previously untested modes: current, power, gain, sub display
65  *   modes. Test untested ranges (voltage above 30V, temperature above
66  *   30deg (into the hundreds), negative temperatures, large resistors,
67  *   large capacitors). Test untested features (min/max/avg, 1ms peak,
68  *   log memory).
69  * - It's assumed that a continuous data stream was arranged for. This
70  *   implementation does not support the "packet request" API. Also I
71  *   was to understand that once the request was sent (write 0300 to
72  *   handle 9, after connecting) no further request is needed. Only
73  *   the loss of communication may need recovery, which we leave as an
74  *   option for later improvement, or as a feature of an external helper
75  *   which feeds the COM port from Bluetooth communication data, or
76  *   abstracts away the BLE communication.
77  *
78  * Implementation notes:
79  * - Yes some ranges seem duplicate but that's fine. The meter's packets
80  *   do provide multiple range indices for some of the modes which do
81  *   communicate values in the same range of values.
82  * - Some of the packet's bits don't match the available documentation.
83  *   Some of the meter's features are not available to the PC side by
84  *   means of inspecting packets.
85  *   - Bit 5 of "bar value" was seen with value 1 in FREQ and OHM:
86  *     f2  17 84 21 21  08 00 00 00  64 01 01 17  12 37  02 40 00  7d
87  *     So we keep the test around but accept when it fails.
88  *   - The "gotta beep" activity of continuity/break test mode is not
89  *     available in the packets.
90  * - The interpretation of range indices depends on the specific mode
91  *   (meter's function, and range when selectable by the user like mV).
92  *   As does the precision of results.
93  */
94
95 #include "config.h"
96 #include <ctype.h>
97 #include <glib.h>
98 #include <math.h>
99 #include <string.h>
100 #include <strings.h>
101 #include "libsigrok/libsigrok.h"
102 #include "libsigrok-internal.h"
103
104 #define LOG_PREFIX "eev121gw"
105
106 /*
107  * TODO:
108  * When these bit field extraction helpers move to some common location,
109  * their names may need adjustment to reduce the potential for conflicts.
110  */
111 // #define BIT(n) (1UL << (n))
112 #define MASK(len) ((1UL << (len)) - 1)
113 #define FIELD_PL(v, pos, len) (((v) >> (pos)) & MASK(len))
114 #define FIELD_NL(v, name) FIELD_PL(v, POS_ ## name, LEN_ ## name)
115 #define FIELD_NB(v, name) FIELD_PL(v, POS_ ## name, 1)
116
117 /*
118  * Support compile time checks for expected sizeof() results etc, like
119  *   STATIC_ASSERT(sizeof(struct packet) == 19, "packet size");
120  * Probably should go to some common location.
121  * See http://www.pixelbeat.org/programming/gcc/static_assert.html for details.
122  */
123 #define ASSERT_CONCAT_(a, b) a ## b
124 #define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b)
125 /* These can't be used after statements in c89. */
126 #ifdef __COUNTER__
127   #define STATIC_ASSERT(e, m) \
128     ; enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1 / (int)(!!(e)) }
129 #else
130   /*
131    * This can't be used twice on the same line so ensure if using in headers
132    * that the headers are not included twice (by wrapping in #ifndef...#endif).
133    * Note it doesn't cause an issue when used on same line of separate modules
134    * compiled with gcc -combine -fwhole-program.
135    */
136   #define STATIC_ASSERT(e, m) \
137     ; enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1 / (int)(!!(e)) }
138 #endif
139
140 /*
141  * Symbolic identifiers for access to the packet's payload. "Offsets"
142  * address bytes within the packet. "Positions" specify the (lowest)
143  * bit number of a field, "lengths" specify the fields' number of bits.
144  * "Values" specify magic values or fixed content (SBZ, RSV, etc).
145  */
146 enum eev121gw_packet_offs {
147         OFF_START_CMD,
148 #define  VAL_START_CMD          0xf2
149         OFF_SERIAL_3,
150         OFF_SERIAL_2,
151         OFF_SERIAL_1,
152         OFF_SERIAL_0,
153 #define  POS_SERIAL_YEAR        24
154 #define  LEN_SERIAL_YEAR        8
155 #define  POS_SERIAL_MONTH       20
156 #define  LEN_SERIAL_MONTH       4
157 #define  POS_SERIAL_NUMBER      0
158 #define  LEN_SERIAL_NUMBER      20
159         OFF_MAIN_MODE,
160 #define  POS_MAIN_MODE_VAL_U    6
161 #define  LEN_MAIN_MODE_VAL_U    2
162 #define  POS_MAIN_MODE_RSV_5    5
163 #define  POS_MAIN_MODE_MODE     0
164 #define  LEN_MAIN_MODE_MODE     5
165         OFF_MAIN_RANGE,
166 #define  POS_MAIN_RANGE_OFL     7
167 #define  POS_MAIN_RANGE_SIGN    6
168 #define  POS_MAIN_RANGE_DEGC    5
169 #define  POS_MAIN_RANGE_DEGF    4
170 #define  POS_MAIN_RANGE_RANGE   0
171 #define  LEN_MAIN_RANGE_RANGE   4
172         OFF_MAIN_VAL_H,
173         OFF_MAIN_VAL_L,
174         OFF_SUB_MODE,
175 #define  POS_SUB_MODE_MODE      0
176 #define  LEN_SUB_MODE_MODE      8
177         OFF_SUB_RANGE,
178 #define  POS_SUB_RANGE_OFL      7
179 #define  POS_SUB_RANGE_SIGN     6
180 #define  POS_SUB_RANGE_K        5
181 #define  POS_SUB_RANGE_HZ       4
182 #define  POS_SUB_RANGE_RSV_3    3
183 #define  POS_SUB_RANGE_POINT    0
184 #define  LEN_SUB_RANGE_POINT    3
185         OFF_SUB_VAL_H,
186         OFF_SUB_VAL_L,
187         OFF_BAR_STATUS,
188 #define  POS_BAR_STATUS_RSV_5   5
189 #define  LEN_BAR_STATUS_RSV_5   3
190 #define  POS_BAR_STATUS_USE     4
191 #define  POS_BAR_STATUS_150     3
192 #define  POS_BAR_STATUS_SIGN    2
193 #define  POS_BAR_STATUS_1K_500  0
194 #define  LEN_BAR_STATUS_1K_500  2
195         OFF_BAR_VALUE,
196 #define  POS_BAR_VALUE_RSV_6    6
197 #define  LEN_BAR_VALUE_RSV_6    2
198 #define  POS_BAR_VALUE_RSV_5    5
199 #define  POS_BAR_VALUE_VALUE    0
200 #define  LEN_BAR_VALUE_VALUE    5
201         OFF_ICON_STS_1,
202 #define  POS_ICON_STS1_DEGC     7
203 #define  POS_ICON_STS1_1KHZ     6
204 #define  POS_ICON_STS1_1MSPK    5
205 #define  POS_ICON_STS1_DCAC     3
206 #define  LEN_ICON_STS1_DCAC     2
207 #define  POS_ICON_STS1_AUTO     2
208 #define  POS_ICON_STS1_APO      1
209 #define  POS_ICON_STS1_BAT      0
210         OFF_ICON_STS_2,
211 #define  POS_ICON_STS2_DEGF     7
212 #define  POS_ICON_STS2_BT       6
213 #define  POS_ICON_STS2_UNK      5 /* TODO: What is this flag? 20mA loop current? */
214 #define  POS_ICON_STS2_REL      4
215 #define  POS_ICON_STS2_DBM      3
216 #define  POS_ICON_STS2_MINMAX   0 /* TODO: How to interpret the 3-bit field? */
217 #define  LEN_ICON_STS2_MINMAX   3
218         OFF_ICON_STS_3,
219 #define  POS_ICON_STS3_RSV_7    7
220 #define  POS_ICON_STS3_TEST     6
221 #define  POS_ICON_STS3_MEM      4 /* TODO: How to interpret the 2-bit field? */
222 #define  LEN_ICON_STS3_MEM      2
223 #define  POS_ICON_STS3_AHOLD    2
224 #define  LEN_ICON_STS3_AHOLD    2
225 #define  POS_ICON_STS3_AC       1
226 #define  POS_ICON_STS3_DC       0
227         OFF_CHECKSUM,
228         /* This is not an offset, but the packet's "byte count". */
229         PACKET_LAST_OFF,
230 };
231
232 STATIC_ASSERT(PACKET_LAST_OFF == EEV121GW_PACKET_SIZE,
233         "byte offsets vs packet length mismatch");
234
235 enum mode_codes {
236         /* Modes for 'main' and 'sub' displays. */
237         MODE_LOW_Z = 0,
238         MODE_DC_V = 1,
239         MODE_AC_V = 2,
240         MODE_DC_MV = 3,
241         MODE_AC_MV = 4,
242         MODE_TEMP = 5,
243         MODE_FREQ = 6,
244         MODE_PERIOD = 7,
245         MODE_DUTY = 8,
246         MODE_RES = 9,
247         MODE_CONT = 10,
248         MODE_DIODE = 11,
249         MODE_CAP = 12,
250         MODE_AC_UVA = 13,
251         MODE_AC_MVA = 14,
252         MODE_AC_VA = 15,
253         MODE_AC_UA = 16,
254         MODE_DC_UA = 17,
255         MODE_AC_MA = 18,
256         MODE_DC_MA = 19,
257         MODE_AC_A = 20,
258         MODE_DC_A = 21,
259         MODE_DC_UVA = 22,
260         MODE_DC_MVA = 23,
261         MODE_DC_VA = 24,
262         /* More modes for 'sub' display. */
263         MODE_SUB_TEMPC = 100,
264         MODE_SUB_TEMPF = 105,
265         MODE_SUB_BATT = 110,
266         MODE_SUB_APO_ON = 120,
267         MODE_SUB_APO_OFF = 125,
268         MODE_SUB_YEAR = 130,
269         MODE_SUB_DATE = 135,
270         MODE_SUB_TIME = 140,
271         MODE_SUB_B_VOLT = 150,
272         MODE_SUB_LCD = 160,
273         MODE_SUB_CONT_PARM_0 = 170,
274         MODE_SUB_CONT_PARM_1 = 171,
275         MODE_SUB_CONT_PARM_2 = 172,
276         MODE_SUB_CONT_PARM_3 = 173,
277         MODE_SUB_DBM = 180,
278         MODE_SUB_IVAL = 190,
279 };
280
281 enum range_codes {
282         RANGE_0,
283         RANGE_1,
284         RANGE_2,
285         RANGE_3,
286         RANGE_4,
287         RANGE_5,
288         RANGE_6,
289         RANGE_MAX,
290 };
291
292 enum bar_range_codes {
293         BAR_RANGE_5,
294         BAR_RANGE_50,
295         BAR_RANGE_500,
296         BAR_RANGE_1000,
297 };
298 #define BAR_VALUE_MAX 25
299
300 enum acdc_codes {
301         ACDC_NONE,
302         ACDC_DC,
303         ACDC_AC,
304         ACDC_ACDC,
305 };
306
307 SR_PRIV const char *eev121gw_channel_formats[EEV121GW_DISPLAY_COUNT] = {
308         /*
309          * TODO:
310          * The "main", "sub", "bar" names were taken from the packet
311          * description. Will users prefer "primary", "secondary", and
312          * "bargraph" names? Or even-length "pri", "sec", "bar" instead?
313          */
314         "main", "sub", "bar",
315 };
316
317 /*
318  * See page 69 in the 2018-09-24 manual for a table of modes and their
319  * respective ranges ("Calibration Reference Table"). This is the input
320  * to get the number of significant digits, and the decimal's position.
321  */
322 struct mode_range_item {
323         const char *desc; /* Description, for diagnostics. */
324         int digits; /* Number of significant digits, see @ref sr_analog_encoding. */
325         int factor; /* Factor to convert the uint to a float. */
326 };
327
328 struct mode_range_items {
329         size_t range_count;
330         const struct mode_range_item ranges[RANGE_MAX];
331 };
332
333 static const struct mode_range_items mode_ranges_lowz = {
334         .range_count = 1,
335         .ranges = {
336                 { .desc =  "600.0V", .digits = 1, .factor = 1, },
337         },
338 };
339
340 static const struct mode_range_items mode_ranges_volts = {
341         .range_count = 4,
342         .ranges = {
343                 { .desc = "5.0000V", .digits = 4, .factor = 4, },
344                 { .desc = "50.000V", .digits = 3, .factor = 3, },
345                 { .desc = "500.00V", .digits = 2, .factor = 2, },
346                 { .desc =  "600.0V", .digits = 1, .factor = 1, },
347         },
348 };
349
350 static const struct mode_range_items mode_ranges_millivolts = {
351         .range_count = 2,
352         .ranges = {
353                 { .desc = "50.000mV", .digits = 6, .factor = 6, },
354                 { .desc = "500.00mV", .digits = 5, .factor = 5, },
355         },
356 };
357
358 static const struct mode_range_items mode_ranges_temp = {
359         .range_count = 1,
360         .ranges = {
361                 { .desc = "-200.0C ~ 1350.0C", .digits = 1, .factor = 1, },
362         },
363 };
364
365 static const struct mode_range_items mode_ranges_freq = {
366         .range_count = 5,
367         .ranges = {
368                 { .desc = "99.999Hz", .digits = 3, .factor = 3, },
369                 { .desc = "999.99Hz", .digits = 2, .factor = 2, },
370                 { .desc = "9.9999kHz", .digits = 1, .factor = 1, },
371                 { .desc = "99.999kHz", .digits = 0, .factor = 0, },
372                 { .desc = "999.99kHz", .digits = -1, .factor = -1, },
373         },
374 };
375
376 static const struct mode_range_items mode_ranges_period = {
377         .range_count = 3,
378         .ranges = {
379                 { .desc = "9.9999ms", .digits = 7, .factor = 7, },
380                 { .desc = "99.999ms", .digits = 6, .factor = 6, },
381                 { .desc = "999.99ms", .digits = 5, .factor = 5, },
382         },
383 };
384
385 static const struct mode_range_items mode_ranges_duty = {
386         .range_count = 1,
387         .ranges = {
388                 { .desc = "99.9%", .digits = 1, .factor = 1, },
389         },
390 };
391
392 static const struct mode_range_items mode_ranges_res = {
393         .range_count = 7,
394         .ranges = {
395                 { .desc = "50.000R", .digits = 3, .factor = 3, },
396                 { .desc = "500.00R", .digits = 2, .factor = 2, },
397                 { .desc = "5.0000k", .digits = 1, .factor = 1, },
398                 { .desc = "50.000k", .digits = 0, .factor = 0, },
399                 { .desc = "500.00k", .digits = -1, .factor = -1, },
400                 { .desc = "5.0000M", .digits = -2, .factor = -2, },
401                 { .desc = "50.000M", .digits = -3, .factor = -3, },
402         },
403 };
404
405 static const struct mode_range_items mode_ranges_cont = {
406         .range_count = 1,
407         .ranges = {
408                 { .desc = "500.00R", .digits = 2, .factor = 2, },
409         },
410 };
411
412 static const struct mode_range_items mode_ranges_diode = {
413         .range_count = 2,
414         .ranges = {
415                 { .desc = "3.0000V", .digits = 4, .factor = 4, },
416                 { .desc = "15.000V", .digits = 3, .factor = 3, },
417         },
418 };
419
420 static const struct mode_range_items mode_ranges_cap = {
421         .range_count = 6,
422         .ranges = {
423                 { .desc =  "10.00n", .digits = 11, .factor = 11, },
424                 { .desc =  "100.0n", .digits = 10, .factor = 10, },
425                 { .desc =  "1.000u", .digits = 9, .factor = 9, },
426                 { .desc =  "10.00u", .digits = 8, .factor = 8, },
427                 { .desc =  "100.0u", .digits = 7, .factor = 7, },
428                 { .desc =  "10.00m", .digits = 5, .factor = 5, },
429         },
430 };
431
432 static const struct mode_range_items mode_ranges_pow_va = {
433         .range_count = 4,
434         .ranges = {
435                 { .desc = "2500.0mVA", .digits = 4, .factor = 4, },
436                 { .desc = "25000.mVA", .digits = 3, .factor = 3, },
437                 { .desc = "25.000VA", .digits = 3, .factor = 3, },
438                 { .desc = "500.00VA", .digits = 2, .factor = 2, },
439         },
440 };
441
442 static const struct mode_range_items mode_ranges_pow_mva = {
443         .range_count = 4,
444         .ranges = {
445                 { .desc = "25.000mVA", .digits = 6, .factor = 6, },
446                 { .desc = "250.00mVA", .digits = 5, .factor = 5, },
447                 { .desc = "250.00mVA", .digits = 5, .factor = 5, },
448                 { .desc = "2500.0mVA", .digits = 4, .factor = 4, },
449         },
450 };
451
452 static const struct mode_range_items mode_ranges_pow_uva = {
453         .range_count = 4,
454         .ranges = {
455                 { .desc = "250.00uVA", .digits = 8, .factor = 8, },
456                 { .desc = "2500.0uVA", .digits = 7, .factor = 7, },
457                 { .desc = "2500.0uVA", .digits = 7, .factor = 7, },
458                 { .desc = "25000.uVA", .digits = 6, .factor = 6, },
459         },
460 };
461
462 static const struct mode_range_items mode_ranges_curr_a = {
463         .range_count = 3,
464         .ranges = {
465                 { .desc = "500.00mA", .digits = 5, .factor = 5, },
466                 { .desc = "5.0000A", .digits = 4, .factor = 4, },
467                 { .desc = "10.000A", .digits = 3, .factor = 3, },
468         },
469 };
470
471 static const struct mode_range_items mode_ranges_curr_ma = {
472         .range_count = 2,
473         .ranges = {
474                 { .desc = "5.0000mA", .digits = 7, .factor = 7, },
475                 { .desc = "50.000mA", .digits = 6, .factor = 6, },
476         },
477 };
478
479 static const struct mode_range_items mode_ranges_curr_ua = {
480         .range_count = 2,
481         .ranges = {
482                 { .desc = "50.000uA", .digits = 9, .factor = 9, },
483                 { .desc = "500.00uA", .digits = 8, .factor = 8, },
484         },
485 };
486
487 static const struct mode_range_items *mode_ranges_main[] = {
488         [MODE_LOW_Z] = &mode_ranges_lowz,
489         [MODE_DC_V] = &mode_ranges_volts,
490         [MODE_AC_V] = &mode_ranges_volts,
491         [MODE_DC_MV] = &mode_ranges_millivolts,
492         [MODE_AC_MV] = &mode_ranges_millivolts,
493         [MODE_TEMP] = &mode_ranges_temp,
494         [MODE_FREQ] = &mode_ranges_freq,
495         [MODE_PERIOD] = &mode_ranges_period,
496         [MODE_DUTY] = &mode_ranges_duty,
497         [MODE_RES] = &mode_ranges_res,
498         [MODE_CONT] = &mode_ranges_cont,
499         [MODE_DIODE] = &mode_ranges_diode,
500         [MODE_CAP] = &mode_ranges_cap,
501         [MODE_DC_VA] = &mode_ranges_pow_va,
502         [MODE_AC_VA] = &mode_ranges_pow_va,
503         [MODE_DC_MVA] = &mode_ranges_pow_mva,
504         [MODE_AC_MVA] = &mode_ranges_pow_mva,
505         [MODE_DC_UVA] = &mode_ranges_pow_uva,
506         [MODE_AC_UVA] = &mode_ranges_pow_uva,
507         [MODE_DC_A] = &mode_ranges_curr_a,
508         [MODE_AC_A] = &mode_ranges_curr_a,
509         [MODE_DC_MA] = &mode_ranges_curr_ma,
510         [MODE_AC_MA] = &mode_ranges_curr_ma,
511         [MODE_DC_UA] = &mode_ranges_curr_ua,
512         [MODE_AC_UA] = &mode_ranges_curr_ua,
513 };
514
515 /*
516  * The secondary display encodes SI units / scaling differently from the
517  * main display, and fewer ranges are available. So we share logic between
518  * displays for scaling, but have to keep separate tables for the displays.
519  */
520
521 static const struct mode_range_items mode_ranges_temp_sub = {
522         .range_count = 2,
523         .ranges = {
524                 [1] = { .desc =  "100.0C", .digits = 1, .factor = 1, },
525         },
526 };
527
528 static const struct mode_range_items mode_ranges_freq_sub = {
529         .range_count = 4,
530         .ranges = {
531                 [1] = { .desc =  "999.9Hz", .digits = 1, .factor = 1, },
532                 [2] = { .desc =  "99.99Hz", .digits = 2, .factor = 2, },
533                 [3] = { .desc =  "9.999kHz", .digits = 3, .factor = 3, },
534         },
535 };
536
537 static const struct mode_range_items mode_ranges_batt_sub = {
538         .range_count = 2,
539         .ranges = {
540                 [1] = { .desc =   "10.0V", .digits = 1, .factor = 1, },
541         },
542 };
543
544 static const struct mode_range_items mode_ranges_gain_sub = {
545         .range_count = 4,
546         .ranges = {
547                 [1] = { .desc = "5000.0dBm", .digits = 1, .factor = 1, },
548                 [2] = { .desc = "500.00dBm", .digits = 2, .factor = 2, },
549                 [3] = { .desc = "50.000dBm", .digits = 3, .factor = 3, },
550         },
551 };
552
553 static const struct mode_range_items mode_ranges_diode_sub = {
554         .range_count = 1,
555         .ranges = {
556                 [0] = { .desc =   "15.0V", .digits = 0, .factor = 0, },
557         },
558 };
559
560 static const struct mode_range_items mode_ranges_volts_sub = {
561         .range_count = 5,
562         .ranges = {
563                 [3] = { .desc = "50.000V", .digits = 3, .factor = 3, },
564                 [4] = { .desc = "5.0000V", .digits = 4, .factor = 4, },
565         },
566 };
567
568 static const struct mode_range_items mode_ranges_mamps_sub = {
569         .range_count = 5,
570         .ranges = {
571                 [2] = { .desc = "500.00mA", .digits = 5, .factor = 5, },
572                 [3] = { .desc = "50.000mA", .digits = 6, .factor = 6, },
573                 [4] = { .desc = "5.0000mA", .digits = 7, .factor = 7, },
574         },
575 };
576
577 static const struct mode_range_items mode_ranges_uamps_sub = {
578         .range_count = 5,
579         .ranges = {
580                 [4] = { .desc = "5.0000mA", .digits = 7, .factor = 7, },
581         },
582 };
583
584 static const struct mode_range_items *mode_ranges_sub[] = {
585         [MODE_DC_V] = &mode_ranges_volts_sub,
586         [MODE_AC_V] = &mode_ranges_volts_sub,
587         [MODE_DC_A] = &mode_ranges_mamps_sub,
588         [MODE_AC_A] = &mode_ranges_mamps_sub,
589         [MODE_DC_MA] = &mode_ranges_mamps_sub,
590         [MODE_AC_MA] = &mode_ranges_mamps_sub,
591         [MODE_DC_UA] = &mode_ranges_uamps_sub,
592         [MODE_AC_UA] = &mode_ranges_uamps_sub,
593         [MODE_FREQ] = &mode_ranges_freq_sub,
594         [MODE_DIODE] = &mode_ranges_diode_sub,
595         [MODE_SUB_TEMPC] = &mode_ranges_temp_sub,
596         [MODE_SUB_TEMPF] = &mode_ranges_temp_sub,
597         [MODE_SUB_BATT] = &mode_ranges_batt_sub,
598         [MODE_SUB_DBM] = &mode_ranges_gain_sub,
599 };
600
601 static const struct mode_range_item *mode_range_get_scale(
602         enum eev121gw_display display,
603         enum mode_codes mode, enum range_codes range)
604 {
605         const struct mode_range_items *items;
606         const struct mode_range_item *item;
607
608         if (display == EEV121GW_DISPLAY_MAIN) {
609                 if (mode >= ARRAY_SIZE(mode_ranges_main))
610                         return NULL;
611                 items = mode_ranges_main[mode];
612                 if (!items || !items->range_count)
613                         return NULL;
614                 if (range >= items->range_count)
615                         return NULL;
616                 item = &items->ranges[range];
617                 return item;
618         }
619         if (display == EEV121GW_DISPLAY_SUB) {
620                 if (mode >= ARRAY_SIZE(mode_ranges_sub))
621                         return NULL;
622                 items = mode_ranges_sub[mode];
623                 if (!items || !items->range_count)
624                         return NULL;
625                 if (range >= items->range_count)
626                         return NULL;
627                 item = &items->ranges[range];
628                 if (!item->desc || !*item->desc)
629                         return NULL;
630                 return item;
631         }
632
633         return NULL;
634 }
635
636 SR_PRIV gboolean sr_eev121gw_packet_valid(const uint8_t *buf)
637 {
638         uint8_t csum;
639         size_t idx;
640
641         /* Leading byte, literal / fixed value. */
642         if (buf[OFF_START_CMD] != VAL_START_CMD)
643                 return FALSE;
644
645         /* Check some always-zero bits in reserved locations. */
646         if (FIELD_NB(buf[OFF_MAIN_MODE], MAIN_MODE_RSV_5))
647                 return FALSE;
648         if (FIELD_NB(buf[OFF_SUB_RANGE], SUB_RANGE_RSV_3))
649                 return FALSE;
650         if (FIELD_NL(buf[OFF_BAR_STATUS], BAR_STATUS_RSV_5))
651                 return FALSE;
652         if (FIELD_NL(buf[OFF_BAR_VALUE], BAR_VALUE_RSV_6))
653                 return FALSE;
654         /* See TODO for bit 5 of "bar value" not always being 0. */
655         if (0 && FIELD_NB(buf[OFF_BAR_VALUE], BAR_VALUE_RSV_5))
656                 return FALSE;
657         if (FIELD_NB(buf[OFF_ICON_STS_3], ICON_STS3_RSV_7))
658                 return FALSE;
659
660         /* Checksum, XOR over all previous bytes. */
661         csum = 0x00;
662         for (idx = OFF_START_CMD; idx < OFF_CHECKSUM; idx++)
663                 csum ^= buf[idx];
664         if (csum != buf[OFF_CHECKSUM]) {
665                 /* Non-critical condition, almost expected to see invalid data. */
666                 sr_spew("Packet csum: want %02x, got %02x.", csum, buf[OFF_CHECKSUM]);
667                 return FALSE;
668         }
669
670         sr_spew("Packet valid.");
671
672         return TRUE;
673 }
674
675 /**
676  * Parse a protocol packet.
677  *
678  * @param[in] buf Buffer containing the protocol packet. Must not be NULL.
679  * @param[out] floatval Pointer to a float variable. That variable will be
680  *             modified in-place depending on the protocol packet.
681  *             Must not be NULL.
682  * @param[out] analog Pointer to a struct sr_datafeed_analog. The struct will
683  *             be filled with data according to the protocol packet.
684  *             Must not be NULL.
685  * @param[out] info Pointer to a struct eevblog_121gw_info. The struct will be
686  *             filled with data according to the protocol packet.
687  *             Must not be NULL.
688  *
689  * @return SR_OK upon success, SR_ERR upon failure. Upon errors, the
690  *         'analog' variable contents are undefined and should not be used.
691  */
692 static int sr_eev121gw_parse(const uint8_t *buf, float *floatval,
693                 struct sr_datafeed_analog *analog, void *info)
694 {
695         struct eev121gw_info *info_local;
696         enum eev121gw_display display;
697         const char *channel_name;
698         uint32_t raw_serial;
699         uint8_t raw_main_mode, raw_main_range;
700         uint16_t raw_main_value;
701         uint8_t raw_sub_mode, raw_sub_range;
702         uint16_t raw_sub_value;
703         uint8_t raw_bar_status, raw_bar_value;
704         uint8_t raw_icon_stat_1, raw_icon_stat_2, raw_icon_stat_3;
705         uint32_t uint_value;
706         enum mode_codes main_mode;
707         enum range_codes main_range;
708         enum mode_codes sub_mode;
709         enum range_codes sub_range;
710         const struct mode_range_item *scale;
711         gboolean is_dc, is_sign, use_sign;
712         gboolean is_k;
713         unsigned int cont_code;
714
715         info_local = info;
716         display = info_local->ch_idx;
717         channel_name = eev121gw_channel_formats[display];
718         memset(info_local, 0, sizeof(*info_local));
719         *floatval = 0.0f;
720
721         /*
722          * Get the packet's bytes into native C language typed variables.
723          * This keeps byte position references out of logic/calculations.
724          * The start command and CRC were verified before we get here.
725          */
726         raw_serial = RB32(&buf[OFF_SERIAL_3]);
727         raw_main_mode = R8(&buf[OFF_MAIN_MODE]);
728         raw_main_range = R8(&buf[OFF_MAIN_RANGE]);
729         raw_main_value = RB16(&buf[OFF_MAIN_VAL_H]);
730         raw_sub_mode = R8(&buf[OFF_SUB_MODE]);
731         raw_sub_range = R8(&buf[OFF_SUB_RANGE]);
732         raw_sub_value = RB16(&buf[OFF_SUB_VAL_H]);
733         raw_bar_status = R8(&buf[OFF_BAR_STATUS]);
734         raw_bar_value = R8(&buf[OFF_BAR_VALUE]);
735         raw_icon_stat_1 = R8(&buf[OFF_ICON_STS_1]);
736         raw_icon_stat_2 = R8(&buf[OFF_ICON_STS_2]);
737         raw_icon_stat_3 = R8(&buf[OFF_ICON_STS_3]);
738
739         /*
740          * Packets contain a YEAR-MONTH date spec. It's uncertain how
741          * this data relates to the device's production or the firmware
742          * version. It certainly is not the current date either. Only
743          * optionally log this information, it's consistent across all
744          * packets (won't change within a session), and will be noisy if
745          * always enabled.
746          *
747          * Packets also contain a user adjustable device identification
748          * number (see the SETUP options). This is motivated by support
749          * for multiple devices, but won't change here within a session.
750          * The user chose to communicate to one specific device when the
751          * session started, by means of the conn= spec.
752          *
753          * It was suggested that this 'serial' field might be used as an
754          * additional means to check for a packet's validity (or absence
755          * of communication errors). This remains as an option for future
756          * improvement.
757          */
758         if (0) {
759                 unsigned int ser_year, ser_mon, ser_nr;
760
761                 ser_year = FIELD_NL(raw_serial, SERIAL_YEAR);
762                 ser_mon = FIELD_NL(raw_serial, SERIAL_MONTH);
763                 ser_nr = FIELD_NL(raw_serial, SERIAL_NUMBER);
764                 sr_spew("Packet: Y-M %x-%x, nr %x.", ser_year, ser_mon, ser_nr);
765         }
766
767         switch (display) {
768
769         case EEV121GW_DISPLAY_MAIN:
770                 /*
771                  * Get those fields which correspond to the main display.
772                  * The value's mantissa has 18 bits. The sign is separate
773                  * (and is not universally applicable, mode needs to get
774                  * inspected). The range's scaling and precision also
775                  * depend on the mode.
776                  */
777                 main_mode = FIELD_NL(raw_main_mode, MAIN_MODE_MODE);
778                 main_range = FIELD_NL(raw_main_range, MAIN_RANGE_RANGE);
779                 scale = mode_range_get_scale(EEV121GW_DISPLAY_MAIN,
780                         main_mode, main_range);
781                 if (!scale)
782                         return SR_ERR_NA;
783                 info_local->factor = scale->factor;
784                 info_local->digits = scale->digits;
785
786                 uint_value = raw_main_value;
787                 uint_value |= FIELD_NL(raw_main_mode, MAIN_MODE_VAL_U) << 16;
788                 info_local->uint_value = uint_value;
789                 info_local->is_ofl = FIELD_NB(raw_main_range, MAIN_RANGE_OFL);
790
791                 switch (main_mode) {
792                 case MODE_LOW_Z:
793                         is_dc = FALSE;
794                         if (FIELD_NB(raw_icon_stat_3, ICON_STS3_DC))
795                                 is_dc = TRUE;
796                         if (FIELD_NB(raw_icon_stat_3, ICON_STS3_AC))
797                                 is_dc = FALSE;
798                         use_sign = is_dc;
799                         break;
800                 case MODE_DC_V:
801                 case MODE_DC_MV:
802                 case MODE_TEMP:
803                 case MODE_DC_UVA:
804                 case MODE_DC_MVA:
805                 case MODE_DC_VA:
806                 case MODE_DC_UA:
807                 case MODE_DC_MA:
808                 case MODE_DC_A:
809                         use_sign = TRUE;
810                         break;
811                 default:
812                         use_sign = FALSE;
813                         break;
814                 }
815                 if (use_sign) {
816                         is_sign = FIELD_NB(raw_main_range, MAIN_RANGE_SIGN);
817                         info_local->is_neg = is_sign;
818                 }
819
820                 switch (main_mode) {
821                 case MODE_LOW_Z:
822                         info_local->is_voltage = TRUE;
823                         /* TODO: Need to determine AC/DC here? */
824                         info_local->is_volt = TRUE;
825                         info_local->is_low_pass = TRUE;
826                         break;
827                 case MODE_DC_V:
828                         info_local->is_voltage = TRUE;
829                         info_local->is_dc = TRUE;
830                         info_local->is_volt = TRUE;
831                         break;
832                 case MODE_AC_V:
833                         info_local->is_voltage = TRUE;
834                         info_local->is_volt = TRUE;
835                         info_local->is_ac = TRUE;
836                         break;
837                 case MODE_DC_MV:
838                         info_local->is_voltage = TRUE;
839                         info_local->is_dc = TRUE;
840                         info_local->is_volt = TRUE;
841                         break;
842                 case MODE_AC_MV:
843                         info_local->is_voltage = TRUE;
844                         info_local->is_volt = TRUE;
845                         info_local->is_ac = TRUE;
846                         break;
847                 case MODE_TEMP:
848                         info_local->is_temperature = TRUE;
849                         if (FIELD_NB(raw_main_range, MAIN_RANGE_DEGC))
850                                 info_local->is_celsius = TRUE;
851                         if (FIELD_NB(raw_main_range, MAIN_RANGE_DEGF))
852                                 info_local->is_fahrenheit = TRUE;
853                         break;
854                 case MODE_FREQ:
855                         info_local->is_frequency = TRUE;
856                         info_local->is_hertz = TRUE;
857                         break;
858                 case MODE_PERIOD:
859                         info_local->is_period = TRUE;
860                         info_local->is_seconds = TRUE;
861                         break;
862                 case MODE_DUTY:
863                         info_local->is_duty_cycle = TRUE;
864                         info_local->is_percent = TRUE;
865                         break;
866                 case MODE_RES:
867                         info_local->is_resistance = TRUE;
868                         info_local->is_ohm = TRUE;
869                         break;
870                 case MODE_CONT:
871                         info_local->is_continuity = TRUE;
872                         info_local->is_ohm = TRUE;
873                         /*
874                          * In continuity mode the packet provides the
875                          * resistance in ohms (500R range), but seems to
876                          * _not_ carry the "boolean" open/closed state
877                          * which controls the beeper. Users can select
878                          * whether to trigger at 30R or 300R, and whether
879                          * to trigger on values below (continuity) or
880                          * above (cable break) the limit, but we cannot
881                          * tell what the currently used setting is. So
882                          * we neither get the beeper's state, nor can we
883                          * derive it from other information.
884                          */
885                         break;
886                 case MODE_DIODE:
887                         info_local->is_diode = TRUE;
888                         info_local->is_dc = TRUE;
889                         info_local->is_volt = TRUE;
890                         break;
891                 case MODE_CAP:
892                         info_local->is_capacitance = TRUE;
893                         info_local->is_farad = TRUE;
894                         break;
895                 case MODE_AC_UVA:
896                         info_local->is_power = TRUE;
897                         info_local->is_ac = TRUE;
898                         info_local->is_volt_ampere = TRUE;
899                         break;
900                 case MODE_AC_MVA:
901                         info_local->is_power = TRUE;
902                         info_local->is_ac = TRUE;
903                         info_local->is_volt_ampere = TRUE;
904                         break;
905                 case MODE_AC_VA:
906                         info_local->is_power = TRUE;
907                         info_local->is_ac = TRUE;
908                         info_local->is_volt_ampere = TRUE;
909                         break;
910                 case MODE_AC_UA:
911                         info_local->is_current = TRUE;
912                         info_local->is_ac = TRUE;
913                         info_local->is_ampere = TRUE;
914                         break;
915                 case MODE_DC_UA:
916                         info_local->is_current = TRUE;
917                         info_local->is_dc = TRUE;
918                         info_local->is_ampere = TRUE;
919                         break;
920                 case MODE_AC_MA:
921                         info_local->is_current = TRUE;
922                         info_local->is_ac = TRUE;
923                         info_local->is_ampere = TRUE;
924                         break;
925                 case MODE_DC_MA:
926                         info_local->is_current = TRUE;
927                         info_local->is_dc = TRUE;
928                         info_local->is_ampere = TRUE;
929                         break;
930                 case MODE_AC_A:
931                         info_local->is_current = TRUE;
932                         info_local->is_ac = TRUE;
933                         info_local->is_ampere = TRUE;
934                         break;
935                 case MODE_DC_A:
936                         info_local->is_current = TRUE;
937                         info_local->is_dc = TRUE;
938                         info_local->is_ampere = TRUE;
939                         break;
940                 case MODE_DC_UVA:
941                         info_local->is_power = TRUE;
942                         info_local->is_dc = TRUE;
943                         info_local->is_volt_ampere = TRUE;
944                         break;
945                 case MODE_DC_MVA:
946                         info_local->is_power = TRUE;
947                         info_local->is_dc = TRUE;
948                         info_local->is_volt_ampere = TRUE;
949                         break;
950                 case MODE_DC_VA:
951                         info_local->is_power = TRUE;
952                         info_local->is_dc = TRUE;
953                         info_local->is_volt_ampere = TRUE;
954                         break;
955                 /* Modes 100-199 only apply to the secondary display. */
956                 default:
957                         return SR_ERR_NA;
958                 }
959
960                 /*
961                  * Inspect the "icons" section, since it is associated
962                  * with the primary display and global device state.
963                  */
964                 if (FIELD_NB(raw_icon_stat_1, ICON_STS1_1KHZ))
965                         info_local->is_low_pass = TRUE;
966                 if (FIELD_NB(raw_icon_stat_1, ICON_STS1_1MSPK))
967                         info_local->is_1ms_peak = TRUE;
968                 switch (FIELD_NL(raw_icon_stat_1, ICON_STS1_DCAC)) {
969                 case ACDC_ACDC:
970                         info_local->is_ac = TRUE;
971                         info_local->is_dc = TRUE;
972                         break;
973                 case ACDC_AC:
974                         info_local->is_ac = TRUE;
975                         break;
976                 case ACDC_DC:
977                         info_local->is_dc = TRUE;
978                         break;
979                 case ACDC_NONE:
980                         /* EMPTY */
981                         break;
982                 }
983                 if (FIELD_NB(raw_icon_stat_1, ICON_STS1_AUTO))
984                         info_local->is_auto_range = TRUE;
985                 if (FIELD_NB(raw_icon_stat_1, ICON_STS1_APO))
986                         info_local->is_auto_poweroff = TRUE;
987                 if (FIELD_NB(raw_icon_stat_1, ICON_STS1_BAT))
988                         info_local->is_low_batt = TRUE;
989                 if (FIELD_NB(raw_icon_stat_2, ICON_STS2_BT))
990                         info_local->is_bt = TRUE;
991                 /* TODO: Is this the "20mA loop current" flag? */
992                 if (FIELD_NB(raw_icon_stat_2, ICON_STS2_UNK))
993                         info_local->is_loop_current = TRUE;
994                 if (FIELD_NB(raw_icon_stat_2, ICON_STS2_REL))
995                         info_local->is_rel = TRUE;
996                 /* dBm only applies to secondary display, not main. */
997                 switch (FIELD_NL(raw_icon_stat_2, ICON_STS2_MINMAX)) {
998                 /* TODO: Do inspect the min/max/avg flags. */
999                 default:
1000                         /* EMPTY */
1001                         break;
1002                 }
1003                 if (FIELD_NB(raw_icon_stat_3, ICON_STS3_TEST))
1004                         info_local->is_test = TRUE;
1005                 /* TODO: How to interpret the 2-bit MEM field? */
1006                 if (FIELD_NL(raw_icon_stat_3, ICON_STS3_MEM))
1007                         info_local->is_mem = TRUE;
1008                 if (FIELD_NL(raw_icon_stat_3, ICON_STS3_AHOLD))
1009                         info_local->is_hold = TRUE;
1010                 /* TODO: Are these for the secondary display? See status-2 ACDC. */
1011                 if (FIELD_NB(raw_icon_stat_3, ICON_STS3_AC))
1012                         info_local->is_ac = TRUE;
1013                 if (FIELD_NB(raw_icon_stat_3, ICON_STS3_DC))
1014                         info_local->is_dc = TRUE;
1015
1016                 sr_spew("Disp '%s', value: %lu (ov %d, neg %d), mode %d, range %d.",
1017                         channel_name,
1018                         (unsigned long)info_local->uint_value,
1019                         info_local->is_ofl, info_local->is_neg,
1020                         (int)main_mode, (int)main_range);
1021                 /* Advance to the number and units conversion below. */
1022                 break;
1023
1024         case EEV121GW_DISPLAY_SUB:
1025                 /*
1026                  * Get those fields which correspond to the secondary
1027                  * display. The value's mantissa has 16 bits. The sign
1028                  * is separate and only applies to some of the modes.
1029                  * Scaling and precision also depend on the mode. The
1030                  * interpretation of the secondary display is different
1031                  * from the main display: The 'range' is not an index
1032                  * into ranges, instead it's the decimal's position.
1033                  * Yet more scaling depends on the mode, to complicate
1034                  * matters. The secondary display uses modes 100-199,
1035                  * and some of the 0-24 modes as well.
1036                  */
1037                 sub_mode = FIELD_NL(raw_sub_mode, SUB_MODE_MODE);
1038                 sub_range = FIELD_NL(raw_sub_range, SUB_RANGE_POINT);
1039                 scale = mode_range_get_scale(EEV121GW_DISPLAY_SUB,
1040                         sub_mode, sub_range);
1041                 if (!scale)
1042                         return SR_ERR_NA;
1043                 info_local->factor = scale->factor;
1044                 info_local->digits = scale->digits;
1045
1046                 info_local->uint_value = raw_sub_value;
1047                 info_local->is_ofl = FIELD_NB(raw_sub_range, SUB_RANGE_OFL);
1048
1049                 switch (sub_mode) {
1050                 case MODE_DC_V:
1051                 case MODE_AC_V:
1052                 case MODE_DC_A:
1053                 case MODE_AC_A:
1054                 case MODE_SUB_TEMPC:
1055                 case MODE_SUB_TEMPF:
1056                 case MODE_SUB_B_VOLT:
1057                 case MODE_SUB_DBM:
1058                         use_sign = TRUE;
1059                         break;
1060                 default:
1061                         use_sign = FALSE;
1062                         break;
1063                 }
1064                 if (use_sign) {
1065                         is_sign = FIELD_NB(raw_sub_range, SUB_RANGE_SIGN);
1066                         info_local->is_neg = is_sign;
1067                 }
1068                 is_k = FIELD_NB(raw_sub_range, SUB_RANGE_K);
1069
1070                 switch (sub_mode) {
1071                 case MODE_DC_V:
1072                         info_local->is_voltage = TRUE;
1073                         info_local->is_volt = TRUE;
1074                         break;
1075                 case MODE_DC_A:
1076                         info_local->is_current = TRUE;
1077                         info_local->is_ampere = TRUE;
1078                         break;
1079                 case MODE_FREQ:
1080                         info_local->is_frequency = TRUE;
1081                         info_local->is_hertz = TRUE;
1082                         if (is_k) {
1083                                 info_local->factor -= 3;
1084                                 info_local->digits -= 3;
1085                         }
1086                         info_local->is_ofl = FALSE;
1087                         break;
1088                 case MODE_SUB_TEMPC:
1089                         info_local->is_temperature = TRUE;
1090                         info_local->is_celsius = TRUE;
1091                         break;
1092                 case MODE_SUB_TEMPF:
1093                         info_local->is_temperature = TRUE;
1094                         info_local->is_fahrenheit = TRUE;
1095                         break;
1096                 case MODE_SUB_BATT:
1097                         /* TODO: How to communicate it's the *battery* voltage? */
1098                         info_local->is_voltage = TRUE;
1099                         info_local->is_volt = TRUE;
1100                         break;
1101                 case MODE_SUB_DBM:
1102                         info_local->is_gain = TRUE;
1103                         info_local->is_dbm = TRUE;
1104                         break;
1105                 case MODE_SUB_CONT_PARM_0:
1106                 case MODE_SUB_CONT_PARM_1:
1107                 case MODE_SUB_CONT_PARM_2:
1108                 case MODE_SUB_CONT_PARM_3:
1109                         /*
1110                          * These "continuity parameters" are special. The
1111                          * least significant bits represent the options:
1112                          *
1113                          * 0xaa = 170 => down 30
1114                          * 0xab = 171 => up 30
1115                          * 0xac = 172 => down 300
1116                          * 0xad = 173 => up 300
1117                          *
1118                          * bit 0 value 0 -> close (cont)
1119                          * bit 0 value 1 -> open (break)
1120                          * bit 1 value 0 -> 30R limit
1121                          * bit 1 value 1 -> 300R limit
1122                          *
1123                          * This "display value" is only seen during setup
1124                          * but not during regular operation of continuity
1125                          * mode. :( In theory we could somehow pass the
1126                          * 30/300 ohm limit to sigrok, but that'd be of
1127                          * somewhat limited use.
1128                          */
1129                         cont_code = sub_mode - MODE_SUB_CONT_PARM_0;
1130                         info_local->is_resistance = TRUE;
1131                         info_local->is_ohm = TRUE;
1132                         info_local->uint_value = (cont_code & 0x02) ? 300 : 30;
1133                         info_local->is_neg = FALSE;
1134                         info_local->is_ofl = FALSE;
1135                         info_local->factor = 0;
1136                         info_local->digits = 0;
1137                         break;
1138                 case MODE_DIODE:
1139                         /* Displays configured diode test voltage. */
1140                         info_local->is_voltage = TRUE;
1141                         info_local->is_volt = TRUE;
1142                         break;
1143
1144                 /* Reflecting these to users seems pointless, ignore them. */
1145                 case MODE_SUB_APO_ON:
1146                 case MODE_SUB_APO_OFF:
1147                 case MODE_SUB_LCD:
1148                 case MODE_SUB_YEAR:
1149                 case MODE_SUB_DATE:
1150                 case MODE_SUB_TIME:
1151                         return SR_ERR_NA;
1152
1153                 /* Unknown / unsupported sub display mode. */
1154                 default:
1155                         return SR_ERR_NA;
1156                 }
1157
1158                 sr_spew("disp '%s', value: %lu (ov %d, neg %d), mode %d, range %d",
1159                         channel_name,
1160                         (unsigned long)info_local->uint_value,
1161                         info_local->is_ofl, info_local->is_neg,
1162                         (int)sub_mode, (int)sub_range);
1163                 /* Advance to the number and units conversion below. */
1164                 break;
1165
1166         case EEV121GW_DISPLAY_BAR:
1167                 /*
1168                  * Get those fields which correspond to the bargraph.
1169                  * There are 26 segments (ticks 0-25), several ranges
1170                  * apply (up to 5, or up to 10, several decades). The
1171                  * bargraph does not apply to all modes and ranges,
1172                  * hence there is a "use" flag (negative logic, blank
1173                  * signal). Bit 5 was also found to have undocumented
1174                  * values, we refuse to use the bargraph value then.
1175                  */
1176                 if (FIELD_NB(raw_bar_status, BAR_STATUS_USE))
1177                         return SR_ERR_NA;
1178                 if (FIELD_NB(raw_bar_value, BAR_VALUE_RSV_5))
1179                         return SR_ERR_NA;
1180                 uint_value = FIELD_NL(raw_bar_value, BAR_VALUE_VALUE);
1181                 if (uint_value > BAR_VALUE_MAX)
1182                         uint_value = BAR_VALUE_MAX;
1183                 info_local->is_neg = FIELD_NB(raw_bar_status, BAR_STATUS_SIGN);
1184                 switch (FIELD_NL(raw_bar_status, BAR_STATUS_1K_500)) {
1185                 case BAR_RANGE_5:
1186                         /* Full range 5.0, in steps of 0.2 each. */
1187                         uint_value *= 5000 / BAR_VALUE_MAX;
1188                         info_local->factor = 3;
1189                         info_local->digits = 1;
1190                         break;
1191                 case BAR_RANGE_50:
1192                         /* Full range 50, in steps of 2 each. */
1193                         uint_value *= 50 / BAR_VALUE_MAX;
1194                         info_local->factor = 0;
1195                         info_local->digits = 0;
1196                         break;
1197                 case BAR_RANGE_500:
1198                         /* Full range 500, in steps of 20 each. */
1199                         uint_value *= 500 / BAR_VALUE_MAX;
1200                         info_local->factor = 0;
1201                         info_local->digits = -1;
1202                         break;
1203                 case BAR_RANGE_1000:
1204                         /* Full range 1000, in steps of 40 each. */
1205                         uint_value *= 1000 / BAR_VALUE_MAX;
1206                         info_local->factor = 0;
1207                         info_local->digits = -1;
1208                         break;
1209                 default:
1210                         return SR_ERR_NA;
1211                 }
1212                 info_local->uint_value = uint_value;
1213                 info_local->is_unitless = TRUE;
1214                 sr_spew("Disp '%s', value: %u.", channel_name,
1215                         (unsigned int)info_local->uint_value);
1216                 /* Advance to the number and units conversion below. */
1217                 break;
1218
1219         default:
1220                 /* Unknown display, programmer's error, ShouldNotHappen(TM). */
1221                 sr_err("Disp '-?-'.");
1222                 return SR_ERR_ARG;
1223         }
1224
1225         /*
1226          * Convert the unsigned mantissa and its modifiers to a float
1227          * analog value, including scale and quantity. Do the conversion
1228          * first, and optionally override the result with 'inf' later.
1229          * Apply the sign last so that +inf and -inf are supported.
1230          */
1231         *floatval = info_local->uint_value;
1232         if (info_local->factor)
1233                 *floatval *= powf(10, -info_local->factor);
1234         if (info_local->is_ofl)
1235                 *floatval = INFINITY;
1236         if (info_local->is_neg)
1237                 *floatval = -*floatval;
1238
1239         analog->encoding->digits = info_local->digits;
1240         analog->spec->spec_digits = info_local->digits;
1241
1242         /*
1243          * Communicate the measured quantity.
1244          */
1245         /* Determine the quantity itself. */
1246         if (info_local->is_voltage)
1247                 analog->meaning->mq = SR_MQ_VOLTAGE;
1248         if (info_local->is_current)
1249                 analog->meaning->mq = SR_MQ_CURRENT;
1250         if (info_local->is_power)
1251                 analog->meaning->mq = SR_MQ_POWER;
1252         if (info_local->is_gain)
1253                 analog->meaning->mq = SR_MQ_GAIN;
1254         if (info_local->is_resistance)
1255                 analog->meaning->mq = SR_MQ_RESISTANCE;
1256         if (info_local->is_capacitance)
1257                 analog->meaning->mq = SR_MQ_CAPACITANCE;
1258         if (info_local->is_diode)
1259                 analog->meaning->mq = SR_MQ_VOLTAGE;
1260         if (info_local->is_temperature)
1261                 analog->meaning->mq = SR_MQ_TEMPERATURE;
1262         if (info_local->is_continuity)
1263                 analog->meaning->mq = SR_MQ_CONTINUITY;
1264         if (info_local->is_frequency)
1265                 analog->meaning->mq = SR_MQ_FREQUENCY;
1266         if (info_local->is_period)
1267                 analog->meaning->mq = SR_MQ_TIME;
1268         if (info_local->is_duty_cycle)
1269                 analog->meaning->mq = SR_MQ_DUTY_CYCLE;
1270         if (info_local->is_unitless)
1271                 analog->meaning->mq = SR_MQ_COUNT;
1272         /* Add AC / DC / DC+AC flags. */
1273         if (info_local->is_ac)
1274                 analog->meaning->mqflags |= SR_MQFLAG_AC;
1275         if (info_local->is_dc)
1276                 analog->meaning->mqflags |= SR_MQFLAG_DC;
1277         /* Specify units. */
1278         if (info_local->is_ampere)
1279                 analog->meaning->unit = SR_UNIT_AMPERE;
1280         if (info_local->is_volt)
1281                 analog->meaning->unit = SR_UNIT_VOLT;
1282         if (info_local->is_volt_ampere)
1283                 analog->meaning->unit = SR_UNIT_VOLT_AMPERE;
1284         if (info_local->is_dbm)
1285                 analog->meaning->unit = SR_UNIT_DECIBEL_VOLT;
1286         if (info_local->is_ohm)
1287                 analog->meaning->unit = SR_UNIT_OHM;
1288         if (info_local->is_farad)
1289                 analog->meaning->unit = SR_UNIT_FARAD;
1290         if (info_local->is_celsius)
1291                 analog->meaning->unit = SR_UNIT_CELSIUS;
1292         if (info_local->is_fahrenheit)
1293                 analog->meaning->unit = SR_UNIT_FAHRENHEIT;
1294         if (info_local->is_hertz)
1295                 analog->meaning->unit = SR_UNIT_HERTZ;
1296         if (info_local->is_seconds)
1297                 analog->meaning->unit = SR_UNIT_SECOND;
1298         if (info_local->is_percent)
1299                 analog->meaning->unit = SR_UNIT_PERCENTAGE;
1300         if (info_local->is_loop_current)
1301                 analog->meaning->unit = SR_UNIT_PERCENTAGE;
1302         if (info_local->is_unitless)
1303                 analog->meaning->unit = SR_UNIT_UNITLESS;
1304         if (info_local->is_logic)
1305                 analog->meaning->unit = SR_UNIT_UNITLESS;
1306         /* Add other indicator flags. */
1307         if (info_local->is_diode) {
1308                 analog->meaning->mqflags |= SR_MQFLAG_DIODE;
1309                 analog->meaning->mqflags |= SR_MQFLAG_DC;
1310         }
1311         if (info_local->is_min)
1312                 analog->meaning->mqflags |= SR_MQFLAG_MIN;
1313         if (info_local->is_max)
1314                 analog->meaning->mqflags |= SR_MQFLAG_MAX;
1315         if (info_local->is_avg)
1316                 analog->meaning->mqflags |= SR_MQFLAG_AVG;
1317         /* TODO: How to communicate info_local->is_1ms_peak? */
1318         if (info_local->is_rel)
1319                 analog->meaning->mqflags |= SR_MQFLAG_RELATIVE;
1320         if (info_local->is_hold)
1321                 analog->meaning->mqflags |= SR_MQFLAG_HOLD;
1322         /* TODO: How to communicate info_local->is_low_pass? */
1323         if (info_local->is_mem) /* XXX Is REF appropriate here? */
1324                 analog->meaning->mqflags |= SR_MQFLAG_REFERENCE;
1325         if (info_local->is_auto_range)
1326                 analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
1327         /* TODO: How to communicate info->is_test? What's its meaning at all? */
1328         /* TODO: How to communicate info->is_auto_poweroff? */
1329         /* TODO: How to communicate info->is_low_batt? */
1330
1331         return SR_OK;
1332 }
1333
1334 /*
1335  * Parse the same packet multiple times, to extract individual analog
1336  * values which correspond to several displays of the device. Make sure
1337  * to keep the channel index in place, even if the parse routine will
1338  * clear the info structure.
1339  */
1340 SR_PRIV int sr_eev121gw_3displays_parse(const uint8_t *buf, float *floatval,
1341                 struct sr_datafeed_analog *analog, void *info)
1342 {
1343         struct eev121gw_info *info_local;
1344         size_t ch_idx;
1345         int rc;
1346
1347         info_local = info;
1348         ch_idx = info_local->ch_idx;
1349         rc = sr_eev121gw_parse(buf, floatval, analog, info);
1350         info_local->ch_idx = ch_idx + 1;
1351
1352         return rc;
1353 }