]> sigrok.org Git - libsigrok.git/blame - hardware/hameg-hmo/protocol.c
move function declarations to the appropriate header
[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",
53cd1c78 65 "DCL",
13f2b9d7
DJ
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
13f2b9d7
DJ
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) {
89280b1a 262 sr_info("State of analog channel %d -> %s : %s %.3eV %.3e offset", i + 1,
13f2b9d7
DJ
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
23f43dff 285static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
89280b1a 286 const char *command, const char *(*array)[], int *result)
13f2b9d7
DJ
287{
288 char *tmp;
289 unsigned int i;
290
23f43dff 291 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
89280b1a 292 g_free(tmp);
13f2b9d7
DJ
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
23f43dff 313static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
13f2b9d7
DJ
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
23f43dff 325 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
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
23f43dff 333 if (sr_scpi_get_float(scpi, command,
13f2b9d7
DJ
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
23f43dff 341 if (sr_scpi_get_float(scpi, command,
13f2b9d7
DJ
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
23f43dff 349 if (scope_state_get_array_option(scpi, command, config->coupling_options,
13f2b9d7
DJ
350 &state->analog_channels[i].coupling) != SR_OK)
351 return SR_ERR;
352 }
353
354 return SR_OK;
355}
356
23f43dff 357static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
13f2b9d7
DJ
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
23f43dff 369 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
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
23f43dff 379 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
380 &state->digital_pods[i]) != SR_OK)
381 return SR_ERR;
382 }
383
384 return SR_OK;
385}
386
719eff68 387SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
13f2b9d7
DJ
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
89280b1a
UH
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)
13f2b9d7
DJ
407 return SR_ERR;
408
89280b1a
UH
409 if (sr_scpi_get_float(sdi->conn,
410 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
411 &state->horiz_triggerpos) != SR_OK)
13f2b9d7
DJ
412 return SR_ERR;
413
89280b1a
UH
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)
13f2b9d7
DJ
417 return SR_ERR;
418
89280b1a
UH
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)
13f2b9d7
DJ
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,
89280b1a 437 sizeof(struct analog_channel_state))))
13f2b9d7
DJ
438 goto fail;
439
89280b1a
UH
440 if (!(state->digital_channels = g_try_malloc0_n(
441 config->digital_channels, sizeof(gboolean))))
13f2b9d7
DJ
442 goto fail;
443
444 if (!(state->digital_pods = g_try_malloc0_n(config->digital_pods,
89280b1a 445 sizeof(gboolean))))
13f2b9d7
DJ
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
719eff68 462SR_PRIV void hmo_scope_state_free(struct scope_state *state)
13f2b9d7
DJ
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;
89280b1a 474 unsigned int i, j;
13f2b9d7
DJ
475 struct sr_probe *probe;
476 struct dev_context *devc;
477
478 devc = sdi->priv;
479 model_index = -1;
480
89280b1a 481 /* Find the exact model. */
13f2b9d7
DJ
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) {
89280b1a 494 sr_dbg("Unsupported HMO device.");
13f2b9d7
DJ
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
89280b1a 506 /* Add analog channels. */
13f2b9d7
DJ
507 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
508 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
89280b1a 509 (*scope_models[model_index].analog_names)[i])))
13f2b9d7
DJ
510 return SR_ERR_MALLOC;
511 sdi->probes = g_slist_append(sdi->probes, probe);
512
89280b1a
UH
513 devc->analog_groups[i].name =
514 (char *)(*scope_models[model_index].analog_names)[i];
13f2b9d7
DJ
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
89280b1a 521 /* Add digital probe groups. */
13f2b9d7
DJ
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,
89280b1a 526 &devc->digital_groups[i < 8 ? 0 : 1]);
13f2b9d7
DJ
527 }
528
89280b1a 529 /* Add digital channels. */
13f2b9d7
DJ
530 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
531 if (!(probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE,
89280b1a 532 (*scope_models[model_index].digital_names)[i])))
13f2b9d7
DJ
533 return SR_ERR_MALLOC;
534 sdi->probes = g_slist_append(sdi->probes, probe);
535
89280b1a
UH
536 devc->digital_groups[i < 8 ? 0 : 1].probes = g_slist_append(
537 devc->digital_groups[i < 8 ? 0 : 1].probes, probe);
13f2b9d7
DJ
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
719eff68 549SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
06a3e78a 550{
13f2b9d7
DJ
551 struct sr_probe *probe;
552 struct sr_dev_inst *sdi;
06a3e78a 553 struct dev_context *devc;
13f2b9d7 554 struct sr_datafeed_packet packet;
89280b1a
UH
555 GArray *data;
556 struct sr_datafeed_analog analog;
557 struct sr_datafeed_logic logic;
06a3e78a
DJ
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) {
13f2b9d7
DJ
568 probe = devc->current_probe->data;
569
570 switch (probe->type) {
571 case SR_PROBE_ANALOG:
13f2b9d7
DJ
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);
89280b1a 593 break;
13f2b9d7 594 case SR_PROBE_LOGIC:
13f2b9d7
DJ
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);
89280b1a 611 break;
13f2b9d7 612 default:
89280b1a 613 sr_err("Invalid probe type.");
13f2b9d7
DJ
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 }
06a3e78a
DJ
631 }
632
633 return TRUE;
634}