]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/hameg-hmo/protocol.c
uni-t-dmm: Fix incorrect order which breaks UT61B/C.
[libsigrok.git] / hardware / hameg-hmo / protocol.c
... / ...
CommitLineData
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2013 poljar (Damir Jelić) <poljarinho@gmail.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 "protocol.h"
21
22static const char *hameg_scpi_dialect[] = {
23 [SCPI_CMD_GET_DIG_DATA] = ":POD%d:DATA?",
24 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
25 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %E",
26 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
27 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
28 [SCPI_CMD_GET_ANALOG_DATA] = ":CHAN%d:DATA?",
29 [SCPI_CMD_GET_VERTICAL_DIV] = ":CHAN%d:SCAL?",
30 [SCPI_CMD_SET_VERTICAL_DIV] = ":CHAN%d:SCAL %E",
31 [SCPI_CMD_GET_DIG_POD_STATE] = ":POD%d:STAT?",
32 [SCPI_CMD_SET_DIG_POD_STATE] = ":POD%d:STAT %d",
33 [SCPI_CMD_GET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP?",
34 [SCPI_CMD_SET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP %s",
35 [SCPI_CMD_GET_TRIGGER_SOURCE] = ":TRIG:A:SOUR?",
36 [SCPI_CMD_SET_TRIGGER_SOURCE] = ":TRIG:A:SOUR %s",
37 [SCPI_CMD_GET_DIG_CHAN_STATE] = ":LOG%d:STAT?",
38 [SCPI_CMD_SET_DIG_CHAN_STATE] = ":LOG%d:STAT %d",
39 [SCPI_CMD_GET_VERTICAL_OFFSET] = ":CHAN%d:POS?",
40 [SCPI_CMD_GET_HORIZ_TRIGGERPOS] = ":TIM:POS?",
41 [SCPI_CMD_SET_HORIZ_TRIGGERPOS] = ":TIM:POS %E",
42 [SCPI_CMD_GET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT?",
43 [SCPI_CMD_SET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT %d",
44};
45
46static const int32_t hmo_hwcaps[] = {
47 SR_CONF_OSCILLOSCOPE,
48 SR_CONF_TRIGGER_SOURCE,
49 SR_CONF_TIMEBASE,
50 SR_CONF_NUM_TIMEBASE,
51 SR_CONF_TRIGGER_SLOPE,
52 SR_CONF_HORIZ_TRIGGERPOS,
53};
54
55static const int32_t hmo_analog_caps[] = {
56 SR_CONF_NUM_VDIV,
57 SR_CONF_COUPLING,
58 SR_CONF_VDIV,
59};
60
61static const char *hmo_coupling_options[] = {
62 "AC",
63 "ACL",
64 "DC",
65 "DCL",
66 "GND",
67 NULL,
68};
69
70static const char *scope_trigger_slopes[] = {
71 "POS",
72 "NEG",
73 NULL,
74};
75
76static const char *hmo_compact2_trigger_sources[] = {
77 "CH1",
78 "CH2",
79 "LINE",
80 "EXT",
81 "D0",
82 "D1",
83 "D2",
84 "D3",
85 "D4",
86 "D5",
87 "D6",
88 "D7",
89 NULL,
90};
91
92static const char *hmo_compact4_trigger_sources[] = {
93 "CH1",
94 "CH2",
95 "CH3",
96 "CH4",
97 "LINE",
98 "EXT",
99 "D0",
100 "D1",
101 "D2",
102 "D3",
103 "D4",
104 "D5",
105 "D6",
106 "D7",
107 NULL,
108};
109
110static const uint64_t hmo_timebases[][2] = {
111 /* nanoseconds */
112 { 2, 1000000000 },
113 { 5, 1000000000 },
114 { 10, 1000000000 },
115 { 20, 1000000000 },
116 { 50, 1000000000 },
117 { 100, 1000000000 },
118 { 200, 1000000000 },
119 { 500, 1000000000 },
120 /* microseconds */
121 { 1, 1000000 },
122 { 2, 1000000 },
123 { 5, 1000000 },
124 { 10, 1000000 },
125 { 20, 1000000 },
126 { 50, 1000000 },
127 { 100, 1000000 },
128 { 200, 1000000 },
129 { 500, 1000000 },
130 /* milliseconds */
131 { 1, 1000 },
132 { 2, 1000 },
133 { 5, 1000 },
134 { 10, 1000 },
135 { 20, 1000 },
136 { 50, 1000 },
137 { 100, 1000 },
138 { 200, 1000 },
139 { 500, 1000 },
140 /* seconds */
141 { 1, 1 },
142 { 2, 1 },
143 { 5, 1 },
144 { 10, 1 },
145 { 20, 1 },
146 { 50, 1 },
147};
148
149static const uint64_t hmo_vdivs[][2] = {
150 /* millivolts */
151 { 1, 1000 },
152 { 2, 1000 },
153 { 5, 1000 },
154 { 10, 1000 },
155 { 20, 1000 },
156 { 50, 1000 },
157 { 100, 1000 },
158 { 200, 1000 },
159 { 500, 1000 },
160 /* volts */
161 { 1, 1 },
162 { 2, 1 },
163 { 5, 1 },
164 { 10, 1 },
165};
166
167static const char *scope_analog_probe_names[] = {
168 "CH1",
169 "CH2",
170 "CH3",
171 "CH4",
172};
173
174static const char *scope_digital_probe_names[] = {
175 "D0",
176 "D1",
177 "D2",
178 "D3",
179 "D4",
180 "D5",
181 "D6",
182 "D7",
183 "D8",
184 "D9",
185 "D10",
186 "D11",
187 "D12",
188 "D13",
189 "D14",
190 "D15",
191};
192
193static struct scope_config scope_models[] = {
194 {
195 .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
196 .analog_channels = 2,
197 .digital_channels = 8,
198 .digital_pods = 1,
199
200 .analog_names = &scope_analog_probe_names,
201 .digital_names = &scope_digital_probe_names,
202
203 .hw_caps = &hmo_hwcaps,
204 .num_hwcaps = ARRAY_SIZE(hmo_hwcaps),
205
206 .analog_hwcaps = &hmo_analog_caps,
207 .num_analog_hwcaps = ARRAY_SIZE(hmo_analog_caps),
208
209 .coupling_options = &hmo_coupling_options,
210 .trigger_sources = &hmo_compact2_trigger_sources,
211 .trigger_slopes = &scope_trigger_slopes,
212
213 .timebases = &hmo_timebases,
214 .num_timebases = ARRAY_SIZE(hmo_timebases),
215
216 .vdivs = &hmo_vdivs,
217 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
218
219 .num_xdivs = 12,
220 .num_ydivs = 8,
221
222 .scpi_dialect = &hameg_scpi_dialect,
223 },
224 {
225 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
226 .analog_channels = 4,
227 .digital_channels = 8,
228 .digital_pods = 1,
229
230 .analog_names = &scope_analog_probe_names,
231 .digital_names = &scope_digital_probe_names,
232
233 .hw_caps = &hmo_hwcaps,
234 .num_hwcaps = ARRAY_SIZE(hmo_hwcaps),
235
236 .analog_hwcaps = &hmo_analog_caps,
237 .num_analog_hwcaps = ARRAY_SIZE(hmo_analog_caps),
238
239 .coupling_options = &hmo_coupling_options,
240 .trigger_sources = &hmo_compact4_trigger_sources,
241 .trigger_slopes = &scope_trigger_slopes,
242
243 .timebases = &hmo_timebases,
244 .num_timebases = ARRAY_SIZE(hmo_timebases),
245
246 .vdivs = &hmo_vdivs,
247 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
248
249 .num_xdivs = 12,
250 .num_ydivs = 8,
251
252 .scpi_dialect = &hameg_scpi_dialect,
253 },
254};
255
256static void scope_state_dump(struct scope_config *config,
257 struct scope_state *state)
258{
259 unsigned int i;
260
261 for (i = 0; i < config->analog_channels; ++i) {
262 sr_info("State of analog channel %d -> %s : %s %.3eV %.3e offset", i + 1,
263 state->analog_channels[i].state ? "On" : "Off",
264 (*config->coupling_options)[state->analog_channels[i].coupling],
265 state->analog_channels[i].vdiv, state->analog_channels[i].vertical_offset);
266 }
267
268 for (i = 0; i < config->digital_channels; ++i) {
269 sr_info("State of digital channel %d -> %s", i,
270 state->digital_channels[i] ? "On" : "Off");
271 }
272
273 for (i = 0; i < config->digital_pods; ++i) {
274 sr_info("State of digital POD %d -> %s", i,
275 state->digital_pods[i] ? "On" : "Off");
276 }
277
278 sr_info("Current timebase: %.2es", state->timebase);
279 sr_info("Current trigger: %s (source), %s (slope) %.2e (offset)",
280 (*config->trigger_sources)[state->trigger_source],
281 (*config->trigger_slopes)[state->trigger_slope],
282 state->horiz_triggerpos);
283}
284
285static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
286 const char *command, const char *(*array)[], int *result)
287{
288 char *tmp;
289 unsigned int i;
290
291 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
292 g_free(tmp);
293 return SR_ERR;
294 }
295
296 for (i = 0; (*array)[i]; ++i) {
297 if (!g_strcmp0(tmp, (*array)[i])) {
298 *result = i;
299 g_free(tmp);
300 tmp = NULL;
301 break;
302 }
303 }
304
305 if (tmp) {
306 g_free(tmp);
307 return SR_ERR;
308 }
309
310 return SR_OK;
311}
312
313static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
314 struct scope_config *config,
315 struct scope_state *state)
316{
317 unsigned int i;
318 char command[MAX_COMMAND_SIZE];
319
320 for (i = 0; i < config->analog_channels; ++i) {
321 g_snprintf(command, sizeof(command),
322 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
323 i + 1);
324
325 if (sr_scpi_get_bool(scpi, command,
326 &state->analog_channels[i].state) != SR_OK)
327 return SR_ERR;
328
329 g_snprintf(command, sizeof(command),
330 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV],
331 i + 1);
332
333 if (sr_scpi_get_float(scpi, command,
334 &state->analog_channels[i].vdiv) != SR_OK)
335 return SR_ERR;
336
337 g_snprintf(command, sizeof(command),
338 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
339 i + 1);
340
341 if (sr_scpi_get_float(scpi, command,
342 &state->analog_channels[i].vertical_offset) != SR_OK)
343 return SR_ERR;
344
345 g_snprintf(command, sizeof(command),
346 (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
347 i + 1);
348
349 if (scope_state_get_array_option(scpi, command, config->coupling_options,
350 &state->analog_channels[i].coupling) != SR_OK)
351 return SR_ERR;
352 }
353
354 return SR_OK;
355}
356
357static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
358 struct scope_config *config,
359 struct scope_state *state)
360{
361 unsigned int i;
362 char command[MAX_COMMAND_SIZE];
363
364 for (i = 0; i < config->digital_channels; ++i) {
365 g_snprintf(command, sizeof(command),
366 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
367 i);
368
369 if (sr_scpi_get_bool(scpi, command,
370 &state->digital_channels[i]) != SR_OK)
371 return SR_ERR;
372 }
373
374 for (i = 0; i < config->digital_pods; ++i) {
375 g_snprintf(command, sizeof(command),
376 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
377 i + 1);
378
379 if (sr_scpi_get_bool(scpi, command,
380 &state->digital_pods[i]) != SR_OK)
381 return SR_ERR;
382 }
383
384 return SR_OK;
385}
386
387SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
388{
389 struct dev_context *devc;
390 struct scope_state *state;
391 struct scope_config *config;
392
393 devc = sdi->priv;
394 config = devc->model_config;
395 state = devc->model_state;
396
397 if (analog_channel_state_get(sdi->conn, config, state) != SR_OK)
398 return SR_ERR;
399
400 if (digital_channel_state_get(sdi->conn, config, state) != SR_OK)
401 return SR_ERR;
402
403 /* TODO: Check if value is sensible. */
404 if (sr_scpi_get_float(sdi->conn,
405 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
406 &state->timebase) != SR_OK)
407 return SR_ERR;
408
409 if (sr_scpi_get_float(sdi->conn,
410 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
411 &state->horiz_triggerpos) != SR_OK)
412 return SR_ERR;
413
414 if (scope_state_get_array_option(sdi->conn,
415 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
416 config->trigger_sources, &state->trigger_source) != SR_OK)
417 return SR_ERR;
418
419 if (scope_state_get_array_option(sdi->conn,
420 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
421 config->trigger_slopes, &state->trigger_slope) != SR_OK)
422 return SR_ERR;
423
424 scope_state_dump(config, state);
425
426 return SR_OK;
427}
428
429SR_PRIV struct scope_state *scope_state_new(struct scope_config *config)
430{
431 struct scope_state *state;
432
433 if (!(state = g_try_malloc0(sizeof(struct scope_state))))
434 return NULL;
435
436 if (!(state->analog_channels = g_try_malloc0_n(config->analog_channels,
437 sizeof(struct analog_channel_state))))
438 goto fail;
439
440 if (!(state->digital_channels = g_try_malloc0_n(
441 config->digital_channels, sizeof(gboolean))))
442 goto fail;
443
444 if (!(state->digital_pods = g_try_malloc0_n(config->digital_pods,
445 sizeof(gboolean))))
446 goto fail;
447
448 return state;
449
450fail:
451 if (state->analog_channels)
452 g_free(state->analog_channels);
453 if (state->digital_channels)
454 g_free(state->digital_channels);
455 if (state->digital_pods)
456 g_free(state->digital_pods);
457 g_free(state);
458
459 return NULL;
460}
461
462SR_PRIV void hmo_scope_state_free(struct scope_state *state)
463{
464 g_free(state->analog_channels);
465 g_free(state->digital_channels);
466 g_free(state->digital_pods);
467 g_free(state);
468}
469
470SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
471{
472 char tmp[25];
473 int model_index;
474 unsigned int i, j;
475 struct sr_probe *probe;
476 struct dev_context *devc;
477
478 devc = sdi->priv;
479 model_index = -1;
480
481 /* Find the exact model. */
482 for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
483 for (j = 0; scope_models[i].name[j]; j++) {
484 if (!strcmp(sdi->model, scope_models[i].name[j])) {
485 model_index = i;
486 break;
487 }
488 }
489 if (model_index != -1)
490 break;
491 }
492
493 if (model_index == -1) {
494 sr_dbg("Unsupported HMO device.");
495 return SR_ERR_NA;
496 }
497
498 if (!(devc->analog_groups = g_try_malloc0(sizeof(struct sr_probe_group) *
499 scope_models[model_index].analog_channels)))
500 return SR_ERR_MALLOC;
501
502 if (!(devc->digital_groups = g_try_malloc0(sizeof(struct sr_probe_group) *
503 scope_models[model_index].digital_pods)))
504 return SR_ERR_MALLOC;
505
506 /* Add analog channels. */
507 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
508 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
509 (*scope_models[model_index].analog_names)[i])))
510 return SR_ERR_MALLOC;
511 sdi->probes = g_slist_append(sdi->probes, probe);
512
513 devc->analog_groups[i].name =
514 (char *)(*scope_models[model_index].analog_names)[i];
515 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
516
517 sdi->probe_groups = g_slist_append(sdi->probe_groups,
518 &devc->analog_groups[i]);
519 }
520
521 /* Add digital probe groups. */
522 for (i = 0; i < scope_models[model_index].digital_pods; ++i) {
523 g_snprintf(tmp, 25, "POD%d", i);
524 devc->digital_groups[i].name = g_strdup(tmp);
525 sdi->probe_groups = g_slist_append(sdi->probe_groups,
526 &devc->digital_groups[i < 8 ? 0 : 1]);
527 }
528
529 /* Add digital channels. */
530 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
531 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
532 (*scope_models[model_index].digital_names)[i])))
533 return SR_ERR_MALLOC;
534 sdi->probes = g_slist_append(sdi->probes, probe);
535
536 devc->digital_groups[i < 8 ? 0 : 1].probes = g_slist_append(
537 devc->digital_groups[i < 8 ? 0 : 1].probes, probe);
538 }
539
540 devc->model_config = &scope_models[model_index];
541 devc->frame_limit = 0;
542
543 if (!(devc->model_state = scope_state_new(devc->model_config)))
544 return SR_ERR_MALLOC;
545
546 return SR_OK;
547}
548
549SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
550{
551 struct sr_probe *probe;
552 struct sr_dev_inst *sdi;
553 struct dev_context *devc;
554 struct sr_datafeed_packet packet;
555 GArray *data;
556 struct sr_datafeed_analog analog;
557 struct sr_datafeed_logic logic;
558
559 (void)fd;
560
561 if (!(sdi = cb_data))
562 return TRUE;
563
564 if (!(devc = sdi->priv))
565 return TRUE;
566
567 if (revents == G_IO_IN) {
568 probe = devc->current_probe->data;
569
570 switch (probe->type) {
571 case SR_PROBE_ANALOG:
572 if (sr_scpi_get_floatv(sdi->conn, NULL, &data) != SR_OK) {
573 if (data)
574 g_array_free(data, TRUE);
575
576 return TRUE;
577 }
578
579 packet.type = SR_DF_FRAME_BEGIN;
580 sr_session_send(sdi, &packet);
581
582 analog.probes = g_slist_append(NULL, probe);
583 analog.num_samples = data->len;
584 analog.data = (float *) data->data;
585 analog.mq = SR_MQ_VOLTAGE;
586 analog.unit = SR_UNIT_VOLT;
587 analog.mqflags = 0;
588 packet.type = SR_DF_ANALOG;
589 packet.payload = &analog;
590 sr_session_send(cb_data, &packet);
591 g_slist_free(analog.probes);
592 g_array_free(data, TRUE);
593 break;
594 case SR_PROBE_LOGIC:
595 if (sr_scpi_get_uint8v(sdi->conn, NULL, &data) != SR_OK) {
596 if (data)
597 g_free(data);
598 return TRUE;
599 }
600
601 packet.type = SR_DF_FRAME_BEGIN;
602 sr_session_send(sdi, &packet);
603
604 logic.length = data->len;
605 logic.unitsize = 1;
606 logic.data = data->data;
607 packet.type = SR_DF_LOGIC;
608 packet.payload = &logic;
609 sr_session_send(cb_data, &packet);
610 g_array_free(data, TRUE);
611 break;
612 default:
613 sr_err("Invalid probe type.");
614 break;
615 }
616
617 packet.type = SR_DF_FRAME_END;
618 sr_session_send(sdi, &packet);
619
620 if (devc->current_probe->next) {
621 devc->current_probe = devc->current_probe->next;
622 hmo_request_data(sdi);
623 } else if (++devc->num_frames == devc->frame_limit) {
624 packet.type = SR_DF_END;
625 sr_session_send(sdi, &packet);
626 sdi->driver->dev_acquisition_stop(sdi, cb_data);
627 } else {
628 devc->current_probe = devc->enabled_probes;
629 hmo_request_data(sdi);
630 }
631 }
632
633 return TRUE;
634}