]> sigrok.org Git - libsigrok.git/blame - src/hardware/scpi-dmm/protocol.c
scpi-dmm: rephrase read timeout decls, put "unit" after "ms value"
[libsigrok.git] / src / hardware / scpi-dmm / protocol.c
CommitLineData
7a396ff5
GS
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 3 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#include <config.h>
3cdad416
GS
21#include <math.h>
22#include <string.h>
7a396ff5
GS
23#include "protocol.h"
24
3cdad416
GS
25#define WITH_CMD_DELAY 0 /* TODO See which devices need delays. */
26
27SR_PRIV void scpi_dmm_cmd_delay(struct sr_scpi_dev_inst *scpi)
28{
29 if (WITH_CMD_DELAY)
30 g_usleep(WITH_CMD_DELAY * 1000);
ddeaa49d
PA
31
32 if (!scpi->no_opc_command)
33 sr_scpi_get_opc(scpi);
3cdad416
GS
34}
35
36SR_PRIV const struct mqopt_item *scpi_dmm_lookup_mq_number(
37 const struct sr_dev_inst *sdi, enum sr_mq mq, enum sr_mqflag flag)
38{
39 struct dev_context *devc;
40 size_t i;
41 const struct mqopt_item *item;
42
43 devc = sdi->priv;
44 for (i = 0; i < devc->model->mqopt_size; i++) {
45 item = &devc->model->mqopts[i];
46 if (item->mq != mq || item->mqflag != flag)
47 continue;
48 return item;
49 }
50
51 return NULL;
52}
53
54SR_PRIV const struct mqopt_item *scpi_dmm_lookup_mq_text(
55 const struct sr_dev_inst *sdi, const char *text)
56{
57 struct dev_context *devc;
58 size_t i;
59 const struct mqopt_item *item;
60
61 devc = sdi->priv;
62 for (i = 0; i < devc->model->mqopt_size; i++) {
63 item = &devc->model->mqopts[i];
64 if (!item->scpi_func_query || !item->scpi_func_query[0])
65 continue;
66 if (!g_str_has_prefix(text, item->scpi_func_query))
67 continue;
68 return item;
69 }
70
71 return NULL;
72}
73
74SR_PRIV int scpi_dmm_get_mq(const struct sr_dev_inst *sdi,
08f3b427
GS
75 enum sr_mq *mq, enum sr_mqflag *flag, char **rsp,
76 const struct mqopt_item **mqitem)
3cdad416
GS
77{
78 struct dev_context *devc;
79 const char *command;
80 char *response;
81 const char *have;
82 int ret;
83 const struct mqopt_item *item;
84
85 devc = sdi->priv;
86 if (mq)
87 *mq = 0;
88 if (flag)
89 *flag = 0;
90 if (rsp)
91 *rsp = NULL;
08f3b427
GS
92 if (mqitem)
93 *mqitem = NULL;
3cdad416 94
28877994 95 scpi_dmm_cmd_delay(sdi->conn);
3cdad416
GS
96 command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_FUNC);
97 if (!command || !*command)
98 return SR_ERR_NA;
99 response = NULL;
100 ret = sr_scpi_get_string(sdi->conn, command, &response);
3cdad416
GS
101 if (ret != SR_OK)
102 return ret;
83d38ed9
GS
103 if (!response || !*response) {
104 g_free(response);
3cdad416 105 return SR_ERR_NA;
83d38ed9 106 }
3cdad416
GS
107 have = response;
108 if (*have == '"')
109 have++;
110
111 ret = SR_ERR_NA;
112 item = scpi_dmm_lookup_mq_text(sdi, have);
113 if (item) {
114 if (mq)
115 *mq = item->mq;
116 if (flag)
117 *flag = item->mqflag;
08f3b427
GS
118 if (mqitem)
119 *mqitem = item;
3cdad416 120 ret = SR_OK;
2111d157
PA
121 } else {
122 sr_warn("Unknown measurement quantity: %s", have);
3cdad416
GS
123 }
124
125 if (rsp) {
126 *rsp = response;
127 response = NULL;
128 }
129 g_free(response);
130
131 return ret;
132}
133
134SR_PRIV int scpi_dmm_set_mq(const struct sr_dev_inst *sdi,
135 enum sr_mq mq, enum sr_mqflag flag)
136{
137 struct dev_context *devc;
138 const struct mqopt_item *item;
139 const char *mode, *command;
140 int ret;
141
142 devc = sdi->priv;
143 item = scpi_dmm_lookup_mq_number(sdi, mq, flag);
144 if (!item)
145 return SR_ERR_NA;
146
147 mode = item->scpi_func_setup;
148 command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_SETUP_FUNC);
3cdad416 149 scpi_dmm_cmd_delay(sdi->conn);
28877994
GS
150 ret = sr_scpi_send(sdi->conn, command, mode);
151 if (ret != SR_OK)
152 return ret;
3cdad416 153
28877994 154 return SR_OK;
3cdad416
GS
155}
156
a0418c20
GS
157SR_PRIV const char *scpi_dmm_get_range_text(const struct sr_dev_inst *sdi)
158{
159 struct dev_context *devc;
160 int ret;
161 const struct mqopt_item *mqitem;
162 gboolean is_auto;
163 char *response, *pos;
164 double range;
165 int digits;
166
167 devc = sdi->priv;
168
169 ret = scpi_dmm_get_mq(sdi, NULL, NULL, NULL, &mqitem);
170 if (ret != SR_OK)
171 return NULL;
172 if (!mqitem || !mqitem->scpi_func_setup)
173 return NULL;
5bf642db
GS
174 if (mqitem->drv_flags & FLAG_NO_RANGE)
175 return NULL;
a0418c20
GS
176
177 scpi_dmm_cmd_delay(sdi->conn);
178 ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
179 DMM_CMD_QUERY_RANGE_AUTO, mqitem->scpi_func_setup);
180 if (ret != SR_OK)
181 return NULL;
182 ret = sr_scpi_get_bool(sdi->conn, NULL, &is_auto);
183 if (ret != SR_OK)
184 return NULL;
185 if (is_auto)
186 return "auto";
187
188 /*
189 * Get the response into a text buffer. The range value may be
190 * followed by a precision value separated by comma. Common text
191 * to number conversion support code may assume that the input
192 * text spans to the end of the text, need not accept trailing
193 * text which is not part of a number.
194 */
195 scpi_dmm_cmd_delay(sdi->conn);
196 ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
197 DMM_CMD_QUERY_RANGE, mqitem->scpi_func_setup);
198 if (ret != SR_OK)
199 return NULL;
200 response = NULL;
201 ret = sr_scpi_get_string(sdi->conn, NULL, &response);
202 if (ret != SR_OK) {
203 g_free(response);
204 return NULL;
205 }
206 pos = strchr(response, ',');
207 if (pos)
208 *pos = '\0';
209 ret = sr_atod_ascii_digits(response, &range, &digits);
210 g_free(response);
211 if (ret != SR_OK)
212 return NULL;
213 snprintf(devc->range_text, sizeof(devc->range_text), "%lf", range);
214 return devc->range_text;
215}
216
217SR_PRIV int scpi_dmm_set_range_from_text(const struct sr_dev_inst *sdi,
218 const char *range)
219{
220 struct dev_context *devc;
221 int ret;
222 const struct mqopt_item *item;
223 gboolean is_auto;
224
225 devc = sdi->priv;
226
227 if (!range || !*range)
228 return SR_ERR_ARG;
229
230 ret = scpi_dmm_get_mq(sdi, NULL, NULL, NULL, &item);
231 if (ret != SR_OK)
232 return ret;
233 if (!item || !item->scpi_func_setup)
234 return SR_ERR_ARG;
5bf642db
GS
235 if (item->drv_flags & FLAG_NO_RANGE)
236 return SR_ERR_NA;
a0418c20
GS
237
238 is_auto = g_ascii_strcasecmp(range, "auto") == 0;
239 scpi_dmm_cmd_delay(sdi->conn);
240 ret = sr_scpi_cmd(sdi, devc->cmdset, 0, NULL,
241 is_auto ? DMM_CMD_SETUP_RANGE_AUTO : DMM_CMD_SETUP_RANGE,
242 item->scpi_func_setup, is_auto ? "" : range);
243 if (ret != SR_OK)
244 return ret;
245
246 return SR_OK;
247}
248
249SR_PRIV GVariant *scpi_dmm_get_range_text_list(const struct sr_dev_inst *sdi)
250{
251 GVariantBuilder gvb;
252 GVariant *list;
253
254 (void)sdi;
255
256 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
257 /* TODO
258 * Add more items _when_ the connected device supports a fixed
259 * or known set of ranges. The Agilent protocol is flexible and
260 * tolerant, set requests accept any value, and the device will
261 * use an upper limit which is at least the specified value.
262 * The values are communicated as mere numbers without units.
263 */
264 list = g_variant_builder_end(&gvb);
265
266 return list;
267}
268
3cdad416
GS
269SR_PRIV int scpi_dmm_get_meas_agilent(const struct sr_dev_inst *sdi, size_t ch)
270{
271 struct sr_scpi_dev_inst *scpi;
272 struct dev_context *devc;
273 struct scpi_dmm_acq_info *info;
274 struct sr_datafeed_analog *analog;
275 int ret;
276 enum sr_mq mq;
277 enum sr_mqflag mqflag;
278 char *mode_response;
279 const char *p;
280 char **fields;
281 size_t count;
282 char prec_text[20];
283 const struct mqopt_item *item;
284 int prec_exp;
285 const char *command;
286 char *response;
287 gboolean use_double;
288 int sig_digits, val_exp;
289 int digits;
290 enum sr_unit unit;
395c1850 291 double limit;
3cdad416
GS
292
293 scpi = sdi->conn;
294 devc = sdi->priv;
295 info = &devc->run_acq_info;
296 analog = &info->analog[ch];
297
298 /*
299 * Get the meter's current mode, keep the response around.
300 * Skip the measurement if the mode is uncertain.
301 */
08f3b427 302 ret = scpi_dmm_get_mq(sdi, &mq, &mqflag, &mode_response, &item);
3cdad416
GS
303 if (ret != SR_OK) {
304 g_free(mode_response);
305 return ret;
306 }
307 if (!mode_response)
308 return SR_ERR;
309 if (!mq) {
310 g_free(mode_response);
311 return +1;
312 }
313
314 /*
315 * Get the last comma separated field of the function query
316 * response, or fallback to the model's default precision for
317 * the current function. This copes with either of these cases:
318 * VOLT +1.00000E-01,+1.00000E-06
319 * DIOD
320 * TEMP THER,5000,+1.00000E+00,+1.00000E-01
321 */
322 p = sr_scpi_unquote_string(mode_response);
323 fields = g_strsplit(p, ",", 0);
324 count = g_strv_length(fields);
325 if (count >= 2) {
326 snprintf(prec_text, sizeof(prec_text),
327 "%s", fields[count - 1]);
328 p = prec_text;
08f3b427
GS
329 } else if (!item) {
330 p = NULL;
331 } else if (item->default_precision == NO_DFLT_PREC) {
332 p = NULL;
3cdad416 333 } else {
08f3b427
GS
334 snprintf(prec_text, sizeof(prec_text),
335 "1e%d", item->default_precision);
336 p = prec_text;
3cdad416
GS
337 }
338 g_strfreev(fields);
339
340 /*
341 * Need to extract the exponent value ourselves, since a strtod()
342 * call will "eat" the exponent, too. Strip space, strip sign,
343 * strip float number (without! exponent), check for exponent
344 * and get exponent value. Accept absence of Esnn suffixes.
345 */
346 while (p && *p && g_ascii_isspace(*p))
347 p++;
348 if (p && *p && (*p == '+' || *p == '-'))
349 p++;
350 while (p && *p && g_ascii_isdigit(*p))
351 p++;
352 if (p && *p && *p == '.')
353 p++;
354 while (p && *p && g_ascii_isdigit(*p))
355 p++;
356 ret = SR_OK;
357 if (!p || !*p)
358 prec_exp = 0;
359 else if (*p != 'e' && *p != 'E')
360 ret = SR_ERR_DATA;
361 else
362 ret = sr_atoi(++p, &prec_exp);
363 g_free(mode_response);
364 if (ret != SR_OK)
365 return ret;
366
367 /*
368 * Get the measurement value. Make sure to strip trailing space
369 * or else number conversion may fail in fatal ways. Detect OL
370 * conditions. Determine the measurement's precision: Count the
371 * number of significant digits before the period, and get the
372 * exponent's value.
373 *
374 * The text presentation of values is like this:
375 * +1.09450000E-01
376 * Skip space/sign, count digits before the period, skip to the
377 * exponent, get exponent value.
378 *
379 * TODO Can sr_parse_rational() return the exponent for us? In
380 * addition to providing a precise rational value instead of a
381 * float that's an approximation of the received value? Can the
382 * 'analog' struct that we fill in carry rationals?
383 *
384 * Use double precision FP here during conversion. Optionally
385 * downgrade to single precision later to reduce the amount of
386 * logged information.
387 */
388 command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_VALUE);
389 if (!command || !*command)
390 return SR_ERR_NA;
3cdad416 391 scpi_dmm_cmd_delay(scpi);
28877994 392 ret = sr_scpi_get_string(scpi, command, &response);
3cdad416
GS
393 if (ret != SR_OK)
394 return ret;
395 g_strstrip(response);
396 use_double = devc->model->digits > 6;
397 ret = sr_atod_ascii(response, &info->d_value);
398 if (ret != SR_OK) {
399 g_free(response);
400 return ret;
401 }
402 if (!response)
403 return SR_ERR;
395c1850
GS
404 limit = 9e37;
405 if (info->d_value > +limit) {
3cdad416 406 info->d_value = +INFINITY;
395c1850 407 } else if (info->d_value < -limit) {
3cdad416
GS
408 info->d_value = -INFINITY;
409 } else {
410 p = response;
411 while (p && *p && g_ascii_isspace(*p))
412 p++;
413 if (p && *p && (*p == '-' || *p == '+'))
414 p++;
415 sig_digits = 0;
416 while (p && *p && g_ascii_isdigit(*p)) {
417 sig_digits++;
418 p++;
419 }
420 if (p && *p && *p == '.')
421 p++;
422 while (p && *p && g_ascii_isdigit(*p))
423 p++;
424 ret = SR_OK;
425 if (!p || !*p)
426 val_exp = 0;
427 else if (*p != 'e' && *p != 'E')
428 ret = SR_ERR_DATA;
429 else
430 ret = sr_atoi(++p, &val_exp);
431 }
432 g_free(response);
433 if (ret != SR_OK)
434 return ret;
435 /*
436 * TODO Come up with the most appropriate 'digits' calculation.
437 * This implementation assumes that either the device provides
438 * the resolution with the query for the meter's function, or
439 * the driver uses a fallback text pretending the device had
440 * provided it. This works with supported Agilent devices.
441 *
442 * An alternative may be to assume a given digits count which
443 * depends on the device, and adjust that count based on the
444 * value's significant digits and exponent. But this approach
445 * fails if devices change their digits count depending on
446 * modes or user requests, and also fails when e.g. devices
447 * with "100000 counts" can provide values between 100000 and
448 * 120000 in either 4 or 5 digits modes, depending on the most
449 * recent trend of the values. This less robust approach should
450 * only be taken if the mode inquiry won't yield the resolution
451 * (as e.g. DIOD does on 34405A, though we happen to know the
452 * fixed resolution for this very mode on this very model).
453 *
454 * For now, let's keep the prepared code path for the second
455 * approach in place, should some Agilent devices need it yet
456 * benefit from re-using most of the remaining acquisition
457 * routine.
458 */
459#if 1
460 digits = -prec_exp;
461#else
462 digits = devc->model->digits;
463 digits -= sig_digits;
464 digits -= val_exp;
465#endif
466
467 /*
468 * Fill in the 'analog' description: value, encoding, meaning.
469 * Callers will fill in the sample count, and channel name,
470 * and will send out the packet.
471 */
472 if (use_double) {
473 analog->data = &info->d_value;
474 analog->encoding->unitsize = sizeof(info->d_value);
475 } else {
476 info->f_value = info->d_value;
477 analog->data = &info->f_value;
478 analog->encoding->unitsize = sizeof(info->f_value);
479 }
3cdad416
GS
480 analog->encoding->digits = digits;
481 analog->meaning->mq = mq;
482 analog->meaning->mqflags = mqflag;
483 switch (mq) {
484 case SR_MQ_VOLTAGE:
485 unit = SR_UNIT_VOLT;
486 break;
487 case SR_MQ_CURRENT:
488 unit = SR_UNIT_AMPERE;
489 break;
490 case SR_MQ_RESISTANCE:
491 case SR_MQ_CONTINUITY:
492 unit = SR_UNIT_OHM;
493 break;
494 case SR_MQ_CAPACITANCE:
495 unit = SR_UNIT_FARAD;
496 break;
497 case SR_MQ_TEMPERATURE:
498 unit = SR_UNIT_CELSIUS;
499 break;
500 case SR_MQ_FREQUENCY:
501 unit = SR_UNIT_HERTZ;
502 break;
a1619831
AG
503 case SR_MQ_TIME:
504 unit = SR_UNIT_SECOND;
505 break;
3cdad416
GS
506 default:
507 return SR_ERR_NA;
508 }
509 analog->meaning->unit = unit;
510 analog->spec->spec_digits = digits;
511
512 return SR_OK;
513}
514
d0b602f0
TK
515SR_PRIV int scpi_dmm_get_meas_gwinstek(const struct sr_dev_inst *sdi, size_t ch)
516{
517 struct sr_scpi_dev_inst *scpi;
518 struct dev_context *devc;
519 struct scpi_dmm_acq_info *info;
520 struct sr_datafeed_analog *analog;
521 int ret;
522 enum sr_mq mq;
523 enum sr_mqflag mqflag;
524 char *mode_response;
525 const char *p;
526 const struct mqopt_item *item;
527 const char *command;
528 char *response;
529 gboolean use_double;
33aa8117 530 double limit;
d0b602f0
TK
531 int sig_digits, val_exp;
532 int digits;
533 enum sr_unit unit;
534 int mmode;
535
536 scpi = sdi->conn;
537 devc = sdi->priv;
538 info = &devc->run_acq_info;
539 analog = &info->analog[ch];
540
541 /*
542 * Get the meter's current mode, keep the response around.
543 * Skip the measurement if the mode is uncertain.
544 */
545 ret = scpi_dmm_get_mq(sdi, &mq, &mqflag, &mode_response, &item);
546 if (ret != SR_OK) {
547 g_free(mode_response);
548 return ret;
549 }
550 if (!mode_response)
551 return SR_ERR;
552 if (!mq) {
553 g_free(mode_response);
554 return +1;
555 }
556 mmode = atoi(mode_response);
557 g_free(mode_response);
558
559 /*
560 * Get the current reading from the meter.
561 */
562 scpi_dmm_cmd_delay(scpi);
563 command = sr_scpi_cmd_get(devc->cmdset, DMM_CMD_QUERY_VALUE);
564 if (!command || !*command)
565 return SR_ERR_NA;
566 scpi_dmm_cmd_delay(scpi);
567 ret = sr_scpi_get_string(scpi, command, &response);
568 if (ret != SR_OK)
569 return ret;
570 g_strstrip(response);
571 use_double = devc->model->digits > 6;
572 ret = sr_atod_ascii(response, &info->d_value);
573 if (ret != SR_OK) {
574 g_free(response);
575 return ret;
576 }
577 if (!response)
578 return SR_ERR;
395c1850 579 limit = 9e37;
33306b13
PA
580 if (devc->model->infinity_limit != 0.0)
581 limit = devc->model->infinity_limit;
582 if (info->d_value >= +limit) {
d0b602f0 583 info->d_value = +INFINITY;
33306b13 584 } else if (info->d_value <= -limit) {
d0b602f0
TK
585 info->d_value = -INFINITY;
586 } else {
587 p = response;
588 while (p && *p && g_ascii_isspace(*p))
589 p++;
590 if (p && *p && (*p == '-' || *p == '+'))
591 p++;
592 sig_digits = 0;
593 while (p && *p && g_ascii_isdigit(*p)) {
594 sig_digits++;
595 p++;
596 }
597 if (p && *p && *p == '.')
598 p++;
599 while (p && *p && g_ascii_isdigit(*p))
600 p++;
601 ret = SR_OK;
602 if (!p || !*p)
603 val_exp = 0;
604 else if (*p != 'e' && *p != 'E')
605 ret = SR_ERR_DATA;
606 else
607 ret = sr_atoi(++p, &val_exp);
608 }
609 g_free(response);
610 if (ret != SR_OK)
611 return ret;
612
613 /*
33aa8117 614 * Make sure we report "INFINITY" when meter displays "0L".
d0b602f0
TK
615 */
616 switch (mmode) {
617 case 7:
618 case 16:
33aa8117 619 /* In resitance modes 0L reads as 1.20000E8 or 1.99999E8. */
395c1850 620 limit = 1.2e8;
33aa8117
GS
621 if (strcmp(devc->model->model, "GDM8255A") == 0)
622 limit = 1.99999e8;
33aa8117
GS
623 if (info->d_value >= limit)
624 info->d_value = +INFINITY;
d0b602f0
TK
625 break;
626 case 13:
33aa8117 627 /* In continuity mode 0L reads as 1.20000E3. */
d0b602f0
TK
628 if (info->d_value >= 1.2e3)
629 info->d_value = +INFINITY;
630 break;
631 case 17:
33aa8117 632 /* In diode mode 0L reads as 1.00000E0. */
d0b602f0
TK
633 if (info->d_value == 1.0e0)
634 info->d_value = +INFINITY;
635 break;
636 }
637
638 /*
33aa8117
GS
639 * Calculate 'digits' based on the result of the optional
640 * precision reading which was done at acquisition start.
641 * The GW-Instek manual gives the following information
642 * regarding the resolution:
d0b602f0 643 *
33aa8117
GS
644 * Type Digit
645 * -------- ------
646 * Slow 5 1/2
647 * Medium 4 1/2
648 * Fast 3 1/2
d0b602f0 649 */
d0b602f0
TK
650 digits = devc->model->digits;
651 if (devc->precision && *devc->precision) {
33aa8117 652 if (g_str_has_prefix(devc->precision, "Slow"))
d0b602f0 653 digits = 6;
33aa8117 654 else if (g_str_has_prefix(devc->precision, "Mid"))
d0b602f0 655 digits = 5;
33aa8117 656 else if (g_str_has_prefix(devc->precision, "Fast"))
d0b602f0
TK
657 digits = 4;
658 else
33aa8117 659 sr_info("Unknown precision: '%s'", devc->precision);
d0b602f0
TK
660 }
661
662 /*
663 * Fill in the 'analog' description: value, encoding, meaning.
664 * Callers will fill in the sample count, and channel name,
665 * and will send out the packet.
666 */
667 if (use_double) {
668 analog->data = &info->d_value;
669 analog->encoding->unitsize = sizeof(info->d_value);
670 } else {
671 info->f_value = info->d_value;
672 analog->data = &info->f_value;
673 analog->encoding->unitsize = sizeof(info->f_value);
674 }
d0b602f0
TK
675 analog->encoding->digits = digits;
676 analog->meaning->mq = mq;
677 analog->meaning->mqflags = mqflag;
678 switch (mq) {
679 case SR_MQ_VOLTAGE:
680 unit = SR_UNIT_VOLT;
681 break;
682 case SR_MQ_CURRENT:
683 unit = SR_UNIT_AMPERE;
684 break;
685 case SR_MQ_RESISTANCE:
686 case SR_MQ_CONTINUITY:
687 unit = SR_UNIT_OHM;
688 break;
689 case SR_MQ_CAPACITANCE:
690 unit = SR_UNIT_FARAD;
691 break;
692 case SR_MQ_TEMPERATURE:
693 switch (mmode) {
694 case 15:
695 unit = SR_UNIT_FAHRENHEIT;
696 break;
697 case 9:
698 default:
699 unit = SR_UNIT_CELSIUS;
700 }
701 break;
702 case SR_MQ_FREQUENCY:
703 unit = SR_UNIT_HERTZ;
704 break;
705 case SR_MQ_TIME:
706 unit = SR_UNIT_SECOND;
707 break;
708 default:
709 return SR_ERR_NA;
710 }
711 analog->meaning->unit = unit;
712 analog->spec->spec_digits = digits;
713
714 return SR_OK;
715}
716
3cdad416 717/* Strictly speaking this is a timer controlled poll routine. */
7a396ff5
GS
718SR_PRIV int scpi_dmm_receive_data(int fd, int revents, void *cb_data)
719{
3cdad416
GS
720 struct sr_dev_inst *sdi;
721 struct sr_scpi_dev_inst *scpi;
7a396ff5 722 struct dev_context *devc;
3cdad416
GS
723 struct scpi_dmm_acq_info *info;
724 gboolean sent_sample;
725 size_t ch;
726 struct sr_channel *channel;
727 int ret;
7a396ff5
GS
728
729 (void)fd;
3cdad416 730 (void)revents;
7a396ff5 731
3cdad416
GS
732 sdi = cb_data;
733 if (!sdi)
7a396ff5 734 return TRUE;
3cdad416
GS
735 scpi = sdi->conn;
736 devc = sdi->priv;
737 if (!scpi || !devc)
7a396ff5 738 return TRUE;
3cdad416
GS
739 info = &devc->run_acq_info;
740
741 sent_sample = FALSE;
742 ret = SR_OK;
743 for (ch = 0; ch < devc->num_channels; ch++) {
744 /* Check the channel's enabled status. */
745 channel = g_slist_nth_data(sdi->channels, ch);
746 if (!channel->enabled)
747 continue;
748
749 /*
750 * Prepare an analog measurement value. Note that digits
751 * will get updated later.
752 */
753 info->packet.type = SR_DF_ANALOG;
754 info->packet.payload = &info->analog[ch];
755 sr_analog_init(&info->analog[ch], &info->encoding[ch],
756 &info->meaning[ch], &info->spec[ch], 0);
757
758 /* Just check OPC before sending another request. */
759 scpi_dmm_cmd_delay(sdi->conn);
7a396ff5 760
3cdad416
GS
761 /*
762 * Have the model take and interpret a measurement. Lack
763 * of support is pointless, failed retrieval/conversion
764 * is considered fatal. The routine will fill in the
765 * 'analog' details, except for channel name and sample
766 * count (assume one value per channel).
767 *
768 * Note that non-zero non-negative return codes signal
769 * that the channel's data shell get skipped in this
770 * iteration over the channels. This copes with devices
771 * or modes where channels may provide data at different
772 * rates.
773 */
774 if (!devc->model->get_measurement) {
775 ret = SR_ERR_NA;
776 break;
777 }
778 ret = devc->model->get_measurement(sdi, ch);
779 if (ret > 0)
780 continue;
781 if (ret != SR_OK)
782 break;
783
784 /* Send the packet that was filled in by the model's routine. */
785 info->analog[ch].num_samples = 1;
786 info->analog[ch].meaning->channels = g_slist_append(NULL, channel);
787 sr_session_send(sdi, &info->packet);
788 g_slist_free(info->analog[ch].meaning->channels);
789 sent_sample = TRUE;
790 }
791 if (sent_sample)
792 sr_sw_limits_update_samples_read(&devc->limits, 1);
793 if (ret != SR_OK) {
794 /* Stop acquisition upon communication or data errors. */
795 sr_dev_acquisition_stop(sdi);
796 return TRUE;
7a396ff5 797 }
3cdad416
GS
798 if (sr_sw_limits_check(&devc->limits))
799 sr_dev_acquisition_stop(sdi);
7a396ff5
GS
800
801 return TRUE;
802}