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