]> sigrok.org Git - libsigrok.git/blame - src/hardware/hameg-hmo/protocol.c
hameg-hmo: Declare support for 2 pods / 16 channels on HMO2524 and above
[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 26static const char *hameg_scpi_dialect[] = {
401b83a1 27 [SCPI_CMD_GET_DIG_DATA] = ":FORM UINT,8;:POD%d:DATA?",
13f2b9d7 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?",
401b83a1 34 [SCPI_CMD_GET_ANALOG_DATA] = ":FORM REAL,32;:CHAN%d:DATA?",
13f2b9d7 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",
448e81b1 50 [SCPI_CMD_GET_PROBE_UNIT] = ":PROB%d:SET:ATT:UNIT?",
13f2b9d7
DJ
51};
52
f254bc4b 53static const uint32_t hmo_devopts[] = {
13f2b9d7 54 SR_CONF_OSCILLOSCOPE,
a1b61e6e 55 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
5827f61b
BV
56 SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
57 SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
bf622e6d 58 SR_CONF_NUM_HDIV | SR_CONF_GET,
5827f61b
BV
59 SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
60 SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
61 SR_CONF_SAMPLERATE | SR_CONF_GET,
13f2b9d7
DJ
62};
63
f254bc4b 64static const uint32_t hmo_analog_devopts[] = {
5827f61b
BV
65 SR_CONF_NUM_VDIV | SR_CONF_GET,
66 SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
67 SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
13f2b9d7
DJ
68};
69
70static const char *hmo_coupling_options[] = {
b05ab7d2
SB
71 "AC", // AC with 50 Ohm termination (152x, 202x, 30xx, 1202)
72 "ACL", // AC with 1 MOhm termination
73 "DC", // DC with 50 Ohm termination
74 "DCL", // DC with 1 MOhm termination
13f2b9d7
DJ
75 "GND",
76 NULL,
77};
78
79static const char *scope_trigger_slopes[] = {
80 "POS",
81 "NEG",
356f64f8 82 "EITH",
13f2b9d7
DJ
83 NULL,
84};
85
86static const char *hmo_compact2_trigger_sources[] = {
87 "CH1",
88 "CH2",
89 "LINE",
90 "EXT",
510aa828
SB
91 "PATT",
92 "BUS1",
93 "BUS2",
13f2b9d7
DJ
94 "D0",
95 "D1",
96 "D2",
97 "D3",
98 "D4",
99 "D5",
100 "D6",
101 "D7",
102 NULL,
103};
104
105static const char *hmo_compact4_trigger_sources[] = {
106 "CH1",
107 "CH2",
108 "CH3",
109 "CH4",
110 "LINE",
111 "EXT",
510aa828
SB
112 "PATT",
113 "BUS1",
114 "BUS2",
13f2b9d7
DJ
115 "D0",
116 "D1",
117 "D2",
118 "D3",
119 "D4",
120 "D5",
121 "D6",
122 "D7",
123 NULL,
124};
125
74413faf
GS
126static const char *hmo_compact4_dig16_trigger_sources[] = {
127 "CH1",
128 "CH2",
129 "CH3",
130 "CH4",
131 "LINE",
132 "EXT",
133 "PATT",
134 "BUS1",
135 "BUS2",
136 "D0",
137 "D1",
138 "D2",
139 "D3",
140 "D4",
141 "D5",
142 "D6",
143 "D7",
144 "D8",
145 "D9",
146 "D10",
147 "D11",
148 "D12",
149 "D13",
150 "D14",
151 "D15",
152 NULL,
153};
154
13f2b9d7
DJ
155static const uint64_t hmo_timebases[][2] = {
156 /* nanoseconds */
157 { 2, 1000000000 },
158 { 5, 1000000000 },
159 { 10, 1000000000 },
160 { 20, 1000000000 },
161 { 50, 1000000000 },
162 { 100, 1000000000 },
163 { 200, 1000000000 },
164 { 500, 1000000000 },
165 /* microseconds */
166 { 1, 1000000 },
167 { 2, 1000000 },
168 { 5, 1000000 },
169 { 10, 1000000 },
170 { 20, 1000000 },
171 { 50, 1000000 },
172 { 100, 1000000 },
173 { 200, 1000000 },
174 { 500, 1000000 },
175 /* milliseconds */
176 { 1, 1000 },
177 { 2, 1000 },
178 { 5, 1000 },
179 { 10, 1000 },
180 { 20, 1000 },
181 { 50, 1000 },
182 { 100, 1000 },
183 { 200, 1000 },
184 { 500, 1000 },
185 /* seconds */
186 { 1, 1 },
187 { 2, 1 },
188 { 5, 1 },
189 { 10, 1 },
190 { 20, 1 },
191 { 50, 1 },
192};
193
194static const uint64_t hmo_vdivs[][2] = {
195 /* millivolts */
196 { 1, 1000 },
197 { 2, 1000 },
198 { 5, 1000 },
199 { 10, 1000 },
200 { 20, 1000 },
201 { 50, 1000 },
202 { 100, 1000 },
203 { 200, 1000 },
204 { 500, 1000 },
205 /* volts */
206 { 1, 1 },
207 { 2, 1 },
208 { 5, 1 },
209 { 10, 1 },
fe227d17
SA
210 { 20, 1 },
211 { 50, 1 },
13f2b9d7
DJ
212};
213
ba7dd8bb 214static const char *scope_analog_channel_names[] = {
13f2b9d7
DJ
215 "CH1",
216 "CH2",
217 "CH3",
218 "CH4",
219};
220
ba7dd8bb 221static const char *scope_digital_channel_names[] = {
13f2b9d7
DJ
222 "D0",
223 "D1",
224 "D2",
225 "D3",
226 "D4",
227 "D5",
228 "D6",
229 "D7",
230 "D8",
231 "D9",
232 "D10",
233 "D11",
234 "D12",
235 "D13",
236 "D14",
237 "D15",
238};
239
329733d9 240static const struct scope_config scope_models[] = {
13f2b9d7 241 {
e786b194 242 /* HMO2522/3032/3042/3052 support 16 digital channels but they're not supported yet. */
da1726cc 243 .name = {"HMO1002", "HMO722", "HMO1022", "HMO1522", "HMO2022", "HMO2522",
e786b194 244 "HMO3032", "HMO3042", "HMO3052", NULL},
13f2b9d7
DJ
245 .analog_channels = 2,
246 .digital_channels = 8,
247 .digital_pods = 1,
248
ba7dd8bb
UH
249 .analog_names = &scope_analog_channel_names,
250 .digital_names = &scope_digital_channel_names,
13f2b9d7 251
f254bc4b
BV
252 .devopts = &hmo_devopts,
253 .num_devopts = ARRAY_SIZE(hmo_devopts),
13f2b9d7 254
f254bc4b
BV
255 .analog_devopts = &hmo_analog_devopts,
256 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
13f2b9d7
DJ
257
258 .coupling_options = &hmo_coupling_options,
259 .trigger_sources = &hmo_compact2_trigger_sources,
260 .trigger_slopes = &scope_trigger_slopes,
261
262 .timebases = &hmo_timebases,
263 .num_timebases = ARRAY_SIZE(hmo_timebases),
264
265 .vdivs = &hmo_vdivs,
266 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
267
268 .num_xdivs = 12,
269 .num_ydivs = 8,
270
271 .scpi_dialect = &hameg_scpi_dialect,
272 },
273 {
74413faf 274 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
13f2b9d7
DJ
275 .analog_channels = 4,
276 .digital_channels = 8,
277 .digital_pods = 1,
278
ba7dd8bb
UH
279 .analog_names = &scope_analog_channel_names,
280 .digital_names = &scope_digital_channel_names,
13f2b9d7 281
f254bc4b
BV
282 .devopts = &hmo_devopts,
283 .num_devopts = ARRAY_SIZE(hmo_devopts),
13f2b9d7 284
f254bc4b
BV
285 .analog_devopts = &hmo_analog_devopts,
286 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
13f2b9d7
DJ
287
288 .coupling_options = &hmo_coupling_options,
289 .trigger_sources = &hmo_compact4_trigger_sources,
290 .trigger_slopes = &scope_trigger_slopes,
291
292 .timebases = &hmo_timebases,
293 .num_timebases = ARRAY_SIZE(hmo_timebases),
294
295 .vdivs = &hmo_vdivs,
296 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
297
298 .num_xdivs = 12,
299 .num_ydivs = 8,
300
74413faf
GS
301 .scpi_dialect = &hameg_scpi_dialect,
302 },
303 {
304 .name = {"HMO2524", "HMO3034", "HMO3044", "HMO3054", NULL},
305 .analog_channels = 4,
306 .digital_channels = 16,
307 .digital_pods = 2,
308
309 .analog_names = &scope_analog_channel_names,
310 .digital_names = &scope_digital_channel_names,
311
312 .devopts = &hmo_devopts,
313 .num_devopts = ARRAY_SIZE(hmo_devopts),
314
315 .analog_devopts = &hmo_analog_devopts,
316 .num_analog_devopts = ARRAY_SIZE(hmo_analog_devopts),
317
318 .coupling_options = &hmo_coupling_options,
319 .trigger_sources = &hmo_compact4_dig16_trigger_sources,
320 .trigger_slopes = &scope_trigger_slopes,
321
322 .timebases = &hmo_timebases,
323 .num_timebases = ARRAY_SIZE(hmo_timebases),
324
325 .vdivs = &hmo_vdivs,
326 .num_vdivs = ARRAY_SIZE(hmo_vdivs),
327
328 .num_xdivs = 12,
329 .num_ydivs = 8,
330
13f2b9d7
DJ
331 .scpi_dialect = &hameg_scpi_dialect,
332 },
333};
334
329733d9 335static void scope_state_dump(const struct scope_config *config,
13f2b9d7
DJ
336 struct scope_state *state)
337{
338 unsigned int i;
8de2dc3b 339 char *tmp;
13f2b9d7 340
0a1f7b09 341 for (i = 0; i < config->analog_channels; i++) {
8de2dc3b
DJ
342 tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0],
343 (*config->vdivs)[state->analog_channels[i].vdiv][1]);
d9251a2c 344 sr_info("State of analog channel %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)",
8de2dc3b 345 i + 1, state->analog_channels[i].state ? "On" : "Off",
13f2b9d7 346 (*config->coupling_options)[state->analog_channels[i].coupling],
8de2dc3b 347 tmp, state->analog_channels[i].vertical_offset);
13f2b9d7
DJ
348 }
349
0a1f7b09 350 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
351 sr_info("State of digital channel %d -> %s", i,
352 state->digital_channels[i] ? "On" : "Off");
353 }
354
0a1f7b09 355 for (i = 0; i < config->digital_pods; i++) {
13f2b9d7
DJ
356 sr_info("State of digital POD %d -> %s", i,
357 state->digital_pods[i] ? "On" : "Off");
358 }
359
8de2dc3b
DJ
360 tmp = sr_period_string((*config->timebases)[state->timebase][0] *
361 (*config->timebases)[state->timebase][1]);
362 sr_info("Current timebase: %s", tmp);
363 g_free(tmp);
364
14a2f74d
DJ
365 tmp = sr_samplerate_string(state->sample_rate);
366 sr_info("Current samplerate: %s", tmp);
367 g_free(tmp);
368
422a1c0d 369 sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
13f2b9d7
DJ
370 (*config->trigger_sources)[state->trigger_source],
371 (*config->trigger_slopes)[state->trigger_slope],
372 state->horiz_triggerpos);
373}
374
23f43dff 375static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
89280b1a 376 const char *command, const char *(*array)[], int *result)
13f2b9d7
DJ
377{
378 char *tmp;
379 unsigned int i;
380
23f43dff 381 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) {
89280b1a 382 g_free(tmp);
13f2b9d7
DJ
383 return SR_ERR;
384 }
385
0a1f7b09 386 for (i = 0; (*array)[i]; i++) {
13f2b9d7
DJ
387 if (!g_strcmp0(tmp, (*array)[i])) {
388 *result = i;
389 g_free(tmp);
390 tmp = NULL;
391 break;
392 }
393 }
394
395 if (tmp) {
396 g_free(tmp);
397 return SR_ERR;
398 }
399
400 return SR_OK;
401}
402
8fff7519 403/**
a53acd7d
SB
404 * This function takes a value of the form "2.000E-03" and returns the index
405 * of an array where a matching pair was found.
8fff7519
SA
406 *
407 * @param value The string to be parsed.
408 * @param array The array of s/f pairs.
409 * @param array_len The number of pairs in the array.
410 * @param result The index at which a matching pair was found.
411 *
412 * @return SR_ERR on any parsing error, SR_OK otherwise.
413 */
414static int array_float_get(gchar *value, const uint64_t array[][2],
650847e7 415 int array_len, unsigned int *result)
8fff7519 416{
a53acd7d
SB
417 struct sr_rational rval;
418 struct sr_rational aval;
8cccbac8 419
a53acd7d 420 if (sr_parse_rational(value, &rval) != SR_OK)
8fff7519
SA
421 return SR_ERR;
422
a53acd7d
SB
423 for (int i = 0; i < array_len; i++) {
424 sr_rational_set(&aval, array[i][0], array[i][1]);
425 if (sr_rational_eq(&rval, &aval)) {
8fff7519
SA
426 *result = i;
427 return SR_OK;
428 }
429 }
430
431 return SR_ERR;
432}
433
23f43dff 434static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi,
329733d9 435 const struct scope_config *config,
13f2b9d7
DJ
436 struct scope_state *state)
437{
8de2dc3b 438 unsigned int i, j;
13f2b9d7 439 char command[MAX_COMMAND_SIZE];
8fff7519 440 char *tmp_str;
13f2b9d7 441
0a1f7b09 442 for (i = 0; i < config->analog_channels; i++) {
13f2b9d7
DJ
443 g_snprintf(command, sizeof(command),
444 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
445 i + 1);
446
23f43dff 447 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
448 &state->analog_channels[i].state) != SR_OK)
449 return SR_ERR;
450
451 g_snprintf(command, sizeof(command),
452 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV],
453 i + 1);
454
8fff7519 455 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
8de2dc3b 456 return SR_ERR;
8fff7519
SA
457
458 if (array_float_get(tmp_str, hmo_vdivs, ARRAY_SIZE(hmo_vdivs),
459 &j) != SR_OK) {
460 g_free(tmp_str);
b4e31d2a 461 sr_err("Could not determine array index for vertical div scale.");
13f2b9d7 462 return SR_ERR;
b4e31d2a 463 }
13f2b9d7 464
8fff7519
SA
465 g_free(tmp_str);
466 state->analog_channels[i].vdiv = j;
467
13f2b9d7
DJ
468 g_snprintf(command, sizeof(command),
469 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
470 i + 1);
471
23f43dff 472 if (sr_scpi_get_float(scpi, command,
13f2b9d7
DJ
473 &state->analog_channels[i].vertical_offset) != SR_OK)
474 return SR_ERR;
475
476 g_snprintf(command, sizeof(command),
477 (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
478 i + 1);
479
23f43dff 480 if (scope_state_get_array_option(scpi, command, config->coupling_options,
13f2b9d7
DJ
481 &state->analog_channels[i].coupling) != SR_OK)
482 return SR_ERR;
448e81b1
SB
483
484 g_snprintf(command, sizeof(command),
485 (*config->scpi_dialect)[SCPI_CMD_GET_PROBE_UNIT],
486 i + 1);
487
488 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
489 return SR_ERR;
490
491 if (tmp_str[0] == 'A')
492 state->analog_channels[i].probe_unit = 'A';
493 else
494 state->analog_channels[i].probe_unit = 'V';
495 g_free(tmp_str);
13f2b9d7
DJ
496 }
497
498 return SR_OK;
499}
500
23f43dff 501static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi,
329733d9 502 const struct scope_config *config,
13f2b9d7
DJ
503 struct scope_state *state)
504{
505 unsigned int i;
506 char command[MAX_COMMAND_SIZE];
507
0a1f7b09 508 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
509 g_snprintf(command, sizeof(command),
510 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
511 i);
512
23f43dff 513 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
514 &state->digital_channels[i]) != SR_OK)
515 return SR_ERR;
516 }
517
0a1f7b09 518 for (i = 0; i < config->digital_pods; i++) {
13f2b9d7
DJ
519 g_snprintf(command, sizeof(command),
520 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
521 i + 1);
522
23f43dff 523 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
524 &state->digital_pods[i]) != SR_OK)
525 return SR_ERR;
526 }
527
528 return SR_OK;
529}
530
14a2f74d
DJ
531SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi)
532{
533 struct dev_context *devc;
534 struct scope_state *state;
329733d9 535 const struct scope_config *config;
14a2f74d
DJ
536
537 int tmp;
538 unsigned int i;
539 float tmp_float;
540 gboolean channel_found;
541 char tmp_str[MAX_COMMAND_SIZE];
542 char chan_name[20];
543
544 devc = sdi->priv;
545 config = devc->model_config;
546 state = devc->model_state;
547 channel_found = FALSE;
548
0a1f7b09 549 for (i = 0; i < config->analog_channels; i++) {
14a2f74d
DJ
550 if (state->analog_channels[i].state) {
551 g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1);
552 g_snprintf(tmp_str, sizeof(tmp_str),
553 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
554 chan_name);
555 channel_found = TRUE;
556 break;
557 }
558 }
559
560 if (!channel_found) {
561 for (i = 0; i < config->digital_pods; i++) {
562 if (state->digital_pods[i]) {
563 g_snprintf(chan_name, sizeof(chan_name), "POD%d", i);
564 g_snprintf(tmp_str, sizeof(tmp_str),
565 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE],
566 chan_name);
567 channel_found = TRUE;
568 break;
569 }
570 }
571 }
572
573 /* No channel is active, ask the instrument for the sample rate
574 * in single shot mode */
575 if (!channel_found) {
c06c24d2
DJ
576 if (sr_scpi_get_float(sdi->conn,
577 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE],
578 &tmp_float) != SR_OK)
14a2f74d 579 return SR_ERR;
c06c24d2 580
14a2f74d
DJ
581 state->sample_rate = tmp_float;
582 } else {
583 if (sr_scpi_get_int(sdi->conn, tmp_str, &tmp) != SR_OK)
584 return SR_ERR;
585 state->sample_rate = tmp / (((float) (*config->timebases)[state->timebase][0] /
586 (*config->timebases)[state->timebase][1]) *
587 config->num_xdivs);
588 }
589
590 return SR_OK;
591}
592
719eff68 593SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
13f2b9d7
DJ
594{
595 struct dev_context *devc;
596 struct scope_state *state;
329733d9 597 const struct scope_config *config;
8de2dc3b
DJ
598 float tmp_float;
599 unsigned int i;
8cccbac8 600 char *tmp_str;
13f2b9d7
DJ
601
602 devc = sdi->priv;
603 config = devc->model_config;
604 state = devc->model_state;
605
8de2dc3b
DJ
606 sr_info("Fetching scope state");
607
13f2b9d7
DJ
608 if (analog_channel_state_get(sdi->conn, config, state) != SR_OK)
609 return SR_ERR;
610
611 if (digital_channel_state_get(sdi->conn, config, state) != SR_OK)
612 return SR_ERR;
613
89280b1a
UH
614 if (sr_scpi_get_float(sdi->conn,
615 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
8de2dc3b
DJ
616 &tmp_float) != SR_OK)
617 return SR_ERR;
618
8cccbac8
SA
619 if (sr_scpi_get_string(sdi->conn,
620 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
621 &tmp_str) != SR_OK)
622 return SR_ERR;
623
624 if (array_float_get(tmp_str, hmo_timebases, ARRAY_SIZE(hmo_timebases),
625 &i) != SR_OK) {
626 g_free(tmp_str);
b4e31d2a 627 sr_err("Could not determine array index for time base.");
13f2b9d7 628 return SR_ERR;
b4e31d2a 629 }
e5b7eef7 630 g_free(tmp_str);
13f2b9d7 631
8cccbac8
SA
632 state->timebase = i;
633
89280b1a
UH
634 if (sr_scpi_get_float(sdi->conn,
635 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
422a1c0d 636 &tmp_float) != SR_OK)
13f2b9d7 637 return SR_ERR;
422a1c0d
DJ
638 state->horiz_triggerpos = tmp_float /
639 (((double) (*config->timebases)[state->timebase][0] /
640 (*config->timebases)[state->timebase][1]) * config->num_xdivs);
641 state->horiz_triggerpos -= 0.5;
642 state->horiz_triggerpos *= -1;
13f2b9d7 643
89280b1a
UH
644 if (scope_state_get_array_option(sdi->conn,
645 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
646 config->trigger_sources, &state->trigger_source) != SR_OK)
13f2b9d7
DJ
647 return SR_ERR;
648
89280b1a
UH
649 if (scope_state_get_array_option(sdi->conn,
650 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
651 config->trigger_slopes, &state->trigger_slope) != SR_OK)
13f2b9d7
DJ
652 return SR_ERR;
653
14a2f74d
DJ
654 if (hmo_update_sample_rate(sdi) != SR_OK)
655 return SR_ERR;
656
8de2dc3b
DJ
657 sr_info("Fetching finished.");
658
13f2b9d7
DJ
659 scope_state_dump(config, state);
660
661 return SR_OK;
662}
663
329733d9 664static struct scope_state *scope_state_new(const struct scope_config *config)
13f2b9d7
DJ
665{
666 struct scope_state *state;
667
a95f142e
UH
668 state = g_malloc0(sizeof(struct scope_state));
669 state->analog_channels = g_malloc0_n(config->analog_channels,
670 sizeof(struct analog_channel_state));
671 state->digital_channels = g_malloc0_n(
672 config->digital_channels, sizeof(gboolean));
673 state->digital_pods = g_malloc0_n(config->digital_pods,
674 sizeof(gboolean));
13f2b9d7
DJ
675
676 return state;
13f2b9d7
DJ
677}
678
719eff68 679SR_PRIV void hmo_scope_state_free(struct scope_state *state)
13f2b9d7
DJ
680{
681 g_free(state->analog_channels);
682 g_free(state->digital_channels);
683 g_free(state->digital_pods);
684 g_free(state);
685}
686
687SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
688{
689 char tmp[25];
690 int model_index;
2d224dba 691 unsigned int i, j, group;
ba7dd8bb 692 struct sr_channel *ch;
13f2b9d7
DJ
693 struct dev_context *devc;
694
695 devc = sdi->priv;
696 model_index = -1;
697
89280b1a 698 /* Find the exact model. */
13f2b9d7
DJ
699 for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
700 for (j = 0; scope_models[i].name[j]; j++) {
701 if (!strcmp(sdi->model, scope_models[i].name[j])) {
702 model_index = i;
703 break;
704 }
705 }
706 if (model_index != -1)
707 break;
708 }
709
710 if (model_index == -1) {
89280b1a 711 sr_dbg("Unsupported HMO device.");
13f2b9d7
DJ
712 return SR_ERR_NA;
713 }
714
562b7ae5
SA
715 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
716 scope_models[model_index].analog_channels);
13f2b9d7 717
562b7ae5
SA
718 devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
719 scope_models[model_index].digital_pods);
13f2b9d7 720
89280b1a 721 /* Add analog channels. */
13f2b9d7 722 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
5e23fcab 723 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
c368e6f3 724 (*scope_models[model_index].analog_names)[i]);
13f2b9d7 725
562b7ae5
SA
726 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
727
728 devc->analog_groups[i]->name = g_strdup(
729 (char *)(*scope_models[model_index].analog_names)[i]);
730 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
13f2b9d7 731
660e398f 732 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 733 devc->analog_groups[i]);
13f2b9d7
DJ
734 }
735
660e398f 736 /* Add digital channel groups. */
0a1f7b09 737 for (i = 0; i < scope_models[model_index].digital_pods; i++) {
13f2b9d7 738 g_snprintf(tmp, 25, "POD%d", i);
562b7ae5
SA
739
740 devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
741
742 devc->digital_groups[i]->name = g_strdup(tmp);
660e398f 743 sdi->channel_groups = g_slist_append(sdi->channel_groups,
2d224dba 744 devc->digital_groups[i]);
13f2b9d7
DJ
745 }
746
89280b1a 747 /* Add digital channels. */
13f2b9d7 748 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
5e23fcab 749 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
c368e6f3 750 (*scope_models[model_index].digital_names)[i]);
13f2b9d7 751
2d224dba
GS
752 group = i / 8;
753 devc->digital_groups[group]->channels = g_slist_append(
754 devc->digital_groups[group]->channels, ch);
13f2b9d7
DJ
755 }
756
757 devc->model_config = &scope_models[model_index];
758 devc->frame_limit = 0;
759
760 if (!(devc->model_state = scope_state_new(devc->model_config)))
761 return SR_ERR_MALLOC;
762
763 return SR_OK;
764}
765
719eff68 766SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
06a3e78a 767{
ba7dd8bb 768 struct sr_channel *ch;
13f2b9d7 769 struct sr_dev_inst *sdi;
06a3e78a 770 struct dev_context *devc;
401b83a1 771 struct scope_state *state;
13f2b9d7 772 struct sr_datafeed_packet packet;
401b83a1
SB
773 GByteArray *data;
774 struct sr_datafeed_analog analog;
775 struct sr_analog_encoding encoding;
776 struct sr_analog_meaning meaning;
777 struct sr_analog_spec spec;
89280b1a 778 struct sr_datafeed_logic logic;
06a3e78a
DJ
779
780 (void)fd;
f0729866 781 (void)revents;
06a3e78a 782
f62f595b
MK
783 data = NULL;
784
06a3e78a
DJ
785 if (!(sdi = cb_data))
786 return TRUE;
787
788 if (!(devc = sdi->priv))
789 return TRUE;
790
f4f273ce
SB
791 /* Although this is correct in general, the USBTMC libusb implementation
792 * currently does not generate an event prior to the first read. Often
793 * it is ok to start reading just after the 50ms timeout. See bug #785.
dc89faea
UH
794 if (revents != G_IO_IN)
795 return TRUE;
f4f273ce 796 */
13f2b9d7 797
dc89faea 798 ch = devc->current_channel->data;
401b83a1 799 state = devc->model_state;
13f2b9d7 800
dc89faea
UH
801 switch (ch->type) {
802 case SR_CHANNEL_ANALOG:
401b83a1 803 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
dc89faea 804 if (data)
401b83a1 805 g_byte_array_free(data, TRUE);
13f2b9d7 806
dc89faea 807 return TRUE;
13f2b9d7
DJ
808 }
809
dc89faea 810 packet.type = SR_DF_FRAME_BEGIN;
13f2b9d7
DJ
811 sr_session_send(sdi, &packet);
812
401b83a1
SB
813 packet.type = SR_DF_ANALOG;
814
815 analog.data = data->data;
816 analog.num_samples = data->len / sizeof(float);
817 analog.encoding = &encoding;
818 analog.meaning = &meaning;
819 analog.spec = &spec;
820
821 encoding.unitsize = sizeof(float);
822 encoding.is_signed = TRUE;
823 encoding.is_float = TRUE;
824 encoding.is_bigendian = FALSE;
7dcaddd3
UH
825 /* TODO: Use proper 'digits' value for this device (and its modes). */
826 encoding.digits = 2;
401b83a1
SB
827 encoding.is_digits_decimal = FALSE;
828 encoding.scale.p = 1;
829 encoding.scale.q = 1;
830 encoding.offset.p = 0;
831 encoding.offset.q = 1;
832 if (state->analog_channels[ch->index].probe_unit == 'V') {
833 meaning.mq = SR_MQ_VOLTAGE;
834 meaning.unit = SR_UNIT_VOLT;
835 } else {
836 meaning.mq = SR_MQ_CURRENT;
837 meaning.unit = SR_UNIT_AMPERE;
838 }
839 meaning.mqflags = 0;
840 meaning.channels = g_slist_append(NULL, ch);
7dcaddd3
UH
841 /* TODO: Use proper 'digits' value for this device (and its modes). */
842 spec.spec_digits = 2;
dc89faea 843 packet.payload = &analog;
695dc859 844 sr_session_send(sdi, &packet);
401b83a1
SB
845 g_slist_free(meaning.channels);
846 g_byte_array_free(data, TRUE);
dc89faea
UH
847 data = NULL;
848 break;
849 case SR_CHANNEL_LOGIC:
401b83a1 850 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
dc89faea
UH
851 g_free(data);
852 return TRUE;
13f2b9d7 853 }
dc89faea
UH
854
855 packet.type = SR_DF_FRAME_BEGIN;
856 sr_session_send(sdi, &packet);
857
858 logic.length = data->len;
859 logic.unitsize = 1;
860 logic.data = data->data;
861 packet.type = SR_DF_LOGIC;
862 packet.payload = &logic;
695dc859 863 sr_session_send(sdi, &packet);
401b83a1 864 g_byte_array_free(data, TRUE);
dc89faea
UH
865 data = NULL;
866 break;
867 default:
868 sr_err("Invalid channel type.");
869 break;
870 }
871
872 packet.type = SR_DF_FRAME_END;
873 sr_session_send(sdi, &packet);
874
875 if (devc->current_channel->next) {
876 devc->current_channel = devc->current_channel->next;
877 hmo_request_data(sdi);
878 } else if (++devc->num_frames == devc->frame_limit) {
695dc859 879 sdi->driver->dev_acquisition_stop(sdi);
dc89faea
UH
880 } else {
881 devc->current_channel = devc->enabled_channels;
882 hmo_request_data(sdi);
06a3e78a
DJ
883 }
884
885 return TRUE;
886}