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