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