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