]> sigrok.org Git - libsigrok.git/blame - 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
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
6ec6c43b 20#include <config.h>
650847e7
UH
21#include <math.h>
22#include <stdlib.h>
5a1afc09 23#include "scpi.h"
06a3e78a
DJ
24#include "protocol.h"
25
13f2b9d7
DJ
26static const char *hameg_scpi_dialect[] = {
27 [SCPI_CMD_GET_DIG_DATA] = ":POD%d:DATA?",
28 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
965b463d 29 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %s",
13f2b9d7
DJ
30 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
31 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
14a2f74d
DJ
32 [SCPI_CMD_GET_SAMPLE_RATE] = ":ACQ:SRAT?",
33 [SCPI_CMD_GET_SAMPLE_RATE_LIVE] = ":%s:DATA:POINTS?",
13f2b9d7
DJ
34 [SCPI_CMD_GET_ANALOG_DATA] = ":CHAN%d:DATA?",
35 [SCPI_CMD_GET_VERTICAL_DIV] = ":CHAN%d:SCAL?",
965b463d 36 [SCPI_CMD_SET_VERTICAL_DIV] = ":CHAN%d:SCAL %s",
13f2b9d7
DJ
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?",
422a1c0d 47 [SCPI_CMD_SET_HORIZ_TRIGGERPOS] = ":TIM:POS %s",
13f2b9d7
DJ
48 [SCPI_CMD_GET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT?",
49 [SCPI_CMD_SET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT %d",
50};
51
f254bc4b 52static const uint32_t hmo_devopts[] = {
13f2b9d7 53 SR_CONF_OSCILLOSCOPE,
a1b61e6e 54 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
5827f61b
BV
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,
bf622e6d 57 SR_CONF_NUM_HDIV | SR_CONF_GET,
5827f61b
BV
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,
13f2b9d7
DJ
61};
62
f254bc4b 63static const uint32_t hmo_analog_devopts[] = {
5827f61b
BV
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,
13f2b9d7
DJ
67};
68
69static const char *hmo_coupling_options[] = {
70 "AC",
71 "ACL",
72 "DC",
53cd1c78 73 "DCL",
13f2b9d7
DJ
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
ba7dd8bb 175static const char *scope_analog_channel_names[] = {
13f2b9d7
DJ
176 "CH1",
177 "CH2",
178 "CH3",
179 "CH4",
180};
181
ba7dd8bb 182static const char *scope_digital_channel_names[] = {
13f2b9d7
DJ
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
329733d9 201static const struct scope_config scope_models[] = {
13f2b9d7
DJ
202 {
203 .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
204 .analog_channels = 2,
205 .digital_channels = 8,
206 .digital_pods = 1,
207
ba7dd8bb
UH
208 .analog_names = &scope_analog_channel_names,
209 .digital_names = &scope_digital_channel_names,
13f2b9d7 210
f254bc4b
BV
211 .devopts = &hmo_devopts,
212 .num_devopts = ARRAY_SIZE(hmo_devopts),
13f2b9d7 213
f254bc4b
BV
214 .analog_devopts = &hmo_analog_devopts,
215 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
13f2b9d7
DJ
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
ba7dd8bb
UH
238 .analog_names = &scope_analog_channel_names,
239 .digital_names = &scope_digital_channel_names,
13f2b9d7 240
f254bc4b
BV
241 .devopts = &hmo_devopts,
242 .num_devopts = ARRAY_SIZE(hmo_devopts),
13f2b9d7 243
f254bc4b
BV
244 .analog_devopts = &hmo_analog_devopts,
245 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
13f2b9d7
DJ
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
329733d9 264static void scope_state_dump(const struct scope_config *config,
13f2b9d7
DJ
265 struct scope_state *state)
266{
267 unsigned int i;
8de2dc3b 268 char *tmp;
13f2b9d7 269
0a1f7b09 270 for (i = 0; i < config->analog_channels; i++) {
8de2dc3b
DJ
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",
13f2b9d7 275 (*config->coupling_options)[state->analog_channels[i].coupling],
8de2dc3b 276 tmp, state->analog_channels[i].vertical_offset);
13f2b9d7
DJ
277 }
278
0a1f7b09 279 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
280 sr_info("State of digital channel %d -> %s", i,
281 state->digital_channels[i] ? "On" : "Off");
282 }
283
0a1f7b09 284 for (i = 0; i < config->digital_pods; i++) {
13f2b9d7
DJ
285 sr_info("State of digital POD %d -> %s", i,
286 state->digital_pods[i] ? "On" : "Off");
287 }
288
8de2dc3b
DJ
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
14a2f74d
DJ
294 tmp = sr_samplerate_string(state->sample_rate);
295 sr_info("Current samplerate: %s", tmp);
296 g_free(tmp);
297
422a1c0d 298 sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
13f2b9d7
DJ
299 (*config->trigger_sources)[state->trigger_source],
300 (*config->trigger_slopes)[state->trigger_slope],
301 state->horiz_triggerpos);
302}
303
23f43dff 304static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
89280b1a 305 const char *command, const char *(*array)[], int *result)
13f2b9d7
DJ
306{
307 char *tmp;
308 unsigned int i;
309
23f43dff 310 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
89280b1a 311 g_free(tmp);
13f2b9d7
DJ
312 return SR_ERR;
313 }
314
0a1f7b09 315 for (i = 0; (*array)[i]; i++) {
13f2b9d7
DJ
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
8fff7519
SA
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],
650847e7 350 int array_len, unsigned int *result)
8fff7519
SA
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
23f43dff 394static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
329733d9 395 const struct scope_config *config,
13f2b9d7
DJ
396 struct scope_state *state)
397{
8de2dc3b 398 unsigned int i, j;
13f2b9d7 399 char command[MAX_COMMAND_SIZE];
8fff7519 400 char *tmp_str;
13f2b9d7 401
0a1f7b09 402 for (i = 0; i < config->analog_channels; i++) {
13f2b9d7
DJ
403 g_snprintf(command, sizeof(command),
404 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
405 i + 1);
406
23f43dff 407 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
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
8fff7519 415 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
8de2dc3b 416 return SR_ERR;
8fff7519
SA
417
418 if (array_float_get(tmp_str, hmo_vdivs, ARRAY_SIZE(hmo_vdivs),
419 &j) != SR_OK) {
420 g_free(tmp_str);
b4e31d2a 421 sr_err("Could not determine array index for vertical div scale.");
13f2b9d7 422 return SR_ERR;
b4e31d2a 423 }
13f2b9d7 424
8fff7519
SA
425 g_free(tmp_str);
426 state->analog_channels[i].vdiv = j;
427
13f2b9d7
DJ
428 g_snprintf(command, sizeof(command),
429 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
430 i + 1);
431
23f43dff 432 if (sr_scpi_get_float(scpi, command,
13f2b9d7
DJ
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
23f43dff 440 if (scope_state_get_array_option(scpi, command, config->coupling_options,
13f2b9d7
DJ
441 &state->analog_channels[i].coupling) != SR_OK)
442 return SR_ERR;
443 }
444
445 return SR_OK;
446}
447
23f43dff 448static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
329733d9 449 const struct scope_config *config,
13f2b9d7
DJ
450 struct scope_state *state)
451{
452 unsigned int i;
453 char command[MAX_COMMAND_SIZE];
454
0a1f7b09 455 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
456 g_snprintf(command, sizeof(command),
457 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
458 i);
459
23f43dff 460 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
461 &state->digital_channels[i]) != SR_OK)
462 return SR_ERR;
463 }
464
0a1f7b09 465 for (i = 0; i < config->digital_pods; i++) {
13f2b9d7
DJ
466 g_snprintf(command, sizeof(command),
467 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
468 i + 1);
469
23f43dff 470 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
471 &state->digital_pods[i]) != SR_OK)
472 return SR_ERR;
473 }
474
475 return SR_OK;
476}
477
14a2f74d
DJ
478SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi)
479{
480 struct dev_context *devc;
481 struct scope_state *state;
329733d9 482 const struct scope_config *config;
14a2f74d
DJ
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
0a1f7b09 496 for (i = 0; i < config->analog_channels; i++) {
14a2f74d
DJ
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) {
c06c24d2
DJ
523 if (sr_scpi_get_float(sdi->conn,
524 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE],
525 &tmp_float) != SR_OK)
14a2f74d 526 return SR_ERR;
c06c24d2 527
14a2f74d
DJ
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
719eff68 540SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
13f2b9d7
DJ
541{
542 struct dev_context *devc;
543 struct scope_state *state;
329733d9 544 const struct scope_config *config;
8de2dc3b
DJ
545 float tmp_float;
546 unsigned int i;
13f2b9d7
DJ
547
548 devc = sdi->priv;
549 config = devc->model_config;
550 state = devc->model_state;
551
8de2dc3b
DJ
552 sr_info("Fetching scope state");
553
13f2b9d7
DJ
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
89280b1a
UH
560 if (sr_scpi_get_float(sdi->conn,
561 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
8de2dc3b
DJ
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 }
b4e31d2a
SA
572 if (i == config->num_timebases) {
573 sr_err("Could not determine array index for time base.");
13f2b9d7 574 return SR_ERR;
b4e31d2a 575 }
13f2b9d7 576
89280b1a
UH
577 if (sr_scpi_get_float(sdi->conn,
578 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
422a1c0d 579 &tmp_float) != SR_OK)
13f2b9d7 580 return SR_ERR;
422a1c0d
DJ
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;
13f2b9d7 586
89280b1a
UH
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)
13f2b9d7
DJ
590 return SR_ERR;
591
89280b1a
UH
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)
13f2b9d7
DJ
595 return SR_ERR;
596
14a2f74d
DJ
597 if (hmo_update_sample_rate(sdi) != SR_OK)
598 return SR_ERR;
599
8de2dc3b
DJ
600 sr_info("Fetching finished.");
601
13f2b9d7
DJ
602 scope_state_dump(config, state);
603
604 return SR_OK;
605}
606
329733d9 607static struct scope_state *scope_state_new(const struct scope_config *config)
13f2b9d7
DJ
608{
609 struct scope_state *state;
610
a95f142e
UH
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));
13f2b9d7
DJ
618
619 return state;
13f2b9d7
DJ
620}
621
719eff68 622SR_PRIV void hmo_scope_state_free(struct scope_state *state)
13f2b9d7
DJ
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;
89280b1a 634 unsigned int i, j;
ba7dd8bb 635 struct sr_channel *ch;
13f2b9d7
DJ
636 struct dev_context *devc;
637
638 devc = sdi->priv;
639 model_index = -1;
640
89280b1a 641 /* Find the exact model. */
13f2b9d7
DJ
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) {
89280b1a 654 sr_dbg("Unsupported HMO device.");
13f2b9d7
DJ
655 return SR_ERR_NA;
656 }
657
562b7ae5
SA
658 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
659 scope_models[model_index].analog_channels);
13f2b9d7 660
562b7ae5
SA
661 devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
662 scope_models[model_index].digital_pods);
13f2b9d7 663
89280b1a 664 /* Add analog channels. */
13f2b9d7 665 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
5e23fcab 666 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
c368e6f3 667 (*scope_models[model_index].analog_names)[i]);
13f2b9d7 668
562b7ae5
SA
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);
13f2b9d7 674
660e398f 675 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 676 devc->analog_groups[i]);
13f2b9d7
DJ
677 }
678
660e398f 679 /* Add digital channel groups. */
0a1f7b09 680 for (i = 0; i < scope_models[model_index].digital_pods; i++) {
13f2b9d7 681 g_snprintf(tmp, 25, "POD%d", i);
562b7ae5
SA
682
683 devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
684
685 devc->digital_groups[i]->name = g_strdup(tmp);
660e398f 686 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 687 devc->digital_groups[i < 8 ? 0 : 1]);
13f2b9d7
DJ
688 }
689
89280b1a 690 /* Add digital channels. */
13f2b9d7 691 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
5e23fcab 692 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
c368e6f3 693 (*scope_models[model_index].digital_names)[i]);
13f2b9d7 694
562b7ae5
SA
695 devc->digital_groups[i < 8 ? 0 : 1]->channels = g_slist_append(
696 devc->digital_groups[i < 8 ? 0 : 1]->channels, ch);
13f2b9d7
DJ
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
719eff68 708SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
06a3e78a 709{
ba7dd8bb 710 struct sr_channel *ch;
13f2b9d7 711 struct sr_dev_inst *sdi;
06a3e78a 712 struct dev_context *devc;
13f2b9d7 713 struct sr_datafeed_packet packet;
89280b1a 714 GArray *data;
5faebab2 715 struct sr_datafeed_analog_old analog;
89280b1a 716 struct sr_datafeed_logic logic;
06a3e78a
DJ
717
718 (void)fd;
719
f62f595b
MK
720 data = NULL;
721
06a3e78a
DJ
722 if (!(sdi = cb_data))
723 return TRUE;
724
725 if (!(devc = sdi->priv))
726 return TRUE;
727
dc89faea
UH
728 if (revents != G_IO_IN)
729 return TRUE;
13f2b9d7 730
dc89faea 731 ch = devc->current_channel->data;
13f2b9d7 732
dc89faea
UH
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);
13f2b9d7 738
dc89faea 739 return TRUE;
13f2b9d7
DJ
740 }
741
dc89faea 742 packet.type = SR_DF_FRAME_BEGIN;
13f2b9d7
DJ
743 sr_session_send(sdi, &packet);
744
dc89faea
UH
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;
5faebab2 751 packet.type = SR_DF_ANALOG_OLD;
dc89faea
UH
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;
13f2b9d7 762 }
dc89faea
UH
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);
06a3e78a
DJ
792 }
793
794 return TRUE;
795}