]> sigrok.org Git - libsigrok.git/blame_incremental - src/hardware/hameg-hmo/protocol.c
hameg-hmo: Replace floating point comparison for vdiv
[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 "scpi.h"
22#include "protocol.h"
23
24static const char *hameg_scpi_dialect[] = {
25 [SCPI_CMD_GET_DIG_DATA] = ":POD%d:DATA?",
26 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
27 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %s",
28 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
29 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
30 [SCPI_CMD_GET_SAMPLE_RATE] = ":ACQ:SRAT?",
31 [SCPI_CMD_GET_SAMPLE_RATE_LIVE] = ":%s:DATA:POINTS?",
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 %s",
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 %s",
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 uint32_t hmo_devopts[] = {
51 SR_CONF_OSCILLOSCOPE,
52 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
53 SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
54 SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
55 SR_CONF_NUM_HDIV | SR_CONF_GET,
56 SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
57 SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
58 SR_CONF_SAMPLERATE | SR_CONF_GET,
59};
60
61static const uint32_t hmo_analog_devopts[] = {
62 SR_CONF_NUM_VDIV | SR_CONF_GET,
63 SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
64 SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
65};
66
67static const char *hmo_coupling_options[] = {
68 "AC",
69 "ACL",
70 "DC",
71 "DCL",
72 "GND",
73 NULL,
74};
75
76static const char *scope_trigger_slopes[] = {
77 "POS",
78 "NEG",
79 NULL,
80};
81
82static const char *hmo_compact2_trigger_sources[] = {
83 "CH1",
84 "CH2",
85 "LINE",
86 "EXT",
87 "D0",
88 "D1",
89 "D2",
90 "D3",
91 "D4",
92 "D5",
93 "D6",
94 "D7",
95 NULL,
96};
97
98static const char *hmo_compact4_trigger_sources[] = {
99 "CH1",
100 "CH2",
101 "CH3",
102 "CH4",
103 "LINE",
104 "EXT",
105 "D0",
106 "D1",
107 "D2",
108 "D3",
109 "D4",
110 "D5",
111 "D6",
112 "D7",
113 NULL,
114};
115
116static const uint64_t hmo_timebases[][2] = {
117 /* nanoseconds */
118 { 2, 1000000000 },
119 { 5, 1000000000 },
120 { 10, 1000000000 },
121 { 20, 1000000000 },
122 { 50, 1000000000 },
123 { 100, 1000000000 },
124 { 200, 1000000000 },
125 { 500, 1000000000 },
126 /* microseconds */
127 { 1, 1000000 },
128 { 2, 1000000 },
129 { 5, 1000000 },
130 { 10, 1000000 },
131 { 20, 1000000 },
132 { 50, 1000000 },
133 { 100, 1000000 },
134 { 200, 1000000 },
135 { 500, 1000000 },
136 /* milliseconds */
137 { 1, 1000 },
138 { 2, 1000 },
139 { 5, 1000 },
140 { 10, 1000 },
141 { 20, 1000 },
142 { 50, 1000 },
143 { 100, 1000 },
144 { 200, 1000 },
145 { 500, 1000 },
146 /* seconds */
147 { 1, 1 },
148 { 2, 1 },
149 { 5, 1 },
150 { 10, 1 },
151 { 20, 1 },
152 { 50, 1 },
153};
154
155static const uint64_t hmo_vdivs[][2] = {
156 /* millivolts */
157 { 1, 1000 },
158 { 2, 1000 },
159 { 5, 1000 },
160 { 10, 1000 },
161 { 20, 1000 },
162 { 50, 1000 },
163 { 100, 1000 },
164 { 200, 1000 },
165 { 500, 1000 },
166 /* volts */
167 { 1, 1 },
168 { 2, 1 },
169 { 5, 1 },
170 { 10, 1 },
171};
172
173static const char *scope_analog_channel_names[] = {
174 "CH1",
175 "CH2",
176 "CH3",
177 "CH4",
178};
179
180static const char *scope_digital_channel_names[] = {
181 "D0",
182 "D1",
183 "D2",
184 "D3",
185 "D4",
186 "D5",
187 "D6",
188 "D7",
189 "D8",
190 "D9",
191 "D10",
192 "D11",
193 "D12",
194 "D13",
195 "D14",
196 "D15",
197};
198
199static const struct scope_config scope_models[] = {
200 {
201 .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
202 .analog_channels = 2,
203 .digital_channels = 8,
204 .digital_pods = 1,
205
206 .analog_names = &scope_analog_channel_names,
207 .digital_names = &scope_digital_channel_names,
208
209 .devopts = &hmo_devopts,
210 .num_devopts = ARRAY_SIZE(hmo_devopts),
211
212 .analog_devopts = &hmo_analog_devopts,
213 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
214
215 .coupling_options = &hmo_coupling_options,
216 .trigger_sources = &hmo_compact2_trigger_sources,
217 .trigger_slopes = &scope_trigger_slopes,
218
219 .timebases = &hmo_timebases,
220 .num_timebases = ARRAY_SIZE(hmo_timebases),
221
222 .vdivs = &hmo_vdivs,
223 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
224
225 .num_xdivs = 12,
226 .num_ydivs = 8,
227
228 .scpi_dialect = &hameg_scpi_dialect,
229 },
230 {
231 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
232 .analog_channels = 4,
233 .digital_channels = 8,
234 .digital_pods = 1,
235
236 .analog_names = &scope_analog_channel_names,
237 .digital_names = &scope_digital_channel_names,
238
239 .devopts = &hmo_devopts,
240 .num_devopts = ARRAY_SIZE(hmo_devopts),
241
242 .analog_devopts = &hmo_analog_devopts,
243 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
244
245 .coupling_options = &hmo_coupling_options,
246 .trigger_sources = &hmo_compact4_trigger_sources,
247 .trigger_slopes = &scope_trigger_slopes,
248
249 .timebases = &hmo_timebases,
250 .num_timebases = ARRAY_SIZE(hmo_timebases),
251
252 .vdivs = &hmo_vdivs,
253 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
254
255 .num_xdivs = 12,
256 .num_ydivs = 8,
257
258 .scpi_dialect = &hameg_scpi_dialect,
259 },
260};
261
262static void scope_state_dump(const struct scope_config *config,
263 struct scope_state *state)
264{
265 unsigned int i;
266 char *tmp;
267
268 for (i = 0; i < config->analog_channels; i++) {
269 tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0],
270 (*config->vdivs)[state->analog_channels[i].vdiv][1]);
271 sr_info("State of analog channel %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)",
272 i + 1, state->analog_channels[i].state ? "On" : "Off",
273 (*config->coupling_options)[state->analog_channels[i].coupling],
274 tmp, state->analog_channels[i].vertical_offset);
275 }
276
277 for (i = 0; i < config->digital_channels; i++) {
278 sr_info("State of digital channel %d -> %s", i,
279 state->digital_channels[i] ? "On" : "Off");
280 }
281
282 for (i = 0; i < config->digital_pods; i++) {
283 sr_info("State of digital POD %d -> %s", i,
284 state->digital_pods[i] ? "On" : "Off");
285 }
286
287 tmp = sr_period_string((*config->timebases)[state->timebase][0] *
288 (*config->timebases)[state->timebase][1]);
289 sr_info("Current timebase: %s", tmp);
290 g_free(tmp);
291
292 tmp = sr_samplerate_string(state->sample_rate);
293 sr_info("Current samplerate: %s", tmp);
294 g_free(tmp);
295
296 sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
297 (*config->trigger_sources)[state->trigger_source],
298 (*config->trigger_slopes)[state->trigger_slope],
299 state->horiz_triggerpos);
300}
301
302static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
303 const char *command, const char *(*array)[], int *result)
304{
305 char *tmp;
306 unsigned int i;
307
308 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
309 g_free(tmp);
310 return SR_ERR;
311 }
312
313 for (i = 0; (*array)[i]; i++) {
314 if (!g_strcmp0(tmp, (*array)[i])) {
315 *result = i;
316 g_free(tmp);
317 tmp = NULL;
318 break;
319 }
320 }
321
322 if (tmp) {
323 g_free(tmp);
324 return SR_ERR;
325 }
326
327 return SR_OK;
328}
329
330/**
331 * This function takes a value of the form "2.000E-03", converts it to a
332 * significand / factor pair and returns the index of an array where
333 * a matching pair was found.
334 *
335 * It's a bit convoluted because of floating-point issues. The value "10.00E-09"
336 * is parsed by g_ascii_strtod() as 0.000000009999999939, for example.
337 * Therefore it's easier to break the number up into two strings and handle
338 * them separately.
339 *
340 * @param value The string to be parsed.
341 * @param array The array of s/f pairs.
342 * @param array_len The number of pairs in the array.
343 * @param result The index at which a matching pair was found.
344 *
345 * @return SR_ERR on any parsing error, SR_OK otherwise.
346 */
347static int array_float_get(gchar *value, const uint64_t array[][2],
348 int array_len, int *result)
349{
350 int i;
351 uint64_t f;
352 float s;
353 unsigned int s_int;
354 gchar ss[10], es[10];
355
356 memset(ss, 0, sizeof(ss));
357 memset(es, 0, sizeof(es));
358
359 strncpy(ss, value, 5);
360 strncpy(es, &(value[6]), 3);
361
362 if (sr_atof_ascii(ss, &s) != SR_OK)
363 return SR_ERR;
364 if (sr_atoi(es, &i) != SR_OK)
365 return SR_ERR;
366
367 /* Transform e.g. 10^-03 to 1000 as the array stores the inverse. */
368 f = pow(10, abs(i));
369
370 /*
371 * Adjust the significand/factor pair to make sure
372 * that f is a multiple of 1000.
373 */
374 while ((int)fmod(log10(f), 3) > 0) {
375 s *= 10;
376 f *= 10;
377 }
378
379 /* Truncate s to circumvent rounding errors. */
380 s_int = (unsigned int)s;
381
382 for (i = 0; i < array_len; i++) {
383 if ((s_int == array[i][0]) && (f == array[i][1])) {
384 *result = i;
385 return SR_OK;
386 }
387 }
388
389 return SR_ERR;
390}
391
392static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
393 const struct scope_config *config,
394 struct scope_state *state)
395{
396 unsigned int i, j;
397 char command[MAX_COMMAND_SIZE];
398 char *tmp_str;
399
400 for (i = 0; i < config->analog_channels; i++) {
401 g_snprintf(command, sizeof(command),
402 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
403 i + 1);
404
405 if (sr_scpi_get_bool(scpi, command,
406 &state->analog_channels[i].state) != SR_OK)
407 return SR_ERR;
408
409 g_snprintf(command, sizeof(command),
410 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV],
411 i + 1);
412
413 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
414 return SR_ERR;
415
416 if (array_float_get(tmp_str, hmo_vdivs, ARRAY_SIZE(hmo_vdivs),
417 &j) != SR_OK) {
418 g_free(tmp_str);
419 sr_err("Could not determine array index for vertical div scale.");
420 return SR_ERR;
421 }
422
423 g_free(tmp_str);
424 state->analog_channels[i].vdiv = j;
425
426 g_snprintf(command, sizeof(command),
427 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
428 i + 1);
429
430 if (sr_scpi_get_float(scpi, command,
431 &state->analog_channels[i].vertical_offset) != SR_OK)
432 return SR_ERR;
433
434 g_snprintf(command, sizeof(command),
435 (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
436 i + 1);
437
438 if (scope_state_get_array_option(scpi, command, config->coupling_options,
439 &state->analog_channels[i].coupling) != SR_OK)
440 return SR_ERR;
441 }
442
443 return SR_OK;
444}
445
446static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
447 const struct scope_config *config,
448 struct scope_state *state)
449{
450 unsigned int i;
451 char command[MAX_COMMAND_SIZE];
452
453 for (i = 0; i < config->digital_channels; i++) {
454 g_snprintf(command, sizeof(command),
455 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
456 i);
457
458 if (sr_scpi_get_bool(scpi, command,
459 &state->digital_channels[i]) != SR_OK)
460 return SR_ERR;
461 }
462
463 for (i = 0; i < config->digital_pods; i++) {
464 g_snprintf(command, sizeof(command),
465 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
466 i + 1);
467
468 if (sr_scpi_get_bool(scpi, command,
469 &state->digital_pods[i]) != SR_OK)
470 return SR_ERR;
471 }
472
473 return SR_OK;
474}
475
476SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi)
477{
478 struct dev_context *devc;
479 struct scope_state *state;
480 const struct scope_config *config;
481
482 int tmp;
483 unsigned int i;
484 float tmp_float;
485 gboolean channel_found;
486 char tmp_str[MAX_COMMAND_SIZE];
487 char chan_name[20];
488
489 devc = sdi->priv;
490 config = devc->model_config;
491 state = devc->model_state;
492 channel_found = FALSE;
493
494 for (i = 0; i < config->analog_channels; i++) {
495 if (state->analog_channels[i].state) {
496 g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1);
497 g_snprintf(tmp_str, sizeof(tmp_str),
498 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
499 chan_name);
500 channel_found = TRUE;
501 break;
502 }
503 }
504
505 if (!channel_found) {
506 for (i = 0; i < config->digital_pods; i++) {
507 if (state->digital_pods[i]) {
508 g_snprintf(chan_name, sizeof(chan_name), "POD%d", i);
509 g_snprintf(tmp_str, sizeof(tmp_str),
510 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
511 chan_name);
512 channel_found = TRUE;
513 break;
514 }
515 }
516 }
517
518 /* No channel is active, ask the instrument for the sample rate
519 * in single shot mode */
520 if (!channel_found) {
521 if (sr_scpi_get_float(sdi->conn,
522 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE],
523 &tmp_float) != SR_OK)
524 return SR_ERR;
525
526 state->sample_rate = tmp_float;
527 } else {
528 if (sr_scpi_get_int(sdi->conn, tmp_str, &tmp) != SR_OK)
529 return SR_ERR;
530 state->sample_rate = tmp / (((float) (*config->timebases)[state->timebase][0] /
531 (*config->timebases)[state->timebase][1]) *
532 config->num_xdivs);
533 }
534
535 return SR_OK;
536}
537
538SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
539{
540 struct dev_context *devc;
541 struct scope_state *state;
542 const struct scope_config *config;
543 float tmp_float;
544 unsigned int i;
545
546 devc = sdi->priv;
547 config = devc->model_config;
548 state = devc->model_state;
549
550 sr_info("Fetching scope state");
551
552 if (analog_channel_state_get(sdi->conn, config, state) != SR_OK)
553 return SR_ERR;
554
555 if (digital_channel_state_get(sdi->conn, config, state) != SR_OK)
556 return SR_ERR;
557
558 if (sr_scpi_get_float(sdi->conn,
559 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
560 &tmp_float) != SR_OK)
561 return SR_ERR;
562
563 for (i = 0; i < config->num_timebases; i++) {
564 if (tmp_float == ((float) (*config->timebases)[i][0] /
565 (*config->timebases)[i][1])) {
566 state->timebase = i;
567 break;
568 }
569 }
570 if (i == config->num_timebases) {
571 sr_err("Could not determine array index for time base.");
572 return SR_ERR;
573 }
574
575 if (sr_scpi_get_float(sdi->conn,
576 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
577 &tmp_float) != SR_OK)
578 return SR_ERR;
579 state->horiz_triggerpos = tmp_float /
580 (((double) (*config->timebases)[state->timebase][0] /
581 (*config->timebases)[state->timebase][1]) * config->num_xdivs);
582 state->horiz_triggerpos -= 0.5;
583 state->horiz_triggerpos *= -1;
584
585 if (scope_state_get_array_option(sdi->conn,
586 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
587 config->trigger_sources, &state->trigger_source) != SR_OK)
588 return SR_ERR;
589
590 if (scope_state_get_array_option(sdi->conn,
591 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
592 config->trigger_slopes, &state->trigger_slope) != SR_OK)
593 return SR_ERR;
594
595 if (hmo_update_sample_rate(sdi) != SR_OK)
596 return SR_ERR;
597
598 sr_info("Fetching finished.");
599
600 scope_state_dump(config, state);
601
602 return SR_OK;
603}
604
605static struct scope_state *scope_state_new(const struct scope_config *config)
606{
607 struct scope_state *state;
608
609 state = g_malloc0(sizeof(struct scope_state));
610 state->analog_channels = g_malloc0_n(config->analog_channels,
611 sizeof(struct analog_channel_state));
612 state->digital_channels = g_malloc0_n(
613 config->digital_channels, sizeof(gboolean));
614 state->digital_pods = g_malloc0_n(config->digital_pods,
615 sizeof(gboolean));
616
617 return state;
618}
619
620SR_PRIV void hmo_scope_state_free(struct scope_state *state)
621{
622 g_free(state->analog_channels);
623 g_free(state->digital_channels);
624 g_free(state->digital_pods);
625 g_free(state);
626}
627
628SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
629{
630 char tmp[25];
631 int model_index;
632 unsigned int i, j;
633 struct sr_channel *ch;
634 struct dev_context *devc;
635
636 devc = sdi->priv;
637 model_index = -1;
638
639 /* Find the exact model. */
640 for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
641 for (j = 0; scope_models[i].name[j]; j++) {
642 if (!strcmp(sdi->model, scope_models[i].name[j])) {
643 model_index = i;
644 break;
645 }
646 }
647 if (model_index != -1)
648 break;
649 }
650
651 if (model_index == -1) {
652 sr_dbg("Unsupported HMO device.");
653 return SR_ERR_NA;
654 }
655
656 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
657 scope_models[model_index].analog_channels);
658
659 devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
660 scope_models[model_index].digital_pods);
661
662 /* Add analog channels. */
663 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
664 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
665 (*scope_models[model_index].analog_names)[i]);
666
667 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
668
669 devc->analog_groups[i]->name = g_strdup(
670 (char *)(*scope_models[model_index].analog_names)[i]);
671 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
672
673 sdi->channel_groups = g_slist_append(sdi->channel_groups,
674 devc->analog_groups[i]);
675 }
676
677 /* Add digital channel groups. */
678 for (i = 0; i < scope_models[model_index].digital_pods; i++) {
679 g_snprintf(tmp, 25, "POD%d", i);
680
681 devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
682
683 devc->digital_groups[i]->name = g_strdup(tmp);
684 sdi->channel_groups = g_slist_append(sdi->channel_groups,
685 devc->digital_groups[i < 8 ? 0 : 1]);
686 }
687
688 /* Add digital channels. */
689 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
690 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
691 (*scope_models[model_index].digital_names)[i]);
692
693 devc->digital_groups[i < 8 ? 0 : 1]->channels = g_slist_append(
694 devc->digital_groups[i < 8 ? 0 : 1]->channels, ch);
695 }
696
697 devc->model_config = &scope_models[model_index];
698 devc->frame_limit = 0;
699
700 if (!(devc->model_state = scope_state_new(devc->model_config)))
701 return SR_ERR_MALLOC;
702
703 return SR_OK;
704}
705
706SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
707{
708 struct sr_channel *ch;
709 struct sr_dev_inst *sdi;
710 struct dev_context *devc;
711 struct sr_datafeed_packet packet;
712 GArray *data;
713 struct sr_datafeed_analog_old analog;
714 struct sr_datafeed_logic logic;
715
716 (void)fd;
717
718 data = NULL;
719
720 if (!(sdi = cb_data))
721 return TRUE;
722
723 if (!(devc = sdi->priv))
724 return TRUE;
725
726 if (revents != G_IO_IN)
727 return TRUE;
728
729 ch = devc->current_channel->data;
730
731 switch (ch->type) {
732 case SR_CHANNEL_ANALOG:
733 if (sr_scpi_get_floatv(sdi->conn, NULL, &data) != SR_OK) {
734 if (data)
735 g_array_free(data, TRUE);
736
737 return TRUE;
738 }
739
740 packet.type = SR_DF_FRAME_BEGIN;
741 sr_session_send(sdi, &packet);
742
743 analog.channels = g_slist_append(NULL, ch);
744 analog.num_samples = data->len;
745 analog.data = (float *) data->data;
746 analog.mq = SR_MQ_VOLTAGE;
747 analog.unit = SR_UNIT_VOLT;
748 analog.mqflags = 0;
749 packet.type = SR_DF_ANALOG_OLD;
750 packet.payload = &analog;
751 sr_session_send(cb_data, &packet);
752 g_slist_free(analog.channels);
753 g_array_free(data, TRUE);
754 data = NULL;
755 break;
756 case SR_CHANNEL_LOGIC:
757 if (sr_scpi_get_uint8v(sdi->conn, NULL, &data) != SR_OK) {
758 g_free(data);
759 return TRUE;
760 }
761
762 packet.type = SR_DF_FRAME_BEGIN;
763 sr_session_send(sdi, &packet);
764
765 logic.length = data->len;
766 logic.unitsize = 1;
767 logic.data = data->data;
768 packet.type = SR_DF_LOGIC;
769 packet.payload = &logic;
770 sr_session_send(cb_data, &packet);
771 g_array_free(data, TRUE);
772 data = NULL;
773 break;
774 default:
775 sr_err("Invalid channel type.");
776 break;
777 }
778
779 packet.type = SR_DF_FRAME_END;
780 sr_session_send(sdi, &packet);
781
782 if (devc->current_channel->next) {
783 devc->current_channel = devc->current_channel->next;
784 hmo_request_data(sdi);
785 } else if (++devc->num_frames == devc->frame_limit) {
786 sdi->driver->dev_acquisition_stop(sdi, cb_data);
787 } else {
788 devc->current_channel = devc->enabled_channels;
789 hmo_request_data(sdi);
790 }
791
792 return TRUE;
793}