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