]> sigrok.org Git - libsigrok.git/blob - src/hardware/hp-3478a/protocol.c
rigol-ds: improve robustness in samplerate getting code path
[libsigrok.git] / src / hardware / hp-3478a / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2017-2021 Frank Stettner <frank-stettner@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 <stdlib.h>
23 #include "scpi.h"
24 #include "protocol.h"
25
26 static int set_mq_volt(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags);
27 static int set_mq_amp(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags);
28 static int set_mq_ohm(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags);
29
30 static const struct {
31         enum sr_mq mq;
32         int (*set_mode)(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags);
33 } sr_mq_to_cmd_map[] = {
34         { SR_MQ_VOLTAGE, set_mq_volt },
35         { SR_MQ_CURRENT, set_mq_amp },
36         { SR_MQ_RESISTANCE, set_mq_ohm },
37 };
38
39 static int set_mq_volt(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags)
40 {
41         if ((flags & SR_MQFLAG_AC) != SR_MQFLAG_AC &&
42                 (flags & SR_MQFLAG_DC) != SR_MQFLAG_DC)
43                 return SR_ERR_NA;
44
45         return sr_scpi_send(scpi, "%s",
46                 ((flags & SR_MQFLAG_AC) == SR_MQFLAG_AC) ? "F2" : "F1");
47 }
48
49 static int set_mq_amp(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags)
50 {
51         if ((flags & SR_MQFLAG_AC) != SR_MQFLAG_AC &&
52                 (flags & SR_MQFLAG_DC) != SR_MQFLAG_DC)
53                 return SR_ERR_NA;
54
55         return sr_scpi_send(scpi, "%s", (flags & SR_MQFLAG_AC) ? "F6" : "F5");
56 }
57
58 static int set_mq_ohm(struct sr_scpi_dev_inst *scpi, enum sr_mqflag flags)
59 {
60         return sr_scpi_send(scpi, "%s",
61                 (flags & SR_MQFLAG_FOUR_WIRE) ? "F4" : "F3");
62 }
63
64 SR_PRIV int hp_3478a_set_mq(const struct sr_dev_inst *sdi, enum sr_mq mq,
65                                 enum sr_mqflag mq_flags)
66 {
67         int ret;
68         size_t i;
69         struct sr_scpi_dev_inst *scpi = sdi->conn;
70         struct dev_context *devc = sdi->priv;
71
72         /* No need to send a command if we're not changing the measurement type. */
73         if (devc->measurement_mq == mq && devc->measurement_mq_flag == mq_flags)
74                 return SR_OK;
75
76         for (i = 0; i < ARRAY_SIZE(sr_mq_to_cmd_map); i++) {
77                 if (sr_mq_to_cmd_map[i].mq != mq)
78                         continue;
79
80                 ret = sr_mq_to_cmd_map[i].set_mode(scpi, mq_flags);
81                 if (ret != SR_OK)
82                         return ret;
83
84                 ret = hp_3478a_get_status_bytes(sdi);
85                 return ret;
86         }
87
88         return SR_ERR_NA;
89 }
90
91 SR_PRIV int hp_3478a_set_range(const struct sr_dev_inst *sdi, int range_exp)
92 {
93         int ret;
94         struct sr_scpi_dev_inst *scpi = sdi->conn;
95         struct dev_context *devc = sdi->priv;
96
97         /* No need to send command if we're not changing the range. */
98         if (devc->range_exp == range_exp)
99                 return SR_OK;
100
101         /* -99 is a dummy exponent for auto ranging. */
102         if (range_exp == -99)
103                 ret = sr_scpi_send(scpi, "RA");
104         else
105                 ret = sr_scpi_send(scpi, "R%i", range_exp);
106         if (ret != SR_OK)
107                 return ret;
108
109         return hp_3478a_get_status_bytes(sdi);
110 }
111
112 SR_PRIV int hp_3478a_set_digits(const struct sr_dev_inst *sdi, uint8_t digits)
113 {
114         int ret;
115         struct sr_scpi_dev_inst *scpi = sdi->conn;
116         struct dev_context *devc = sdi->priv;
117
118         /* No need to send command if we're not changing the range. */
119         if (devc->spec_digits == digits)
120                 return SR_OK;
121
122         /* digits are based on devc->spec_digits, so we have to substract 1 */
123         ret = sr_scpi_send(scpi, "N%i", digits-1);
124         if (ret != SR_OK)
125                 return ret;
126
127         return hp_3478a_get_status_bytes(sdi);
128 }
129
130 static int parse_range_vdc(struct dev_context *devc, uint8_t range_byte)
131 {
132         if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VDC_30MV) {
133                 devc->range_exp = -2;
134                 devc->enc_digits = devc->spec_digits - 2;
135         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VDC_300MV) {
136                 devc->range_exp = -1;
137                 devc->enc_digits = devc->spec_digits - 3;
138         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VDC_3V) {
139                 devc->range_exp = 0;
140                 devc->enc_digits = devc->spec_digits - 1;
141         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VDC_30V) {
142                 devc->range_exp = 1;
143                 devc->enc_digits = devc->spec_digits - 2;
144         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VDC_300V) {
145                 devc->range_exp = 2;
146                 devc->enc_digits = devc->spec_digits - 3;
147         } else
148                 return SR_ERR_DATA;
149
150         return SR_OK;
151 }
152
153 static int parse_range_vac(struct dev_context *devc, uint8_t range_byte)
154 {
155         if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VAC_300MV) {
156                 devc->range_exp = -1;
157                 devc->enc_digits = devc->spec_digits - 3;
158         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VAC_3V) {
159                 devc->range_exp = 0;
160                 devc->enc_digits = devc->spec_digits - 1;
161         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VAC_30V) {
162                 devc->range_exp = 1;
163                 devc->enc_digits = devc->spec_digits - 2;
164         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_VAC_300V) {
165                 devc->range_exp = 2;
166                 devc->enc_digits = devc->spec_digits - 3;
167         } else
168                 return SR_ERR_DATA;
169
170         return SR_OK;
171 }
172
173 static int parse_range_a(struct dev_context *devc, uint8_t range_byte)
174 {
175         if ((range_byte & SB1_RANGE_BLOCK) == RANGE_A_300MA) {
176                 devc->range_exp = -1;
177                 devc->enc_digits = devc->spec_digits - 3;
178         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_A_3A) {
179                 devc->range_exp = 0;
180                 devc->enc_digits = devc->spec_digits - 1;
181         } else
182                 return SR_ERR_DATA;
183
184         return SR_OK;
185 }
186
187 static int parse_range_ohm(struct dev_context *devc, uint8_t range_byte)
188 {
189         if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_30R) {
190                 devc->range_exp = 1;
191                 devc->enc_digits = devc->spec_digits - 2;
192         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_300R) {
193                 devc->range_exp = 2;
194                 devc->enc_digits = devc->spec_digits - 3;
195         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_3KR) {
196                 devc->range_exp = 3;
197                 devc->enc_digits = devc->spec_digits - 1;
198         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_30KR) {
199                 devc->range_exp = 4;
200                 devc->enc_digits = devc->spec_digits - 2;
201         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_300KR) {
202                 devc->range_exp = 5;
203                 devc->enc_digits = devc->spec_digits - 3;
204         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_3MR) {
205                 devc->range_exp = 6;
206                 devc->enc_digits = devc->spec_digits - 1;
207         } else if ((range_byte & SB1_RANGE_BLOCK) == RANGE_OHM_30MR) {
208                 devc->range_exp = 7;
209                 devc->enc_digits = devc->spec_digits - 2;
210         } else
211                 return SR_ERR_DATA;
212
213         return SR_OK;
214 }
215
216 static int parse_function_byte(struct dev_context *devc, uint8_t function_byte)
217 {
218         /* Digits / Resolution (spec_digits must be set before range parsing) */
219         if ((function_byte & SB1_DIGITS_BLOCK) == DIGITS_5_5)
220                 devc->spec_digits = 6;
221         else if ((function_byte & SB1_DIGITS_BLOCK) == DIGITS_4_5)
222                 devc->spec_digits = 5;
223         else if ((function_byte & SB1_DIGITS_BLOCK) == DIGITS_3_5)
224                 devc->spec_digits = 4;
225         else
226                 return SR_ERR_DATA;
227
228         /* Function + Range */
229         devc->measurement_mq_flag = 0;
230         devc->acquisition_mq_flags = 0;
231         if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_VDC) {
232                 devc->measurement_mq = SR_MQ_VOLTAGE;
233                 devc->measurement_mq_flag = SR_MQFLAG_DC;
234                 devc->acquisition_mq_flags |= SR_MQFLAG_DC;
235                 devc->measurement_unit = SR_UNIT_VOLT;
236                 parse_range_vdc(devc, function_byte);
237         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_VAC) {
238                 devc->measurement_mq = SR_MQ_VOLTAGE;
239                 devc->measurement_mq_flag = SR_MQFLAG_AC;
240                 devc->acquisition_mq_flags |= SR_MQFLAG_AC | SR_MQFLAG_RMS;
241                 devc->measurement_unit = SR_UNIT_VOLT;
242                 parse_range_vac(devc, function_byte);
243         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_2WR) {
244                 devc->measurement_mq = SR_MQ_RESISTANCE;
245                 devc->measurement_unit = SR_UNIT_OHM;
246                 parse_range_ohm(devc, function_byte);
247         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_4WR) {
248                 devc->measurement_mq = SR_MQ_RESISTANCE;
249                 devc->measurement_mq_flag = SR_MQFLAG_FOUR_WIRE;
250                 devc->acquisition_mq_flags |= SR_MQFLAG_FOUR_WIRE;
251                 devc->measurement_unit = SR_UNIT_OHM;
252                 parse_range_ohm(devc, function_byte);
253         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_ADC) {
254                 devc->measurement_mq = SR_MQ_CURRENT;
255                 devc->measurement_mq_flag = SR_MQFLAG_DC;
256                 devc->acquisition_mq_flags |= SR_MQFLAG_DC;
257                 devc->measurement_unit = SR_UNIT_AMPERE;
258                 parse_range_a(devc, function_byte);
259         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_AAC) {
260                 devc->measurement_mq = SR_MQ_CURRENT;
261                 devc->measurement_mq_flag = SR_MQFLAG_AC;
262                 devc->acquisition_mq_flags |= SR_MQFLAG_AC | SR_MQFLAG_RMS;
263                 devc->measurement_unit = SR_UNIT_AMPERE;
264                 parse_range_a(devc, function_byte);
265         } else if ((function_byte & SB1_FUNCTION_BLOCK) == FUNCTION_EXR) {
266                 devc->measurement_mq = SR_MQ_RESISTANCE;
267                 devc->measurement_unit = SR_UNIT_OHM;
268                 parse_range_ohm(devc, function_byte);
269         }
270
271         return SR_OK;
272 }
273
274 static int parse_status_byte(struct dev_context *devc, uint8_t status_byte)
275 {
276         devc->trigger = TRIGGER_UNDEFINED;
277
278         /* External Trigger */
279         if ((status_byte & STATUS_EXT_TRIGGER) == STATUS_EXT_TRIGGER)
280                 devc->trigger = TRIGGER_EXTERNAL;
281
282         /* Cal RAM */
283         if ((status_byte & STATUS_CAL_RAM) == STATUS_CAL_RAM)
284                 devc->calibration = TRUE;
285         else
286                 devc->calibration = FALSE;
287
288         /* Front/Rear terminals */
289         if ((status_byte & STATUS_FRONT_TERMINAL) == STATUS_FRONT_TERMINAL)
290                 devc->terminal = TERMINAL_FRONT;
291         else
292                 devc->terminal = TERMINAL_REAR;
293
294         /* 50Hz / 60Hz */
295         if ((status_byte & STATUS_50HZ) == STATUS_50HZ)
296                 devc->line = LINE_50HZ;
297         else
298                 devc->line = LINE_60HZ;
299
300         /* Auto-Zero */
301         if ((status_byte & STATUS_AUTO_ZERO) == STATUS_AUTO_ZERO)
302                 devc->auto_zero = TRUE;
303         else
304                 devc->auto_zero = FALSE;
305
306         /* Auto-Range */
307         if ((status_byte & STATUS_AUTO_RANGE) == STATUS_AUTO_RANGE) {
308                 devc->acquisition_mq_flags |= SR_MQFLAG_AUTORANGE;
309                 devc->range_exp = -99;
310         } else
311                 devc->acquisition_mq_flags &= ~SR_MQFLAG_AUTORANGE;
312
313         /* Internal trigger */
314         if ((status_byte & STATUS_INT_TRIGGER) == STATUS_INT_TRIGGER)
315                 devc->trigger = TRIGGER_INTERNAL;
316
317         return SR_OK;
318 }
319
320 static int parse_srq_byte(uint8_t sqr_byte)
321 {
322         (void)sqr_byte;
323
324 #if 0
325         /* The ServiceReQuest register isn't used at the moment. */
326
327         /* PON SRQ */
328         if ((sqr_byte & SRQ_POWER_ON) == SRQ_POWER_ON)
329                 sr_spew("Power On SRQ or clear msg received");
330
331         /* Cal failed SRQ */
332         if ((sqr_byte & SRQ_CAL_FAILED) == SRQ_CAL_FAILED)
333                 sr_spew("CAL failed SRQ");
334
335         /* Keyboard SRQ */
336         if ((sqr_byte & SRQ_KEYBORD) == SRQ_KEYBORD)
337                 sr_spew("Keyboard SRQ");
338
339         /* Hardware error SRQ */
340         if ((sqr_byte & SRQ_HARDWARE_ERR) == SRQ_HARDWARE_ERR)
341                 sr_spew("Hardware error SRQ");
342
343         /* Syntax error SRQ */
344         if ((sqr_byte & SRQ_SYNTAX_ERR) == SRQ_SYNTAX_ERR)
345                 sr_spew("Syntax error SRQ");
346
347         /* Every reading is available to the bus SRQ */
348         if ((sqr_byte & SRQ_BUS_AVAIL) == SRQ_BUS_AVAIL)
349                 sr_spew("Every reading is available to the bus SRQ");
350 #endif
351
352         return SR_OK;
353 }
354
355 static int parse_error_byte(uint8_t error_byte)
356 {
357         int ret;
358
359         ret = SR_OK;
360
361         /* A/D link */
362         if ((error_byte & ERROR_AD_LINK) == ERROR_AD_LINK) {
363                 sr_err("Failure in the A/D link");
364                 ret = SR_ERR;
365         }
366
367         /* A/D Self Test */
368         if ((error_byte & ERROR_AD_SELF_TEST) == ERROR_AD_SELF_TEST) {
369                 sr_err("A/D has failed its internal Self Test");
370                 ret = SR_ERR;
371         }
372
373         /* A/D slope error */
374         if ((error_byte & ERROR_AD_SLOPE) == ERROR_AD_SLOPE) {
375                 sr_err("There has been an A/D slope error");
376                 ret = SR_ERR;
377         }
378
379         /* ROM Selt Test */
380         if ((error_byte & ERROR_ROM_SELF_TEST) == ERROR_ROM_SELF_TEST) {
381                 sr_err("The ROM Self Test has failed");
382                 ret = SR_ERR;
383         }
384
385         /* RAM Selt Test */
386         if ((error_byte & ERROR_RAM_SELF_TEST) == ERROR_RAM_SELF_TEST) {
387                 sr_err("The RAM Self Test has failed");
388                 ret = SR_ERR;
389         }
390
391         /* Selt Test */
392         if ((error_byte & ERROR_SELF_TEST) == ERROR_SELF_TEST) {
393                 sr_err("Self Test: Any of the CAL RAM locations have bad "
394                        "checksums, or a range with a bad checksum is selected");
395                 ret = SR_ERR;
396         }
397
398         return ret;
399 }
400
401 SR_PRIV int hp_3478a_get_status_bytes(const struct sr_dev_inst *sdi)
402 {
403         int ret;
404         char *response;
405         uint8_t function_byte, status_byte, srq_byte, error_byte;
406         struct sr_scpi_dev_inst *scpi = sdi->conn;
407         struct dev_context *devc = sdi->priv;
408
409         ret = sr_scpi_get_string(scpi, "B", &response);
410         if (ret != SR_OK)
411                 return ret;
412
413         if (!response)
414                 return SR_ERR;
415
416         function_byte = (uint8_t)response[0];
417         status_byte = (uint8_t)response[1];
418         srq_byte = (uint8_t)response[2];
419         error_byte = (uint8_t)response[3];
420
421         g_free(response);
422
423         parse_function_byte(devc, function_byte);
424         parse_status_byte(devc, status_byte);
425         parse_srq_byte(srq_byte);
426         ret = parse_error_byte(error_byte);
427
428         return ret;
429 }
430
431 static void acq_send_measurement(struct sr_dev_inst *sdi)
432 {
433         struct sr_datafeed_packet packet;
434         struct sr_datafeed_analog analog;
435         struct sr_analog_encoding encoding;
436         struct sr_analog_meaning meaning;
437         struct sr_analog_spec spec;
438         struct dev_context *devc;
439         float f;
440
441         devc = sdi->priv;
442
443         packet.type = SR_DF_ANALOG;
444         packet.payload = &analog;
445
446         sr_analog_init(&analog, &encoding, &meaning, &spec, devc->enc_digits);
447
448         /* TODO: Implement NAN, depending on counts, range and value. */
449         f = devc->measurement;
450         analog.num_samples = 1;
451         analog.data = &f;
452
453         encoding.unitsize = sizeof(float);
454         encoding.is_float = TRUE;
455         encoding.digits = devc->enc_digits;
456
457         meaning.mq = devc->measurement_mq;
458         meaning.mqflags = devc->acquisition_mq_flags;
459         meaning.unit = devc->measurement_unit;
460         meaning.channels = sdi->channels;
461
462         spec.spec_digits = devc->spec_digits;
463
464         sr_session_send(sdi, &packet);
465 }
466
467 SR_PRIV int hp_3478a_receive_data(int fd, int revents, void *cb_data)
468 {
469         struct sr_scpi_dev_inst *scpi;
470         struct sr_dev_inst *sdi;
471         struct dev_context *devc;
472         char status_register;
473
474         (void)fd;
475         (void)revents;
476
477         if (!(sdi = cb_data) || !(devc = sdi->priv))
478                 return TRUE;
479
480         scpi = sdi->conn;
481
482         /*
483          * TODO: Wait for SRQ from the DMM when a new measurement is available.
484          *       For now, we don't wait for a SRQ, but just do a SPoll and
485          *       check the Data Ready bit (0x01).
486          *       This is necessary, because (1) reading a value will block the
487          *       bus until a measurement is available and (2) when switching
488          *       ranges, there could be a timeout.
489          */
490         if (sr_scpi_gpib_spoll(scpi, &status_register) != SR_OK)
491                 return FALSE;
492         if (!(((uint8_t)status_register) & 0x01))
493                 return TRUE;
494
495         /* Get a reading from the DMM. */
496         if (sr_scpi_get_double(scpi, NULL, &devc->measurement) != SR_OK)
497                 return FALSE;
498
499         /* Check for overflow. */
500         if (devc->measurement >= 9.998e+9)
501                 devc->measurement = INFINITY;
502
503         /*
504          * This is necessary to get the actual range for the encoding digits.
505          * Must be called after reading the value, because it resets the
506          * status register!
507          */
508         if (hp_3478a_get_status_bytes(sdi) != SR_OK)
509                 return FALSE;
510
511         acq_send_measurement(sdi);
512         sr_sw_limits_update_samples_read(&devc->limits, 1);
513
514         if (sr_sw_limits_check(&devc->limits))
515                 sr_dev_acquisition_stop(sdi);
516
517         return TRUE;
518 }