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