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