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