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