]> sigrok.org Git - libsigrok.git/blame - src/hardware/agilent-dmm/sched.c
Build: Set local include directories in Makefile.am
[libsigrok.git] / src / hardware / agilent-dmm / sched.c
CommitLineData
e93cdf42 1/*
50985c20 2 * This file is part of the libsigrok project.
e93cdf42
BV
3 *
4 * Copyright (C) 2012 Bert Vermeulen <bert@biot.com>
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 <glib.h>
e93cdf42
BV
21#include <stdlib.h>
22#include <string.h>
e93cdf42 23#include <math.h>
c1aae900 24#include <libsigrok/libsigrok.h>
515ab088
UH
25#include "libsigrok-internal.h"
26#include "agilent-dmm.h"
e93cdf42 27
e93cdf42
BV
28static void dispatch(const struct sr_dev_inst *sdi)
29{
30 struct dev_context *devc;
31 const struct agdmm_job *jobs;
32 int64_t now;
33 int i;
34
35 devc = sdi->priv;
36 jobs = devc->profile->jobs;
37 now = g_get_monotonic_time() / 1000;
38 for (i = 0; (&jobs[i])->interval; i++) {
39 if (now - devc->jobqueue[i] > (&jobs[i])->interval) {
38d326e8 40 sr_spew("Running job %d.", i);
e93cdf42
BV
41 (&jobs[i])->send(sdi);
42 devc->jobqueue[i] = now;
43 }
44 }
e93cdf42
BV
45}
46
47static void receive_line(const struct sr_dev_inst *sdi)
48{
49 struct dev_context *devc;
50 const struct agdmm_recv *recvs, *recv;
51 GRegex *reg;
52 GMatchInfo *match;
53 int i;
54
55 devc = sdi->priv;
56
57 /* Strip CRLF */
58 while (devc->buflen) {
59 if (*(devc->buf + devc->buflen - 1) == '\r'
60 || *(devc->buf + devc->buflen - 1) == '\n')
61 *(devc->buf + --devc->buflen) = '\0';
62 else
63 break;
64 }
38d326e8 65 sr_spew("Received '%s'.", devc->buf);
e93cdf42
BV
66
67 recv = NULL;
68 recvs = devc->profile->recvs;
69 for (i = 0; (&recvs[i])->recv_regex; i++) {
70 reg = g_regex_new((&recvs[i])->recv_regex, 0, 0, NULL);
71 if (g_regex_match(reg, (char *)devc->buf, 0, &match)) {
72 recv = &recvs[i];
73 break;
74 }
75 g_match_info_unref(match);
76 g_regex_unref(reg);
77 }
78 if (recv) {
79 recv->recv(sdi, match);
80 g_match_info_unref(match);
81 g_regex_unref(reg);
f2e86bbf 82 } else
38d326e8 83 sr_dbg("Unknown line '%s'.", devc->buf);
e93cdf42
BV
84
85 /* Done with this. */
86 devc->buflen = 0;
e93cdf42
BV
87}
88
89SR_PRIV int agdmm_receive_data(int fd, int revents, void *cb_data)
90{
642e9d62 91 struct sr_dev_inst *sdi;
e93cdf42 92 struct dev_context *devc;
fb3a1505 93 struct sr_serial_dev_inst *serial;
e93cdf42
BV
94 int len;
95
109a3ba4
BV
96 (void)fd;
97
e93cdf42
BV
98 if (!(sdi = cb_data))
99 return TRUE;
100
101 if (!(devc = sdi->priv))
102 return TRUE;
103
fb3a1505 104 serial = sdi->conn;
e93cdf42
BV
105 if (revents == G_IO_IN) {
106 /* Serial data arrived. */
0c5f2abc 107 while (AGDMM_BUFSIZE - devc->buflen - 1 > 0) {
e0b781a4 108 len = serial_read_nonblocking(serial, devc->buf + devc->buflen, 1);
f2e86bbf
BV
109 if (len < 1)
110 break;
111 devc->buflen += len;
112 *(devc->buf + devc->buflen) = '\0';
113 if (*(devc->buf + devc->buflen - 1) == '\n') {
114 /* End of line */
115 receive_line(sdi);
116 break;
e93cdf42
BV
117 }
118 }
119 }
120
121 dispatch(sdi);
122
35e199da 123 if (devc->limit_samples && devc->num_samples >= devc->limit_samples)
e93cdf42
BV
124 sdi->driver->dev_acquisition_stop(sdi, cb_data);
125
126 return TRUE;
127}
128
129static int agdmm_send(const struct sr_dev_inst *sdi, const char *cmd)
130{
fb3a1505 131 struct sr_serial_dev_inst *serial;
e93cdf42
BV
132 char buf[32];
133
fb3a1505
BV
134 serial = sdi->conn;
135
38d326e8 136 sr_spew("Sending '%s'.", cmd);
e93cdf42
BV
137 strncpy(buf, cmd, 28);
138 if (!strncmp(buf, "*IDN?", 5))
90486ba8 139 strcat(buf, "\r\n");
e93cdf42 140 else
90486ba8 141 strcat(buf, "\n\r\n");
95779b43 142 if (serial_write_blocking(serial, buf, strlen(buf), SERIAL_WRITE_TIMEOUT_MS) < (int)strlen(buf)) {
081c214e 143 sr_err("Failed to send.");
e93cdf42
BV
144 return SR_ERR;
145 }
ce4d26dd 146
e93cdf42
BV
147 return SR_OK;
148}
149
a4394fb3 150static int send_stat(const struct sr_dev_inst *sdi)
e93cdf42 151{
e93cdf42
BV
152 return agdmm_send(sdi, "STAT?");
153}
154
8c0152f2 155static int recv_stat_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
e93cdf42 156{
e6b021f3
BV
157 struct dev_context *devc;
158 char *s;
159
160 devc = sdi->priv;
161 s = g_match_info_fetch(match, 1);
38d326e8 162 sr_spew("STAT response '%s'.", s);
e6b021f3
BV
163
164 /* Max, Min or Avg mode -- no way to tell which, so we'll
165 * set both flags to denote it's not a normal measurement. */
166 if (s[0] == '1')
167 devc->cur_mqflags |= SR_MQFLAG_MAX | SR_MQFLAG_MIN;
168 else
169 devc->cur_mqflags &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN);
e93cdf42 170
e6b021f3
BV
171 if (s[1] == '1')
172 devc->cur_mqflags |= SR_MQFLAG_RELATIVE;
173 else
174 devc->cur_mqflags &= ~SR_MQFLAG_RELATIVE;
175
176 /* Triggered or auto hold modes. */
177 if (s[2] == '1' || s[3] == '1')
178 devc->cur_mqflags |= SR_MQFLAG_HOLD;
179 else
180 devc->cur_mqflags &= ~SR_MQFLAG_HOLD;
181
182 /* Temp/aux mode. */
183 if (s[7] == '1')
184 devc->mode_tempaux = TRUE;
185 else
186 devc->mode_tempaux = FALSE;
187
38d326e8 188 /* Continuity mode. */
e6b021f3
BV
189 if (s[16] == '1')
190 devc->mode_continuity = TRUE;
191 else
192 devc->mode_continuity = FALSE;
193
194 g_free(s);
e93cdf42
BV
195
196 return SR_OK;
197}
198
173378f0
BV
199static int recv_stat_u124x(const struct sr_dev_inst *sdi, GMatchInfo *match)
200{
201 struct dev_context *devc;
202 char *s;
203
204 devc = sdi->priv;
205 s = g_match_info_fetch(match, 1);
206 sr_spew("STAT response '%s'.", s);
207
208 /* Max, Min or Avg mode -- no way to tell which, so we'll
209 * set both flags to denote it's not a normal measurement. */
210 if (s[0] == '1')
211 devc->cur_mqflags |= SR_MQFLAG_MAX | SR_MQFLAG_MIN;
212 else
213 devc->cur_mqflags &= ~(SR_MQFLAG_MAX | SR_MQFLAG_MIN);
214
215 if (s[1] == '1')
216 devc->cur_mqflags |= SR_MQFLAG_RELATIVE;
217 else
218 devc->cur_mqflags &= ~SR_MQFLAG_RELATIVE;
219
220 /* Hold mode. */
221 if (s[7] == '1')
222 devc->cur_mqflags |= SR_MQFLAG_HOLD;
223 else
224 devc->cur_mqflags &= ~SR_MQFLAG_HOLD;
225
226 g_free(s);
227
228 return SR_OK;
229}
230
8c0152f2
BV
231static int recv_stat_u125x(const struct sr_dev_inst *sdi, GMatchInfo *match)
232{
233 struct dev_context *devc;
234 char *s;
235
236 devc = sdi->priv;
237 s = g_match_info_fetch(match, 1);
38d326e8 238 sr_spew("STAT response '%s'.", s);
8c0152f2
BV
239
240 /* Peak hold mode. */
241 if (s[4] == '1')
242 devc->cur_mqflags |= SR_MQFLAG_MAX;
243 else
244 devc->cur_mqflags &= ~SR_MQFLAG_MAX;
245
246 /* Triggered hold mode. */
247 if (s[7] == '1')
248 devc->cur_mqflags |= SR_MQFLAG_HOLD;
249 else
250 devc->cur_mqflags &= ~SR_MQFLAG_HOLD;
251
252 g_free(s);
253
254 return SR_OK;
255}
256
a4394fb3 257static int send_fetc(const struct sr_dev_inst *sdi)
e93cdf42 258{
e93cdf42
BV
259 return agdmm_send(sdi, "FETC?");
260}
261
a4394fb3 262static int recv_fetc(const struct sr_dev_inst *sdi, GMatchInfo *match)
e93cdf42
BV
263{
264 struct dev_context *devc;
265 struct sr_datafeed_packet packet;
266 struct sr_datafeed_analog analog;
267 float fvalue;
f216eb86 268 const char *s;
fe9d5abe 269 char *mstr;
e93cdf42 270
38d326e8 271 sr_spew("FETC reply '%s'.", g_match_info_get_string(match));
e93cdf42
BV
272 devc = sdi->priv;
273
274 if (devc->cur_mq == -1)
275 /* Haven't seen configuration yet, so can't know what
276 * the fetched float means. Not really an error, we'll
277 * get metadata soon enough. */
278 return SR_OK;
279
f216eb86
BV
280 s = g_match_info_get_string(match);
281 if (!strcmp(s, "-9.90000000E+37") || !strcmp(s, "+9.90000000E+37")) {
74ac7d7f 282 /* An invalid measurement shows up on the display as "O.L", but
e93cdf42
BV
283 * comes through like this. Since comparing 38-digit floats
284 * is rather problematic, we'll cut through this here. */
285 fvalue = NAN;
286 } else {
287 mstr = g_match_info_fetch(match, 1);
7c03b564 288 if (sr_atof_ascii(mstr, &fvalue) != SR_OK) {
fe9d5abe 289 g_free(mstr);
51b92b7d 290 sr_dbg("Invalid float.");
e93cdf42
BV
291 return SR_ERR;
292 }
fe9d5abe 293 g_free(mstr);
e93cdf42
BV
294 if (devc->cur_divider > 0)
295 fvalue /= devc->cur_divider;
296 }
297
298 memset(&analog, 0, sizeof(struct sr_datafeed_analog));
299 analog.mq = devc->cur_mq;
e6b021f3
BV
300 analog.unit = devc->cur_unit;
301 analog.mqflags = devc->cur_mqflags;
ba7dd8bb 302 analog.channels = sdi->channels;
e93cdf42
BV
303 analog.num_samples = 1;
304 analog.data = &fvalue;
305 packet.type = SR_DF_ANALOG;
306 packet.payload = &analog;
307 sr_session_send(devc->cb_data, &packet);
308
309 devc->num_samples++;
310
311 return SR_OK;
312}
313
a4394fb3 314static int send_conf(const struct sr_dev_inst *sdi)
e93cdf42 315{
e93cdf42
BV
316 return agdmm_send(sdi, "CONF?");
317}
318
a4394fb3 319static int recv_conf_u123x(const struct sr_dev_inst *sdi, GMatchInfo *match)
e93cdf42
BV
320{
321 struct dev_context *devc;
322 char *mstr;
323
38d326e8 324 sr_spew("CONF? response '%s'.", g_match_info_get_string(match));
e93cdf42
BV
325 devc = sdi->priv;
326 mstr = g_match_info_fetch(match, 1);
327 if (!strcmp(mstr, "V")) {
328 devc->cur_mq = SR_MQ_VOLTAGE;
e6b021f3
BV
329 devc->cur_unit = SR_UNIT_VOLT;
330 devc->cur_mqflags = 0;
e93cdf42 331 devc->cur_divider = 0;
0c5f2abc 332 } else if (!strcmp(mstr, "MV")) {
e6b021f3
BV
333 if (devc->mode_tempaux) {
334 devc->cur_mq = SR_MQ_TEMPERATURE;
f3f19d11
UH
335 /* No way to detect whether Fahrenheit or Celsius
336 * is used, so we'll just default to Celsius. */
e6b021f3
BV
337 devc->cur_unit = SR_UNIT_CELSIUS;
338 devc->cur_mqflags = 0;
339 devc->cur_divider = 0;
340 } else {
341 devc->cur_mq = SR_MQ_VOLTAGE;
342 devc->cur_unit = SR_UNIT_VOLT;
343 devc->cur_mqflags = 0;
344 devc->cur_divider = 1000;
345 }
0c5f2abc 346 } else if (!strcmp(mstr, "A")) {
e93cdf42 347 devc->cur_mq = SR_MQ_CURRENT;
e6b021f3
BV
348 devc->cur_unit = SR_UNIT_AMPERE;
349 devc->cur_mqflags = 0;
e93cdf42 350 devc->cur_divider = 0;
0c5f2abc 351 } else if (!strcmp(mstr, "UA")) {
e93cdf42 352 devc->cur_mq = SR_MQ_CURRENT;
e6b021f3
BV
353 devc->cur_unit = SR_UNIT_AMPERE;
354 devc->cur_mqflags = 0;
e93cdf42 355 devc->cur_divider = 1000000;
0c5f2abc 356 } else if (!strcmp(mstr, "FREQ")) {
e93cdf42 357 devc->cur_mq = SR_MQ_FREQUENCY;
e6b021f3
BV
358 devc->cur_unit = SR_UNIT_HERTZ;
359 devc->cur_mqflags = 0;
e93cdf42 360 devc->cur_divider = 0;
0c5f2abc 361 } else if (!strcmp(mstr, "RES")) {
e6b021f3
BV
362 if (devc->mode_continuity) {
363 devc->cur_mq = SR_MQ_CONTINUITY;
364 devc->cur_unit = SR_UNIT_BOOLEAN;
365 } else {
366 devc->cur_mq = SR_MQ_RESISTANCE;
367 devc->cur_unit = SR_UNIT_OHM;
368 }
369 devc->cur_mqflags = 0;
e93cdf42 370 devc->cur_divider = 0;
0c5f2abc 371 } else if (!strcmp(mstr, "CAP")) {
e93cdf42 372 devc->cur_mq = SR_MQ_CAPACITANCE;
e6b021f3
BV
373 devc->cur_unit = SR_UNIT_FARAD;
374 devc->cur_mqflags = 0;
e93cdf42 375 devc->cur_divider = 0;
e93cdf42 376 } else
38d326e8 377 sr_dbg("Unknown first argument.");
e93cdf42
BV
378 g_free(mstr);
379
e066c32a
BV
380 if (g_match_info_get_match_count(match) == 4) {
381 mstr = g_match_info_fetch(match, 3);
e93cdf42 382 /* Third value, if present, is always AC or DC. */
51b92b7d 383 if (!strcmp(mstr, "AC")) {
e6b021f3 384 devc->cur_mqflags |= SR_MQFLAG_AC;
51b92b7d
BV
385 if (devc->cur_mq == SR_MQ_VOLTAGE)
386 devc->cur_mqflags |= SR_MQFLAG_RMS;
387 } else if (!strcmp(mstr, "DC")) {
e6b021f3 388 devc->cur_mqflags |= SR_MQFLAG_DC;
51b92b7d 389 } else {
a965748a 390 sr_dbg("Unknown first argument '%s'.", mstr);
51b92b7d 391 }
e93cdf42 392 g_free(mstr);
e6b021f3
BV
393 } else
394 devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
e93cdf42
BV
395
396 return SR_OK;
397}
398
173378f0 399static int recv_conf_u124x_5x(const struct sr_dev_inst *sdi, GMatchInfo *match)
8c0152f2
BV
400{
401 struct dev_context *devc;
a965748a 402 char *mstr, *m2;
8c0152f2 403
38d326e8 404 sr_spew("CONF? response '%s'.", g_match_info_get_string(match));
8c0152f2
BV
405 devc = sdi->priv;
406 mstr = g_match_info_fetch(match, 1);
407 if (!strncmp(mstr, "VOLT", 4)) {
408 devc->cur_mq = SR_MQ_VOLTAGE;
409 devc->cur_unit = SR_UNIT_VOLT;
410 devc->cur_mqflags = 0;
411 devc->cur_divider = 0;
412 if (mstr[4] == ':') {
ee2bcdfc 413 if (!strncmp(mstr + 5, "AC", 2)) {
51b92b7d 414 devc->cur_mqflags |= SR_MQFLAG_AC | SR_MQFLAG_RMS;
ee2bcdfc 415 } else if (!strncmp(mstr + 5, "DC", 2)) {
8c0152f2 416 devc->cur_mqflags |= SR_MQFLAG_DC;
ee2bcdfc 417 } else if (!strncmp(mstr + 5, "ACDC", 4)) {
51b92b7d
BV
418 /* AC + DC offset */
419 devc->cur_mqflags |= SR_MQFLAG_AC | SR_MQFLAG_DC | SR_MQFLAG_RMS;
420 } else {
8c0152f2 421 devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
51b92b7d 422 }
8c0152f2
BV
423 } else
424 devc->cur_mqflags &= ~(SR_MQFLAG_AC | SR_MQFLAG_DC);
0c5f2abc 425 } else if (!strcmp(mstr, "CURR")) {
8c0152f2
BV
426 devc->cur_mq = SR_MQ_CURRENT;
427 devc->cur_unit = SR_UNIT_AMPERE;
428 devc->cur_mqflags = 0;
429 devc->cur_divider = 0;
0c5f2abc 430 } else if (!strcmp(mstr, "RES")) {
a965748a
BV
431 devc->cur_mq = SR_MQ_RESISTANCE;
432 devc->cur_unit = SR_UNIT_OHM;
433 devc->cur_mqflags = 0;
434 devc->cur_divider = 0;
0c5f2abc 435 } else if (!strcmp(mstr, "CAP")) {
a965748a
BV
436 devc->cur_mq = SR_MQ_CAPACITANCE;
437 devc->cur_unit = SR_UNIT_FARAD;
8c0152f2
BV
438 devc->cur_mqflags = 0;
439 devc->cur_divider = 0;
0c5f2abc 440 } else if (!strcmp(mstr, "FREQ")) {
a965748a
BV
441 devc->cur_mq = SR_MQ_FREQUENCY;
442 devc->cur_unit = SR_UNIT_HERTZ;
443 devc->cur_mqflags = 0;
444 devc->cur_divider = 0;
0c5f2abc 445 } else if (!strcmp(mstr, "CONT")) {
a965748a
BV
446 devc->cur_mq = SR_MQ_CONTINUITY;
447 devc->cur_unit = SR_UNIT_BOOLEAN;
448 devc->cur_mqflags = 0;
449 devc->cur_divider = 0;
0c5f2abc 450 } else if (!strncmp(mstr, "T1", 2) || !strncmp(mstr, "T2", 2)) {
a965748a
BV
451 devc->cur_mq = SR_MQ_TEMPERATURE;
452 m2 = g_match_info_fetch(match, 2);
453 if (!strcmp(m2, "FAR"))
454 devc->cur_unit = SR_UNIT_FAHRENHEIT;
455 else
456 devc->cur_unit = SR_UNIT_CELSIUS;
457 g_free(m2);
458 devc->cur_mqflags = 0;
459 devc->cur_divider = 0;
0c5f2abc 460 } else if (!strcmp(mstr, "SCOU")) {
a965748a
BV
461 /*
462 * Switch counter, not supported. Not sure what values
463 * come from FETC in this mode, or how they would map
464 * into libsigrok.
465 */
0c5f2abc 466 } else if (!strncmp(mstr, "CPER:", 5)) {
110fe1b4
BV
467 devc->cur_mq = SR_MQ_CURRENT;
468 devc->cur_unit = SR_UNIT_PERCENTAGE;
469 devc->cur_mqflags = 0;
470 devc->cur_divider = 0;
51b92b7d 471 } else {
a965748a 472 sr_dbg("Unknown first argument '%s'.", mstr);
51b92b7d 473 }
8c0152f2
BV
474 g_free(mstr);
475
8c0152f2
BV
476 return SR_OK;
477}
478
a4394fb3
BV
479static int recv_conf(const struct sr_dev_inst *sdi, GMatchInfo *match)
480{
481 struct dev_context *devc;
482 char *mstr;
483
38d326e8 484 sr_spew("CONF? response '%s'.", g_match_info_get_string(match));
a4394fb3
BV
485 devc = sdi->priv;
486 mstr = g_match_info_fetch(match, 1);
0c5f2abc 487 if (!strcmp(mstr, "DIOD")) {
a4394fb3
BV
488 devc->cur_mq = SR_MQ_VOLTAGE;
489 devc->cur_unit = SR_UNIT_VOLT;
490 devc->cur_mqflags = SR_MQFLAG_DIODE;
491 devc->cur_divider = 0;
8c0152f2 492 } else
38d326e8 493 sr_dbg("Unknown single argument.");
a4394fb3
BV
494 g_free(mstr);
495
496 return SR_OK;
497}
498
81599cc5
BV
499/* This comes in whenever the rotary switch is changed to a new position.
500 * We could use it to determine the major measurement mode, but we already
501 * have the output of CONF? for that, which is more detailed. However
502 * we do need to catch this here, or it'll show up in some other output. */
a4394fb3 503static int recv_switch(const struct sr_dev_inst *sdi, GMatchInfo *match)
e93cdf42 504{
e93cdf42
BV
505 (void)sdi;
506
38d326e8 507 sr_spew("Switch '%s'.", g_match_info_get_string(match));
e93cdf42
BV
508
509 return SR_OK;
510}
511
f857bd92
BV
512/* Poll keys/switches and values at 7Hz, mode at 1Hz. */
513SR_PRIV const struct agdmm_job agdmm_jobs_u12xx[] = {
a4394fb3
BV
514 { 143, send_stat },
515 { 1000, send_conf },
516 { 143, send_fetc },
e93cdf42
BV
517 { 0, NULL }
518};
519
8c0152f2
BV
520SR_PRIV const struct agdmm_recv agdmm_recvs_u123x[] = {
521 { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u123x },
a4394fb3
BV
522 { "^\\*([0-9])$", recv_switch },
523 { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
524 { "^\"(V|MV|A|UA|FREQ),(\\d),(AC|DC)\"$", recv_conf_u123x },
525 { "^\"(RES|CAP),(\\d)\"$", recv_conf_u123x},
526 { "^\"(DIOD)\"$", recv_conf },
e93cdf42
BV
527 { NULL, NULL }
528};
529
173378f0
BV
530SR_PRIV const struct agdmm_recv agdmm_recvs_u124x[] = {
531 { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u124x },
532 { "^\\*([0-9])$", recv_switch },
533 { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
110fe1b4 534 { "^\"(VOLT|CURR|RES|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
ee2bcdfc 535 { "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
110fe1b4 536 { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
a965748a 537 { "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
173378f0
BV
538 { "^\"(DIOD)\"$", recv_conf },
539 { NULL, NULL }
540};
541
8c0152f2
BV
542SR_PRIV const struct agdmm_recv agdmm_recvs_u125x[] = {
543 { "^\"(\\d\\d.{18}\\d)\"$", recv_stat_u125x },
544 { "^\\*([0-9])$", recv_switch },
545 { "^([-+][0-9]\\.[0-9]{8}E[-+][0-9]{2})$", recv_fetc },
110fe1b4 546 { "^\"(VOLT|CURR|RES|CAP|FREQ) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
ee2bcdfc 547 { "^\"(VOLT:[ACD]+) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
110fe1b4 548 { "^\"(CPER:[40]-20mA) ([-+][0-9\\.E\\-+]+),([-+][0-9\\.E\\-+]+)\"$", recv_conf_u124x_5x },
c7f5219e 549 { "^\"(T[0-9]:[A-Z]+) ([A-Z]+)\"$", recv_conf_u124x_5x },
8c0152f2
BV
550 { "^\"(DIOD)\"$", recv_conf },
551 { NULL, NULL }
552};