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