]> sigrok.org Git - libsigrok.git/blame_incremental - src/hardware/hameg-hmo/protocol.c
hameg-hmo: Support BE format for SCPI sample downloads
[libsigrok.git] / src / 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 <config.h>
21#include <math.h>
22#include <stdlib.h>
23#include "scpi.h"
24#include "protocol.h"
25
26static const char *hameg_scpi_dialect[] = {
27 [SCPI_CMD_GET_DIG_DATA] = ":FORM UINT,8;:POD%d:DATA?",
28 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
29 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %s",
30 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
31 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
32 [SCPI_CMD_GET_SAMPLE_RATE] = ":ACQ:SRAT?",
33 [SCPI_CMD_GET_SAMPLE_RATE_LIVE] = ":%s:DATA:POINTS?",
34 [SCPI_CMD_GET_ANALOG_DATA] = ":FORM REAL,32;:CHAN%d:DATA?",
35 [SCPI_CMD_GET_VERTICAL_DIV] = ":CHAN%d:SCAL?",
36 [SCPI_CMD_SET_VERTICAL_DIV] = ":CHAN%d:SCAL %s",
37 [SCPI_CMD_GET_DIG_POD_STATE] = ":POD%d:STAT?",
38 [SCPI_CMD_SET_DIG_POD_STATE] = ":POD%d:STAT %d",
39 [SCPI_CMD_GET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP?",
40 [SCPI_CMD_SET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP %s",
41 [SCPI_CMD_GET_TRIGGER_SOURCE] = ":TRIG:A:SOUR?",
42 [SCPI_CMD_SET_TRIGGER_SOURCE] = ":TRIG:A:SOUR %s",
43 [SCPI_CMD_GET_DIG_CHAN_STATE] = ":LOG%d:STAT?",
44 [SCPI_CMD_SET_DIG_CHAN_STATE] = ":LOG%d:STAT %d",
45 [SCPI_CMD_GET_VERTICAL_OFFSET] = ":CHAN%d:POS?",
46 [SCPI_CMD_GET_HORIZ_TRIGGERPOS] = ":TIM:POS?",
47 [SCPI_CMD_SET_HORIZ_TRIGGERPOS] = ":TIM:POS %s",
48 [SCPI_CMD_GET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT?",
49 [SCPI_CMD_SET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT %d",
50 [SCPI_CMD_GET_PROBE_UNIT] = ":PROB%d:SET:ATT:UNIT?",
51 [SCPI_CMD_GET_BYTE_ORDER] = ":FORM:BORD?",
52};
53
54static const uint32_t hmo_devopts[] = {
55 SR_CONF_OSCILLOSCOPE,
56 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
57 SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
58 SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
59 SR_CONF_NUM_HDIV | SR_CONF_GET,
60 SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
61 SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
62 SR_CONF_SAMPLERATE | SR_CONF_GET,
63};
64
65static const uint32_t hmo_analog_devopts[] = {
66 SR_CONF_NUM_VDIV | SR_CONF_GET,
67 SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
68 SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
69};
70
71static const char *hmo_coupling_options[] = {
72 "AC", // AC with 50 Ohm termination (152x, 202x, 30xx, 1202)
73 "ACL", // AC with 1 MOhm termination
74 "DC", // DC with 50 Ohm termination
75 "DCL", // DC with 1 MOhm termination
76 "GND",
77 NULL,
78};
79
80static const char *scope_trigger_slopes[] = {
81 "POS",
82 "NEG",
83 "EITH",
84 NULL,
85};
86
87static const char *hmo_compact2_trigger_sources[] = {
88 "CH1",
89 "CH2",
90 "LINE",
91 "EXT",
92 "PATT",
93 "BUS1",
94 "BUS2",
95 "D0",
96 "D1",
97 "D2",
98 "D3",
99 "D4",
100 "D5",
101 "D6",
102 "D7",
103 NULL,
104};
105
106static const char *hmo_compact4_trigger_sources[] = {
107 "CH1",
108 "CH2",
109 "CH3",
110 "CH4",
111 "LINE",
112 "EXT",
113 "PATT",
114 "BUS1",
115 "BUS2",
116 "D0",
117 "D1",
118 "D2",
119 "D3",
120 "D4",
121 "D5",
122 "D6",
123 "D7",
124 NULL,
125};
126
127static const char *hmo_compact4_dig16_trigger_sources[] = {
128 "CH1",
129 "CH2",
130 "CH3",
131 "CH4",
132 "LINE",
133 "EXT",
134 "PATT",
135 "BUS1",
136 "BUS2",
137 "D0",
138 "D1",
139 "D2",
140 "D3",
141 "D4",
142 "D5",
143 "D6",
144 "D7",
145 "D8",
146 "D9",
147 "D10",
148 "D11",
149 "D12",
150 "D13",
151 "D14",
152 "D15",
153 NULL,
154};
155
156static const uint64_t hmo_timebases[][2] = {
157 /* nanoseconds */
158 { 2, 1000000000 },
159 { 5, 1000000000 },
160 { 10, 1000000000 },
161 { 20, 1000000000 },
162 { 50, 1000000000 },
163 { 100, 1000000000 },
164 { 200, 1000000000 },
165 { 500, 1000000000 },
166 /* microseconds */
167 { 1, 1000000 },
168 { 2, 1000000 },
169 { 5, 1000000 },
170 { 10, 1000000 },
171 { 20, 1000000 },
172 { 50, 1000000 },
173 { 100, 1000000 },
174 { 200, 1000000 },
175 { 500, 1000000 },
176 /* milliseconds */
177 { 1, 1000 },
178 { 2, 1000 },
179 { 5, 1000 },
180 { 10, 1000 },
181 { 20, 1000 },
182 { 50, 1000 },
183 { 100, 1000 },
184 { 200, 1000 },
185 { 500, 1000 },
186 /* seconds */
187 { 1, 1 },
188 { 2, 1 },
189 { 5, 1 },
190 { 10, 1 },
191 { 20, 1 },
192 { 50, 1 },
193};
194
195static const uint64_t hmo_vdivs[][2] = {
196 /* millivolts */
197 { 1, 1000 },
198 { 2, 1000 },
199 { 5, 1000 },
200 { 10, 1000 },
201 { 20, 1000 },
202 { 50, 1000 },
203 { 100, 1000 },
204 { 200, 1000 },
205 { 500, 1000 },
206 /* volts */
207 { 1, 1 },
208 { 2, 1 },
209 { 5, 1 },
210 { 10, 1 },
211 { 20, 1 },
212 { 50, 1 },
213};
214
215static const char *scope_analog_channel_names[] = {
216 "CH1",
217 "CH2",
218 "CH3",
219 "CH4",
220};
221
222static const char *scope_digital_channel_names[] = {
223 "D0",
224 "D1",
225 "D2",
226 "D3",
227 "D4",
228 "D5",
229 "D6",
230 "D7",
231 "D8",
232 "D9",
233 "D10",
234 "D11",
235 "D12",
236 "D13",
237 "D14",
238 "D15",
239};
240
241static const struct scope_config scope_models[] = {
242 {
243 /* HMO2522/3032/3042/3052 support 16 digital channels but they're not supported yet. */
244 .name = {"HMO1002", "HMO722", "HMO1022", "HMO1522", "HMO2022", "HMO2522",
245 "HMO3032", "HMO3042", "HMO3052", NULL},
246 .analog_channels = 2,
247 .digital_channels = 8,
248 .digital_pods = 1,
249
250 .analog_names = &scope_analog_channel_names,
251 .digital_names = &scope_digital_channel_names,
252
253 .devopts = &hmo_devopts,
254 .num_devopts = ARRAY_SIZE(hmo_devopts),
255
256 .analog_devopts = &hmo_analog_devopts,
257 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
258
259 .coupling_options = &hmo_coupling_options,
260 .trigger_sources = &hmo_compact2_trigger_sources,
261 .trigger_slopes = &scope_trigger_slopes,
262
263 .timebases = &hmo_timebases,
264 .num_timebases = ARRAY_SIZE(hmo_timebases),
265
266 .vdivs = &hmo_vdivs,
267 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
268
269 .num_xdivs = 12,
270 .num_ydivs = 8,
271
272 .scpi_dialect = &hameg_scpi_dialect,
273 },
274 {
275 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
276 .analog_channels = 4,
277 .digital_channels = 8,
278 .digital_pods = 1,
279
280 .analog_names = &scope_analog_channel_names,
281 .digital_names = &scope_digital_channel_names,
282
283 .devopts = &hmo_devopts,
284 .num_devopts = ARRAY_SIZE(hmo_devopts),
285
286 .analog_devopts = &hmo_analog_devopts,
287 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
288
289 .coupling_options = &hmo_coupling_options,
290 .trigger_sources = &hmo_compact4_trigger_sources,
291 .trigger_slopes = &scope_trigger_slopes,
292
293 .timebases = &hmo_timebases,
294 .num_timebases = ARRAY_SIZE(hmo_timebases),
295
296 .vdivs = &hmo_vdivs,
297 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
298
299 .num_xdivs = 12,
300 .num_ydivs = 8,
301
302 .scpi_dialect = &hameg_scpi_dialect,
303 },
304 {
305 .name = {"HMO2524", "HMO3034", "HMO3044", "HMO3054", NULL},
306 .analog_channels = 4,
307 .digital_channels = 16,
308 .digital_pods = 2,
309
310 .analog_names = &scope_analog_channel_names,
311 .digital_names = &scope_digital_channel_names,
312
313 .devopts = &hmo_devopts,
314 .num_devopts = ARRAY_SIZE(hmo_devopts),
315
316 .analog_devopts = &hmo_analog_devopts,
317 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
318
319 .coupling_options = &hmo_coupling_options,
320 .trigger_sources = &hmo_compact4_dig16_trigger_sources,
321 .trigger_slopes = &scope_trigger_slopes,
322
323 .timebases = &hmo_timebases,
324 .num_timebases = ARRAY_SIZE(hmo_timebases),
325
326 .vdivs = &hmo_vdivs,
327 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
328
329 .num_xdivs = 12,
330 .num_ydivs = 8,
331
332 .scpi_dialect = &hameg_scpi_dialect,
333 },
334};
335
336static void scope_state_dump(const struct scope_config *config,
337 struct scope_state *state)
338{
339 unsigned int i;
340 char *tmp;
341
342 for (i = 0; i < config->analog_channels; i++) {
343 tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0],
344 (*config->vdivs)[state->analog_channels[i].vdiv][1]);
345 sr_info("State of analog channel %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)",
346 i + 1, state->analog_channels[i].state ? "On" : "Off",
347 (*config->coupling_options)[state->analog_channels[i].coupling],
348 tmp, state->analog_channels[i].vertical_offset);
349 }
350
351 for (i = 0; i < config->digital_channels; i++) {
352 sr_info("State of digital channel %d -> %s", i,
353 state->digital_channels[i] ? "On" : "Off");
354 }
355
356 for (i = 0; i < config->digital_pods; i++) {
357 sr_info("State of digital POD %d -> %s", i,
358 state->digital_pods[i] ? "On" : "Off");
359 }
360
361 tmp = sr_period_string((*config->timebases)[state->timebase][0] *
362 (*config->timebases)[state->timebase][1]);
363 sr_info("Current timebase: %s", tmp);
364 g_free(tmp);
365
366 tmp = sr_samplerate_string(state->sample_rate);
367 sr_info("Current samplerate: %s", tmp);
368 g_free(tmp);
369
370 sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
371 (*config->trigger_sources)[state->trigger_source],
372 (*config->trigger_slopes)[state->trigger_slope],
373 state->horiz_triggerpos);
374}
375
376static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
377 const char *command, const char *(*array)[], int *result)
378{
379 char *tmp;
380 unsigned int i;
381
382 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
383 g_free(tmp);
384 return SR_ERR;
385 }
386
387 for (i = 0; (*array)[i]; i++) {
388 if (!g_strcmp0(tmp, (*array)[i])) {
389 *result = i;
390 g_free(tmp);
391 tmp = NULL;
392 break;
393 }
394 }
395
396 if (tmp) {
397 g_free(tmp);
398 return SR_ERR;
399 }
400
401 return SR_OK;
402}
403
404/**
405 * This function takes a value of the form "2.000E-03" and returns the index
406 * of an array where a matching pair was found.
407 *
408 * @param value The string to be parsed.
409 * @param array The array of s/f pairs.
410 * @param array_len The number of pairs in the array.
411 * @param result The index at which a matching pair was found.
412 *
413 * @return SR_ERR on any parsing error, SR_OK otherwise.
414 */
415static int array_float_get(gchar *value, const uint64_t array[][2],
416 int array_len, unsigned int *result)
417{
418 struct sr_rational rval;
419 struct sr_rational aval;
420
421 if (sr_parse_rational(value, &rval) != SR_OK)
422 return SR_ERR;
423
424 for (int i = 0; i < array_len; i++) {
425 sr_rational_set(&aval, array[i][0], array[i][1]);
426 if (sr_rational_eq(&rval, &aval)) {
427 *result = i;
428 return SR_OK;
429 }
430 }
431
432 return SR_ERR;
433}
434
435static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
436 const struct scope_config *config,
437 struct scope_state *state)
438{
439 unsigned int i, j;
440 char command[MAX_COMMAND_SIZE];
441 char *tmp_str;
442
443 for (i = 0; i < config->analog_channels; i++) {
444 g_snprintf(command, sizeof(command),
445 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
446 i + 1);
447
448 if (sr_scpi_get_bool(scpi, command,
449 &state->analog_channels[i].state) != SR_OK)
450 return SR_ERR;
451
452 g_snprintf(command, sizeof(command),
453 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV],
454 i + 1);
455
456 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
457 return SR_ERR;
458
459 if (array_float_get(tmp_str, hmo_vdivs, ARRAY_SIZE(hmo_vdivs),
460 &j) != SR_OK) {
461 g_free(tmp_str);
462 sr_err("Could not determine array index for vertical div scale.");
463 return SR_ERR;
464 }
465
466 g_free(tmp_str);
467 state->analog_channels[i].vdiv = j;
468
469 g_snprintf(command, sizeof(command),
470 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
471 i + 1);
472
473 if (sr_scpi_get_float(scpi, command,
474 &state->analog_channels[i].vertical_offset) != SR_OK)
475 return SR_ERR;
476
477 g_snprintf(command, sizeof(command),
478 (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
479 i + 1);
480
481 if (scope_state_get_array_option(scpi, command, config->coupling_options,
482 &state->analog_channels[i].coupling) != SR_OK)
483 return SR_ERR;
484
485 g_snprintf(command, sizeof(command),
486 (*config->scpi_dialect)[SCPI_CMD_GET_PROBE_UNIT],
487 i + 1);
488
489 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
490 return SR_ERR;
491
492 if (tmp_str[0] == 'A')
493 state->analog_channels[i].probe_unit = 'A';
494 else
495 state->analog_channels[i].probe_unit = 'V';
496 g_free(tmp_str);
497 }
498
499 /*
500 * Determine the byte order which will be used for data blocks.
501 * A ":FORM:BORD?" request will yield either an "MSBF" or "LSBF"
502 * response.
503 */
504 state->byteorder = '?';
505 if (sr_scpi_get_string(scpi,
506 (*config->scpi_dialect)[SCPI_CMD_GET_BYTE_ORDER],
507 &tmp_str) != SR_OK)
508 return SR_ERR;
509 if (tmp_str[0] == 'M')
510 state->byteorder = 'b';
511 else if (tmp_str[0] == 'L')
512 state->byteorder = 'l';
513 g_free(tmp_str);
514
515 return SR_OK;
516}
517
518static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
519 const struct scope_config *config,
520 struct scope_state *state)
521{
522 unsigned int i;
523 char command[MAX_COMMAND_SIZE];
524
525 for (i = 0; i < config->digital_channels; i++) {
526 g_snprintf(command, sizeof(command),
527 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
528 i);
529
530 if (sr_scpi_get_bool(scpi, command,
531 &state->digital_channels[i]) != SR_OK)
532 return SR_ERR;
533 }
534
535 for (i = 0; i < config->digital_pods; i++) {
536 g_snprintf(command, sizeof(command),
537 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
538 i + 1);
539
540 if (sr_scpi_get_bool(scpi, command,
541 &state->digital_pods[i]) != SR_OK)
542 return SR_ERR;
543 }
544
545 return SR_OK;
546}
547
548SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi)
549{
550 struct dev_context *devc;
551 struct scope_state *state;
552 const struct scope_config *config;
553
554 int tmp;
555 unsigned int i;
556 float tmp_float;
557 gboolean channel_found;
558 char tmp_str[MAX_COMMAND_SIZE];
559 char chan_name[20];
560
561 devc = sdi->priv;
562 config = devc->model_config;
563 state = devc->model_state;
564 channel_found = FALSE;
565
566 for (i = 0; i < config->analog_channels; i++) {
567 if (state->analog_channels[i].state) {
568 g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1);
569 g_snprintf(tmp_str, sizeof(tmp_str),
570 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
571 chan_name);
572 channel_found = TRUE;
573 break;
574 }
575 }
576
577 if (!channel_found) {
578 for (i = 0; i < config->digital_pods; i++) {
579 if (state->digital_pods[i]) {
580 g_snprintf(chan_name, sizeof(chan_name), "POD%d", i);
581 g_snprintf(tmp_str, sizeof(tmp_str),
582 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
583 chan_name);
584 channel_found = TRUE;
585 break;
586 }
587 }
588 }
589
590 /* No channel is active, ask the instrument for the sample rate
591 * in single shot mode */
592 if (!channel_found) {
593 if (sr_scpi_get_float(sdi->conn,
594 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE],
595 &tmp_float) != SR_OK)
596 return SR_ERR;
597
598 state->sample_rate = tmp_float;
599 } else {
600 if (sr_scpi_get_int(sdi->conn, tmp_str, &tmp) != SR_OK)
601 return SR_ERR;
602 state->sample_rate = tmp / (((float) (*config->timebases)[state->timebase][0] /
603 (*config->timebases)[state->timebase][1]) *
604 config->num_xdivs);
605 }
606
607 return SR_OK;
608}
609
610SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
611{
612 struct dev_context *devc;
613 struct scope_state *state;
614 const struct scope_config *config;
615 float tmp_float;
616 unsigned int i;
617 char *tmp_str;
618
619 devc = sdi->priv;
620 config = devc->model_config;
621 state = devc->model_state;
622
623 sr_info("Fetching scope state");
624
625 if (analog_channel_state_get(sdi->conn, config, state) != SR_OK)
626 return SR_ERR;
627
628 if (digital_channel_state_get(sdi->conn, config, state) != SR_OK)
629 return SR_ERR;
630
631 if (sr_scpi_get_float(sdi->conn,
632 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
633 &tmp_float) != SR_OK)
634 return SR_ERR;
635
636 if (sr_scpi_get_string(sdi->conn,
637 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
638 &tmp_str) != SR_OK)
639 return SR_ERR;
640
641 if (array_float_get(tmp_str, hmo_timebases, ARRAY_SIZE(hmo_timebases),
642 &i) != SR_OK) {
643 g_free(tmp_str);
644 sr_err("Could not determine array index for time base.");
645 return SR_ERR;
646 }
647 g_free(tmp_str);
648
649 state->timebase = i;
650
651 if (sr_scpi_get_float(sdi->conn,
652 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
653 &tmp_float) != SR_OK)
654 return SR_ERR;
655 state->horiz_triggerpos = tmp_float /
656 (((double) (*config->timebases)[state->timebase][0] /
657 (*config->timebases)[state->timebase][1]) * config->num_xdivs);
658 state->horiz_triggerpos -= 0.5;
659 state->horiz_triggerpos *= -1;
660
661 if (scope_state_get_array_option(sdi->conn,
662 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
663 config->trigger_sources, &state->trigger_source) != SR_OK)
664 return SR_ERR;
665
666 if (scope_state_get_array_option(sdi->conn,
667 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
668 config->trigger_slopes, &state->trigger_slope) != SR_OK)
669 return SR_ERR;
670
671 if (hmo_update_sample_rate(sdi) != SR_OK)
672 return SR_ERR;
673
674 sr_info("Fetching finished.");
675
676 scope_state_dump(config, state);
677
678 return SR_OK;
679}
680
681static struct scope_state *scope_state_new(const struct scope_config *config)
682{
683 struct scope_state *state;
684
685 state = g_malloc0(sizeof(struct scope_state));
686 state->analog_channels = g_malloc0_n(config->analog_channels,
687 sizeof(struct analog_channel_state));
688 state->digital_channels = g_malloc0_n(
689 config->digital_channels, sizeof(gboolean));
690 state->digital_pods = g_malloc0_n(config->digital_pods,
691 sizeof(gboolean));
692
693 return state;
694}
695
696SR_PRIV void hmo_scope_state_free(struct scope_state *state)
697{
698 g_free(state->analog_channels);
699 g_free(state->digital_channels);
700 g_free(state->digital_pods);
701 g_free(state);
702}
703
704SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
705{
706 char tmp[25];
707 int model_index;
708 unsigned int i, j, group;
709 struct sr_channel *ch;
710 struct dev_context *devc;
711
712 devc = sdi->priv;
713 model_index = -1;
714
715 /* Find the exact model. */
716 for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
717 for (j = 0; scope_models[i].name[j]; j++) {
718 if (!strcmp(sdi->model, scope_models[i].name[j])) {
719 model_index = i;
720 break;
721 }
722 }
723 if (model_index != -1)
724 break;
725 }
726
727 if (model_index == -1) {
728 sr_dbg("Unsupported HMO device.");
729 return SR_ERR_NA;
730 }
731
732 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
733 scope_models[model_index].analog_channels);
734
735 devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
736 scope_models[model_index].digital_pods);
737
738 /* Add analog channels. */
739 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
740 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
741 (*scope_models[model_index].analog_names)[i]);
742
743 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
744
745 devc->analog_groups[i]->name = g_strdup(
746 (char *)(*scope_models[model_index].analog_names)[i]);
747 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
748
749 sdi->channel_groups = g_slist_append(sdi->channel_groups,
750 devc->analog_groups[i]);
751 }
752
753 /* Add digital channel groups. */
754 for (i = 0; i < scope_models[model_index].digital_pods; i++) {
755 g_snprintf(tmp, 25, "POD%d", i);
756
757 devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
758
759 devc->digital_groups[i]->name = g_strdup(tmp);
760 sdi->channel_groups = g_slist_append(sdi->channel_groups,
761 devc->digital_groups[i]);
762 }
763
764 /* Add digital channels. */
765 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
766 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
767 (*scope_models[model_index].digital_names)[i]);
768
769 group = i / 8;
770 devc->digital_groups[group]->channels = g_slist_append(
771 devc->digital_groups[group]->channels, ch);
772 }
773
774 devc->model_config = &scope_models[model_index];
775 devc->frame_limit = 0;
776
777 if (!(devc->model_state = scope_state_new(devc->model_config)))
778 return SR_ERR_MALLOC;
779
780 return SR_OK;
781}
782
783SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
784{
785 struct sr_channel *ch;
786 struct sr_dev_inst *sdi;
787 struct dev_context *devc;
788 struct scope_state *state;
789 struct sr_datafeed_packet packet;
790 GByteArray *data;
791 struct sr_datafeed_analog analog;
792 struct sr_analog_encoding encoding;
793 struct sr_analog_meaning meaning;
794 struct sr_analog_spec spec;
795 struct sr_datafeed_logic logic;
796
797 (void)fd;
798 (void)revents;
799
800 data = NULL;
801
802 if (!(sdi = cb_data))
803 return TRUE;
804
805 if (!(devc = sdi->priv))
806 return TRUE;
807
808 /* Although this is correct in general, the USBTMC libusb implementation
809 * currently does not generate an event prior to the first read. Often
810 * it is ok to start reading just after the 50ms timeout. See bug #785.
811 if (revents != G_IO_IN)
812 return TRUE;
813 */
814
815 ch = devc->current_channel->data;
816 state = devc->model_state;
817
818 switch (ch->type) {
819 case SR_CHANNEL_ANALOG:
820 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
821 if (data)
822 g_byte_array_free(data, TRUE);
823
824 return TRUE;
825 }
826
827 packet.type = SR_DF_FRAME_BEGIN;
828 sr_session_send(sdi, &packet);
829
830 packet.type = SR_DF_ANALOG;
831
832 analog.data = data->data;
833 analog.num_samples = data->len / sizeof(float);
834 analog.encoding = &encoding;
835 analog.meaning = &meaning;
836 analog.spec = &spec;
837
838 encoding.unitsize = sizeof(float);
839 encoding.is_signed = TRUE;
840 encoding.is_float = TRUE;
841 /* Assume LE format when unknown for backwards compat. */
842 encoding.is_bigendian = (state->byteorder == 'b') ? TRUE : FALSE;
843 /* TODO: Use proper 'digits' value for this device (and its modes). */
844 encoding.digits = 2;
845 encoding.is_digits_decimal = FALSE;
846 encoding.scale.p = 1;
847 encoding.scale.q = 1;
848 encoding.offset.p = 0;
849 encoding.offset.q = 1;
850 if (state->analog_channels[ch->index].probe_unit == 'V') {
851 meaning.mq = SR_MQ_VOLTAGE;
852 meaning.unit = SR_UNIT_VOLT;
853 } else {
854 meaning.mq = SR_MQ_CURRENT;
855 meaning.unit = SR_UNIT_AMPERE;
856 }
857 meaning.mqflags = 0;
858 meaning.channels = g_slist_append(NULL, ch);
859 /* TODO: Use proper 'digits' value for this device (and its modes). */
860 spec.spec_digits = 2;
861 packet.payload = &analog;
862 sr_session_send(sdi, &packet);
863 g_slist_free(meaning.channels);
864 g_byte_array_free(data, TRUE);
865 data = NULL;
866 break;
867 case SR_CHANNEL_LOGIC:
868 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
869 g_free(data);
870 return TRUE;
871 }
872
873 packet.type = SR_DF_FRAME_BEGIN;
874 sr_session_send(sdi, &packet);
875
876 logic.length = data->len;
877 logic.unitsize = 1;
878 logic.data = data->data;
879 packet.type = SR_DF_LOGIC;
880 packet.payload = &logic;
881 sr_session_send(sdi, &packet);
882 g_byte_array_free(data, TRUE);
883 data = NULL;
884 break;
885 default:
886 sr_err("Invalid channel type.");
887 break;
888 }
889
890 packet.type = SR_DF_FRAME_END;
891 sr_session_send(sdi, &packet);
892
893 if (devc->current_channel->next) {
894 devc->current_channel = devc->current_channel->next;
895 hmo_request_data(sdi);
896 } else if (++devc->num_frames == devc->frame_limit) {
897 sdi->driver->dev_acquisition_stop(sdi);
898 } else {
899 devc->current_channel = devc->enabled_channels;
900 hmo_request_data(sdi);
901 }
902
903 return TRUE;
904}