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