]> sigrok.org Git - libsigrok.git/blame - src/hardware/hameg-hmo/protocol.c
hameg-hmo: Add SR_CONF_HIGH_RESOLUTION and SR_CONF_PEAK_DETECTION.
[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>
e131be0a 5 * Copyright (C) 2018 Guido Trentalancia <guido@trentalancia.com>
06a3e78a
DJ
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
6ec6c43b 21#include <config.h>
650847e7
UH
22#include <math.h>
23#include <stdlib.h>
5a1afc09 24#include "scpi.h"
06a3e78a
DJ
25#include "protocol.h"
26
e06875b2
GS
27SR_PRIV void hmo_queue_logic_data(struct dev_context *devc,
28 size_t group, GByteArray *pod_data);
29SR_PRIV void hmo_send_logic_packet(struct sr_dev_inst *sdi,
30 struct dev_context *devc);
31SR_PRIV void hmo_cleanup_logic_data(struct dev_context *devc);
32
13f2b9d7 33static const char *hameg_scpi_dialect[] = {
e131be0a
GT
34 [SCPI_CMD_GET_DIG_DATA] = ":FORM UINT,8;:POD%d:DATA?",
35 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
36 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %s",
29a9b1a0 37 [SCPI_CMD_GET_HORIZONTAL_DIV] = ":TIM:DIV?",
e131be0a
GT
38 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
39 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
40 [SCPI_CMD_GET_SAMPLE_RATE] = ":ACQ:SRAT?",
e131be0a
GT
41 [SCPI_CMD_GET_ANALOG_DATA] = ":FORM:BORD %s;" \
42 ":FORM REAL,32;:CHAN%d:DATA?",
66ddc22a
GT
43 [SCPI_CMD_GET_VERTICAL_SCALE] = ":CHAN%d:SCAL?",
44 [SCPI_CMD_SET_VERTICAL_SCALE] = ":CHAN%d:SCAL %s",
e131be0a
GT
45 [SCPI_CMD_GET_DIG_POD_STATE] = ":POD%d:STAT?",
46 [SCPI_CMD_SET_DIG_POD_STATE] = ":POD%d:STAT %d",
97a00074
GT
47 [SCPI_CMD_GET_TRIGGER_SOURCE] = ":TRIG:A:SOUR?",
48 [SCPI_CMD_SET_TRIGGER_SOURCE] = ":TRIG:A:SOUR %s",
e131be0a 49 [SCPI_CMD_GET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP?",
c8ecfa6e 50 [SCPI_CMD_SET_TRIGGER_SLOPE] = ":TRIG:A:TYPE EDGE;:TRIG:A:EDGE:SLOP %s",
4fa4db2c
GT
51 [SCPI_CMD_GET_TRIGGER_PATTERN] = ":TRIG:A:PATT:SOUR?",
52 [SCPI_CMD_SET_TRIGGER_PATTERN] = ":TRIG:A:TYPE LOGIC;" \
53 ":TRIG:A:PATT:FUNC AND;" \
0184aca1 54 ":TRIG:A:PATT:COND \"TRUE\";" \
4fa4db2c
GT
55 ":TRIG:A:PATT:MODE OFF;" \
56 ":TRIG:A:PATT:SOUR \"%s\"",
97a00074
GT
57 [SCPI_CMD_GET_HIGH_RESOLUTION] = ":ACQ:HRES?",
58 [SCPI_CMD_SET_HIGH_RESOLUTION] = ":ACQ:HRES %s",
59 [SCPI_CMD_GET_PEAK_DETECTION] = ":ACQ:PEAK?",
60 [SCPI_CMD_SET_PEAK_DETECTION] = ":ACQ:PEAK %s",
e131be0a
GT
61 [SCPI_CMD_GET_DIG_CHAN_STATE] = ":LOG%d:STAT?",
62 [SCPI_CMD_SET_DIG_CHAN_STATE] = ":LOG%d:STAT %d",
63 [SCPI_CMD_GET_VERTICAL_OFFSET] = ":CHAN%d:POS?",
64 [SCPI_CMD_GET_HORIZ_TRIGGERPOS] = ":TIM:POS?",
65 [SCPI_CMD_SET_HORIZ_TRIGGERPOS] = ":TIM:POS %s",
66 [SCPI_CMD_GET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT?",
67 [SCPI_CMD_SET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT %d",
68 [SCPI_CMD_GET_PROBE_UNIT] = ":PROB%d:SET:ATT:UNIT?",
69 [SCPI_CMD_GET_DIG_POD_THRESHOLD] = ":POD%d:THR?",
70 [SCPI_CMD_SET_DIG_POD_THRESHOLD] = ":POD%d:THR %s",
71 [SCPI_CMD_GET_DIG_POD_USER_THRESHOLD] = ":POD%d:THR:UDL%d?",
72 [SCPI_CMD_SET_DIG_POD_USER_THRESHOLD] = ":POD%d:THR:UDL%d %s",
13f2b9d7
DJ
73};
74
aac30633
GT
75static const char *rohde_schwarz_log_not_pod_scpi_dialect[] = {
76 [SCPI_CMD_GET_DIG_DATA] = ":FORM UINT,8;:LOG%d:DATA?",
77 [SCPI_CMD_GET_TIMEBASE] = ":TIM:SCAL?",
78 [SCPI_CMD_SET_TIMEBASE] = ":TIM:SCAL %s",
29a9b1a0 79 [SCPI_CMD_GET_HORIZONTAL_DIV] = ":TIM:DIV?",
aac30633
GT
80 [SCPI_CMD_GET_COUPLING] = ":CHAN%d:COUP?",
81 [SCPI_CMD_SET_COUPLING] = ":CHAN%d:COUP %s",
82 [SCPI_CMD_GET_SAMPLE_RATE] = ":ACQ:SRAT?",
83 [SCPI_CMD_GET_ANALOG_DATA] = ":FORM:BORD %s;" \
84 ":FORM REAL,32;:CHAN%d:DATA?",
66ddc22a
GT
85 [SCPI_CMD_GET_VERTICAL_SCALE] = ":CHAN%d:SCAL?",
86 [SCPI_CMD_SET_VERTICAL_SCALE] = ":CHAN%d:SCAL %s",
aac30633
GT
87 [SCPI_CMD_GET_DIG_POD_STATE] = ":LOG%d:STAT?",
88 [SCPI_CMD_SET_DIG_POD_STATE] = ":LOG%d:STAT %d",
97a00074
GT
89 [SCPI_CMD_GET_TRIGGER_SOURCE] = ":TRIG:A:SOUR?",
90 [SCPI_CMD_SET_TRIGGER_SOURCE] = ":TRIG:A:SOUR %s",
aac30633
GT
91 [SCPI_CMD_GET_TRIGGER_SLOPE] = ":TRIG:A:EDGE:SLOP?",
92 [SCPI_CMD_SET_TRIGGER_SLOPE] = ":TRIG:A:TYPE EDGE;:TRIG:A:EDGE:SLOP %s",
93 [SCPI_CMD_GET_TRIGGER_PATTERN] = ":TRIG:A:PATT:SOUR?",
94 [SCPI_CMD_SET_TRIGGER_PATTERN] = ":TRIG:A:TYPE LOGIC;" \
95 ":TRIG:A:PATT:FUNC AND;" \
0184aca1 96 ":TRIG:A:PATT:COND \"TRUE\";" \
aac30633
GT
97 ":TRIG:A:PATT:MODE OFF;" \
98 ":TRIG:A:PATT:SOUR \"%s\"",
97a00074
GT
99 [SCPI_CMD_GET_HIGH_RESOLUTION] = ":ACQ:HRES?",
100 [SCPI_CMD_SET_HIGH_RESOLUTION] = ":ACQ:HRES %s",
101 [SCPI_CMD_GET_PEAK_DETECTION] = ":ACQ:PEAK?",
102 [SCPI_CMD_SET_PEAK_DETECTION] = ":ACQ:PEAK %s",
aac30633
GT
103 [SCPI_CMD_GET_DIG_CHAN_STATE] = ":LOG%d:STAT?",
104 [SCPI_CMD_SET_DIG_CHAN_STATE] = ":LOG%d:STAT %d",
105 [SCPI_CMD_GET_VERTICAL_OFFSET] = ":CHAN%d:POS?", /* Might not be supported on RTB200x... */
106 [SCPI_CMD_GET_HORIZ_TRIGGERPOS] = ":TIM:POS?",
107 [SCPI_CMD_SET_HORIZ_TRIGGERPOS] = ":TIM:POS %s",
108 [SCPI_CMD_GET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT?",
109 [SCPI_CMD_SET_ANALOG_CHAN_STATE] = ":CHAN%d:STAT %d",
110 [SCPI_CMD_GET_PROBE_UNIT] = ":PROB%d:SET:ATT:UNIT?",
111 [SCPI_CMD_GET_DIG_POD_THRESHOLD] = ":DIG%d:TECH?",
112 [SCPI_CMD_SET_DIG_POD_THRESHOLD] = ":DIG%d:TECH %s",
113 [SCPI_CMD_GET_DIG_POD_USER_THRESHOLD] = ":DIG%d:THR?",
114 [SCPI_CMD_SET_DIG_POD_USER_THRESHOLD] = ":DIG%d:THR %s",
115};
116
4b25cbff 117static const uint32_t devopts[] = {
13f2b9d7 118 SR_CONF_OSCILLOSCOPE,
830e24b6
GT
119 SR_CONF_LIMIT_SAMPLES | SR_CONF_SET,
120 SR_CONF_LIMIT_FRAMES | SR_CONF_SET,
86621306 121 SR_CONF_SAMPLERATE | SR_CONF_GET,
5827f61b 122 SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
bf622e6d 123 SR_CONF_NUM_HDIV | SR_CONF_GET,
5827f61b 124 SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
86621306
UH
125 SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
126 SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
4fa4db2c 127 SR_CONF_TRIGGER_PATTERN | SR_CONF_GET | SR_CONF_SET,
97a00074
GT
128 SR_CONF_HIGH_RESOLUTION | SR_CONF_GET | SR_CONF_SET,
129 SR_CONF_PEAK_DETECTION | SR_CONF_GET | SR_CONF_SET,
13f2b9d7
DJ
130};
131
6b82c3e5 132static const uint32_t devopts_cg_analog[] = {
5827f61b 133 SR_CONF_NUM_VDIV | SR_CONF_GET,
5827f61b 134 SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
86621306 135 SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
13f2b9d7
DJ
136};
137
e131be0a
GT
138static const uint32_t devopts_cg_digital[] = {
139 SR_CONF_LOGIC_THRESHOLD | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
140 SR_CONF_LOGIC_THRESHOLD_CUSTOM | SR_CONF_GET | SR_CONF_SET,
141};
142
4b25cbff 143static const char *coupling_options[] = {
b05ab7d2
SB
144 "AC", // AC with 50 Ohm termination (152x, 202x, 30xx, 1202)
145 "ACL", // AC with 1 MOhm termination
146 "DC", // DC with 50 Ohm termination
147 "DCL", // DC with 1 MOhm termination
13f2b9d7 148 "GND",
13f2b9d7
DJ
149};
150
aac30633
GT
151static const char *coupling_options_rtb200x[] = {
152 "ACL", // AC with 1 MOhm termination
153 "DCL", // DC with 1 MOhm termination
154 "GND",
155};
156
157static const char *coupling_options_rtm300x[] = {
158 "ACL", // AC with 1 MOhm termination
159 "DC", // DC with 50 Ohm termination
160 "DCL", // DC with 1 MOhm termination
161 "GND",
162};
163
13f2b9d7
DJ
164static const char *scope_trigger_slopes[] = {
165 "POS",
166 "NEG",
356f64f8 167 "EITH",
13f2b9d7
DJ
168};
169
e131be0a
GT
170/* Predefined logic thresholds. */
171static const char *logic_threshold[] = {
172 "TTL",
173 "ECL",
174 "CMOS",
175 "USER1",
176 "USER2", // overwritten by logic_threshold_custom, use USER1 for permanent setting
177};
178
aac30633
GT
179static const char *logic_threshold_rtb200x_rtm300x[] = {
180 "TTL",
181 "ECL",
182 "CMOS",
183 "MAN", // overwritten by logic_threshold_custom
184};
185
4cf90b86 186/* RTC1002, HMO Compact2 and HMO1002/HMO1202 */
6d0f3508 187static const char *an2_dig8_trigger_sources[] = {
f8195cb2
UH
188 "CH1", "CH2",
189 "LINE", "EXT", "PATT", "BUS1", "BUS2",
190 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
13f2b9d7
DJ
191};
192
4cf90b86 193/* HMO3xx2 */
6d0f3508
GT
194static const char *an2_dig16_trigger_sources[] = {
195 "CH1", "CH2",
196 "LINE", "EXT", "PATT", "BUS1", "BUS2",
197 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
198 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
199};
200
aac30633
GT
201/* RTB2002 and RTM3002 */
202static const char *an2_dig16_sbus_trigger_sources[] = {
203 "CH1", "CH2",
204 "LINE", "EXT", "PATT", "SBUS1", "SBUS2",
205 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
206 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
207};
208
4cf90b86 209/* HMO Compact4 */
6d0f3508 210static const char *an4_dig8_trigger_sources[] = {
f8195cb2
UH
211 "CH1", "CH2", "CH3", "CH4",
212 "LINE", "EXT", "PATT", "BUS1", "BUS2",
213 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
13f2b9d7
DJ
214};
215
4cf90b86 216/* HMO3xx4 and HMO2524 */
6d0f3508 217static const char *an4_dig16_trigger_sources[] = {
f8195cb2
UH
218 "CH1", "CH2", "CH3", "CH4",
219 "LINE", "EXT", "PATT", "BUS1", "BUS2",
220 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
221 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
74413faf
GS
222};
223
b720f16e 224/* RTB2004, RTM3004 and RTA4004 */
aac30633
GT
225static const char *an4_dig16_sbus_trigger_sources[] = {
226 "CH1", "CH2", "CH3", "CH4",
227 "LINE", "EXT", "PATT", "SBUS1", "SBUS2",
228 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
229 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
230};
231
4b25cbff 232static const uint64_t timebases[][2] = {
a058de04
GT
233 /* nanoseconds */
234 { 1, 1000000000 },
235 { 2, 1000000000 },
236 { 5, 1000000000 },
237 { 10, 1000000000 },
238 { 20, 1000000000 },
239 { 50, 1000000000 },
240 { 100, 1000000000 },
241 { 200, 1000000000 },
242 { 500, 1000000000 },
243 /* microseconds */
244 { 1, 1000000 },
245 { 2, 1000000 },
246 { 5, 1000000 },
247 { 10, 1000000 },
248 { 20, 1000000 },
249 { 50, 1000000 },
250 { 100, 1000000 },
251 { 200, 1000000 },
252 { 500, 1000000 },
253 /* milliseconds */
254 { 1, 1000 },
255 { 2, 1000 },
256 { 5, 1000 },
257 { 10, 1000 },
258 { 20, 1000 },
259 { 50, 1000 },
260 { 100, 1000 },
261 { 200, 1000 },
262 { 500, 1000 },
263 /* seconds */
264 { 1, 1 },
265 { 2, 1 },
266 { 5, 1 },
267 { 10, 1 },
268 { 20, 1 },
269 { 50, 1 },
270};
271
272/* HMO Compact series (HMO722/724/1022/1024/1522/1524/2022/2024) do
273 * not support 1 ns timebase setting.
274 */
275static const uint64_t timebases_hmo_compact[][2] = {
13f2b9d7
DJ
276 /* nanoseconds */
277 { 2, 1000000000 },
278 { 5, 1000000000 },
279 { 10, 1000000000 },
280 { 20, 1000000000 },
281 { 50, 1000000000 },
282 { 100, 1000000000 },
283 { 200, 1000000000 },
284 { 500, 1000000000 },
285 /* microseconds */
286 { 1, 1000000 },
287 { 2, 1000000 },
288 { 5, 1000000 },
289 { 10, 1000000 },
290 { 20, 1000000 },
291 { 50, 1000000 },
292 { 100, 1000000 },
293 { 200, 1000000 },
294 { 500, 1000000 },
295 /* milliseconds */
296 { 1, 1000 },
297 { 2, 1000 },
298 { 5, 1000 },
299 { 10, 1000 },
300 { 20, 1000 },
301 { 50, 1000 },
302 { 100, 1000 },
303 { 200, 1000 },
304 { 500, 1000 },
305 /* seconds */
306 { 1, 1 },
307 { 2, 1 },
308 { 5, 1 },
309 { 10, 1 },
310 { 20, 1 },
311 { 50, 1 },
312};
313
4b25cbff 314static const uint64_t vdivs[][2] = {
13f2b9d7
DJ
315 /* millivolts */
316 { 1, 1000 },
317 { 2, 1000 },
318 { 5, 1000 },
319 { 10, 1000 },
320 { 20, 1000 },
321 { 50, 1000 },
322 { 100, 1000 },
323 { 200, 1000 },
324 { 500, 1000 },
325 /* volts */
326 { 1, 1 },
327 { 2, 1 },
328 { 5, 1 },
329 { 10, 1 },
330};
331
ba7dd8bb 332static const char *scope_analog_channel_names[] = {
f8195cb2 333 "CH1", "CH2", "CH3", "CH4",
13f2b9d7
DJ
334};
335
ba7dd8bb 336static const char *scope_digital_channel_names[] = {
f8195cb2
UH
337 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
338 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
13f2b9d7
DJ
339};
340
a12456f1 341static struct scope_config scope_models[] = {
13f2b9d7 342 {
a058de04
GT
343 /* HMO Compact2: HMO722/1022/1522/2022 support only 8 digital channels. */
344 .name = {"HMO722", "HMO1022", "HMO1522", "HMO2022", NULL},
345 .analog_channels = 2,
346 .digital_channels = 8,
347
348 .analog_names = &scope_analog_channel_names,
349 .digital_names = &scope_digital_channel_names,
350
351 .devopts = &devopts,
352 .num_devopts = ARRAY_SIZE(devopts),
353
354 .devopts_cg_analog = &devopts_cg_analog,
355 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
356
357 .devopts_cg_digital = &devopts_cg_digital,
358 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
359
360 .coupling_options = &coupling_options,
361 .num_coupling_options = ARRAY_SIZE(coupling_options),
362
363 .logic_threshold = &logic_threshold,
364 .num_logic_threshold = ARRAY_SIZE(logic_threshold),
365 .logic_threshold_for_pod = TRUE,
366
367 .trigger_sources = &an2_dig8_trigger_sources,
368 .num_trigger_sources = ARRAY_SIZE(an2_dig8_trigger_sources),
369
370 .trigger_slopes = &scope_trigger_slopes,
371 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
372
373 .timebases = &timebases_hmo_compact,
374 .num_timebases = ARRAY_SIZE(timebases_hmo_compact),
375
376 .vdivs = &vdivs,
377 .num_vdivs = ARRAY_SIZE(vdivs),
378
a058de04
GT
379 .num_ydivs = 8,
380
381 .scpi_dialect = &hameg_scpi_dialect,
382 },
383 {
384 /* RTC1002 and HMO1002/HMO1202 support only 8 digital channels. */
385 .name = {"RTC1002", "HMO1002", "HMO1202", NULL},
13f2b9d7
DJ
386 .analog_channels = 2,
387 .digital_channels = 8,
13f2b9d7 388
ba7dd8bb
UH
389 .analog_names = &scope_analog_channel_names,
390 .digital_names = &scope_digital_channel_names,
13f2b9d7 391
4b25cbff
UH
392 .devopts = &devopts,
393 .num_devopts = ARRAY_SIZE(devopts),
13f2b9d7 394
6b82c3e5
UH
395 .devopts_cg_analog = &devopts_cg_analog,
396 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
13f2b9d7 397
e131be0a
GT
398 .devopts_cg_digital = &devopts_cg_digital,
399 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
400
4b25cbff 401 .coupling_options = &coupling_options,
692716f5
UH
402 .num_coupling_options = ARRAY_SIZE(coupling_options),
403
e131be0a
GT
404 .logic_threshold = &logic_threshold,
405 .num_logic_threshold = ARRAY_SIZE(logic_threshold),
aac30633 406 .logic_threshold_for_pod = TRUE,
e131be0a 407
6d0f3508
GT
408 .trigger_sources = &an2_dig8_trigger_sources,
409 .num_trigger_sources = ARRAY_SIZE(an2_dig8_trigger_sources),
410
411 .trigger_slopes = &scope_trigger_slopes,
412 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
413
414 .timebases = &timebases,
415 .num_timebases = ARRAY_SIZE(timebases),
416
417 .vdivs = &vdivs,
418 .num_vdivs = ARRAY_SIZE(vdivs),
419
6d0f3508
GT
420 .num_ydivs = 8,
421
422 .scpi_dialect = &hameg_scpi_dialect,
423 },
424 {
425 /* HMO3032/3042/3052/3522 support 16 digital channels. */
426 .name = {"HMO3032", "HMO3042", "HMO3052", "HMO3522", NULL},
427 .analog_channels = 2,
428 .digital_channels = 16,
6d0f3508
GT
429
430 .analog_names = &scope_analog_channel_names,
431 .digital_names = &scope_digital_channel_names,
432
433 .devopts = &devopts,
434 .num_devopts = ARRAY_SIZE(devopts),
435
436 .devopts_cg_analog = &devopts_cg_analog,
437 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
438
e131be0a
GT
439 .devopts_cg_digital = &devopts_cg_digital,
440 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
441
6d0f3508
GT
442 .coupling_options = &coupling_options,
443 .num_coupling_options = ARRAY_SIZE(coupling_options),
444
e131be0a
GT
445 .logic_threshold = &logic_threshold,
446 .num_logic_threshold = ARRAY_SIZE(logic_threshold),
aac30633 447 .logic_threshold_for_pod = TRUE,
e131be0a 448
6d0f3508
GT
449 .trigger_sources = &an2_dig16_trigger_sources,
450 .num_trigger_sources = ARRAY_SIZE(an2_dig16_trigger_sources),
692716f5 451
13f2b9d7 452 .trigger_slopes = &scope_trigger_slopes,
692716f5 453 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
13f2b9d7 454
4b25cbff
UH
455 .timebases = &timebases,
456 .num_timebases = ARRAY_SIZE(timebases),
13f2b9d7 457
4b25cbff
UH
458 .vdivs = &vdivs,
459 .num_vdivs = ARRAY_SIZE(vdivs),
13f2b9d7 460
13f2b9d7
DJ
461 .num_ydivs = 8,
462
463 .scpi_dialect = &hameg_scpi_dialect,
464 },
465 {
a058de04 466 /* HMO Compact4: HMO724/1024/1524/2024 support only 8 digital channels. */
74413faf 467 .name = {"HMO724", "HMO1024", "HMO1524", "HMO2024", NULL},
13f2b9d7
DJ
468 .analog_channels = 4,
469 .digital_channels = 8,
13f2b9d7 470
ba7dd8bb
UH
471 .analog_names = &scope_analog_channel_names,
472 .digital_names = &scope_digital_channel_names,
13f2b9d7 473
4b25cbff
UH
474 .devopts = &devopts,
475 .num_devopts = ARRAY_SIZE(devopts),
13f2b9d7 476
6b82c3e5
UH
477 .devopts_cg_analog = &devopts_cg_analog,
478 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
13f2b9d7 479
e131be0a
GT
480 .devopts_cg_digital = &devopts_cg_digital,
481 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
482
4b25cbff 483 .coupling_options = &coupling_options,
692716f5
UH
484 .num_coupling_options = ARRAY_SIZE(coupling_options),
485
e131be0a
GT
486 .logic_threshold = &logic_threshold,
487 .num_logic_threshold = ARRAY_SIZE(logic_threshold),
aac30633 488 .logic_threshold_for_pod = TRUE,
e131be0a 489
6d0f3508
GT
490 .trigger_sources = &an4_dig8_trigger_sources,
491 .num_trigger_sources = ARRAY_SIZE(an4_dig8_trigger_sources),
692716f5 492
13f2b9d7 493 .trigger_slopes = &scope_trigger_slopes,
692716f5 494 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
13f2b9d7 495
a058de04
GT
496 .timebases = &timebases_hmo_compact,
497 .num_timebases = ARRAY_SIZE(timebases_hmo_compact),
13f2b9d7 498
4b25cbff
UH
499 .vdivs = &vdivs,
500 .num_vdivs = ARRAY_SIZE(vdivs),
13f2b9d7 501
13f2b9d7
DJ
502 .num_ydivs = 8,
503
74413faf
GS
504 .scpi_dialect = &hameg_scpi_dialect,
505 },
506 {
bf8a02b6 507 .name = {"HMO2524", "HMO3034", "HMO3044", "HMO3054", "HMO3524", NULL},
74413faf
GS
508 .analog_channels = 4,
509 .digital_channels = 16,
74413faf
GS
510
511 .analog_names = &scope_analog_channel_names,
512 .digital_names = &scope_digital_channel_names,
513
4b25cbff
UH
514 .devopts = &devopts,
515 .num_devopts = ARRAY_SIZE(devopts),
74413faf 516
6b82c3e5
UH
517 .devopts_cg_analog = &devopts_cg_analog,
518 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
74413faf 519
e131be0a
GT
520 .devopts_cg_digital = &devopts_cg_digital,
521 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
522
4b25cbff 523 .coupling_options = &coupling_options,
692716f5
UH
524 .num_coupling_options = ARRAY_SIZE(coupling_options),
525
e131be0a
GT
526 .logic_threshold = &logic_threshold,
527 .num_logic_threshold = ARRAY_SIZE(logic_threshold),
aac30633 528 .logic_threshold_for_pod = TRUE,
e131be0a 529
6d0f3508
GT
530 .trigger_sources = &an4_dig16_trigger_sources,
531 .num_trigger_sources = ARRAY_SIZE(an4_dig16_trigger_sources),
692716f5 532
74413faf 533 .trigger_slopes = &scope_trigger_slopes,
692716f5 534 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
74413faf 535
4b25cbff
UH
536 .timebases = &timebases,
537 .num_timebases = ARRAY_SIZE(timebases),
74413faf 538
4b25cbff
UH
539 .vdivs = &vdivs,
540 .num_vdivs = ARRAY_SIZE(vdivs),
74413faf 541
74413faf
GS
542 .num_ydivs = 8,
543
13f2b9d7
DJ
544 .scpi_dialect = &hameg_scpi_dialect,
545 },
aac30633
GT
546 {
547 .name = {"RTB2002", NULL},
548 .analog_channels = 2,
549 .digital_channels = 16,
aac30633
GT
550
551 .analog_names = &scope_analog_channel_names,
552 .digital_names = &scope_digital_channel_names,
553
554 .devopts = &devopts,
555 .num_devopts = ARRAY_SIZE(devopts),
556
557 .devopts_cg_analog = &devopts_cg_analog,
558 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
559
560 .devopts_cg_digital = &devopts_cg_digital,
561 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
562
563 .coupling_options = &coupling_options_rtb200x,
564 .num_coupling_options = ARRAY_SIZE(coupling_options_rtb200x),
565
566 .logic_threshold = &logic_threshold_rtb200x_rtm300x,
567 .num_logic_threshold = ARRAY_SIZE(logic_threshold_rtb200x_rtm300x),
568 .logic_threshold_for_pod = FALSE,
569
570 .trigger_sources = &an2_dig16_sbus_trigger_sources,
571 .num_trigger_sources = ARRAY_SIZE(an2_dig16_sbus_trigger_sources),
572
573 .trigger_slopes = &scope_trigger_slopes,
574 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
575
576 .timebases = &timebases,
577 .num_timebases = ARRAY_SIZE(timebases),
578
579 .vdivs = &vdivs,
580 .num_vdivs = ARRAY_SIZE(vdivs),
581
aac30633
GT
582 .num_ydivs = 8,
583
584 .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
585 },
586 {
587 .name = {"RTB2004", NULL},
588 .analog_channels = 4,
589 .digital_channels = 16,
aac30633
GT
590
591 .analog_names = &scope_analog_channel_names,
592 .digital_names = &scope_digital_channel_names,
593
594 .devopts = &devopts,
595 .num_devopts = ARRAY_SIZE(devopts),
596
597 .devopts_cg_analog = &devopts_cg_analog,
598 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
599
600 .devopts_cg_digital = &devopts_cg_digital,
601 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
602
603 .coupling_options = &coupling_options_rtb200x,
604 .num_coupling_options = ARRAY_SIZE(coupling_options_rtb200x),
605
606 .logic_threshold = &logic_threshold_rtb200x_rtm300x,
607 .num_logic_threshold = ARRAY_SIZE(logic_threshold_rtb200x_rtm300x),
608 .logic_threshold_for_pod = FALSE,
609
610 .trigger_sources = &an4_dig16_sbus_trigger_sources,
611 .num_trigger_sources = ARRAY_SIZE(an4_dig16_sbus_trigger_sources),
612
613 .trigger_slopes = &scope_trigger_slopes,
614 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
615
616 .timebases = &timebases,
617 .num_timebases = ARRAY_SIZE(timebases),
618
619 .vdivs = &vdivs,
620 .num_vdivs = ARRAY_SIZE(vdivs),
621
aac30633
GT
622 .num_ydivs = 8,
623
624 .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
625 },
626 {
627 .name = {"RTM3002", NULL},
628 .analog_channels = 2,
629 .digital_channels = 16,
aac30633
GT
630
631 .analog_names = &scope_analog_channel_names,
632 .digital_names = &scope_digital_channel_names,
633
634 .devopts = &devopts,
635 .num_devopts = ARRAY_SIZE(devopts),
636
637 .devopts_cg_analog = &devopts_cg_analog,
638 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
639
640 .devopts_cg_digital = &devopts_cg_digital,
641 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
642
643 .coupling_options = &coupling_options_rtm300x,
644 .num_coupling_options = ARRAY_SIZE(coupling_options_rtm300x),
645
646 .logic_threshold = &logic_threshold_rtb200x_rtm300x,
647 .num_logic_threshold = ARRAY_SIZE(logic_threshold_rtb200x_rtm300x),
648 .logic_threshold_for_pod = FALSE,
649
650 .trigger_sources = &an2_dig16_sbus_trigger_sources,
651 .num_trigger_sources = ARRAY_SIZE(an2_dig16_sbus_trigger_sources),
652
653 .trigger_slopes = &scope_trigger_slopes,
654 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
655
656 .timebases = &timebases,
657 .num_timebases = ARRAY_SIZE(timebases),
658
659 .vdivs = &vdivs,
660 .num_vdivs = ARRAY_SIZE(vdivs),
661
aac30633
GT
662 .num_ydivs = 8,
663
664 .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
665 },
666 {
667 .name = {"RTM3004", NULL},
668 .analog_channels = 4,
669 .digital_channels = 16,
aac30633
GT
670
671 .analog_names = &scope_analog_channel_names,
672 .digital_names = &scope_digital_channel_names,
673
674 .devopts = &devopts,
675 .num_devopts = ARRAY_SIZE(devopts),
676
677 .devopts_cg_analog = &devopts_cg_analog,
678 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
679
680 .devopts_cg_digital = &devopts_cg_digital,
681 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
682
683 .coupling_options = &coupling_options_rtm300x,
684 .num_coupling_options = ARRAY_SIZE(coupling_options_rtm300x),
b720f16e
GT
685
686 .logic_threshold = &logic_threshold_rtb200x_rtm300x,
687 .num_logic_threshold = ARRAY_SIZE(logic_threshold_rtb200x_rtm300x),
688 .logic_threshold_for_pod = FALSE,
689
690 .trigger_sources = &an4_dig16_sbus_trigger_sources,
691 .num_trigger_sources = ARRAY_SIZE(an4_dig16_sbus_trigger_sources),
692
693 .trigger_slopes = &scope_trigger_slopes,
694 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
695
696 .timebases = &timebases,
697 .num_timebases = ARRAY_SIZE(timebases),
698
699 .vdivs = &vdivs,
700 .num_vdivs = ARRAY_SIZE(vdivs),
701
b720f16e
GT
702 .num_ydivs = 8,
703
704 .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
705 },
706 {
707 .name = {"RTA4004", NULL},
708 .analog_channels = 4,
709 .digital_channels = 16,
b720f16e
GT
710
711 .analog_names = &scope_analog_channel_names,
712 .digital_names = &scope_digital_channel_names,
713
714 .devopts = &devopts,
715 .num_devopts = ARRAY_SIZE(devopts),
716
717 .devopts_cg_analog = &devopts_cg_analog,
718 .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog),
719
720 .devopts_cg_digital = &devopts_cg_digital,
721 .num_devopts_cg_digital = ARRAY_SIZE(devopts_cg_digital),
722
723 .coupling_options = &coupling_options_rtm300x,
724 .num_coupling_options = ARRAY_SIZE(coupling_options_rtm300x),
aac30633
GT
725
726 .logic_threshold = &logic_threshold_rtb200x_rtm300x,
727 .num_logic_threshold = ARRAY_SIZE(logic_threshold_rtb200x_rtm300x),
728 .logic_threshold_for_pod = FALSE,
729
730 .trigger_sources = &an4_dig16_sbus_trigger_sources,
731 .num_trigger_sources = ARRAY_SIZE(an4_dig16_sbus_trigger_sources),
732
733 .trigger_slopes = &scope_trigger_slopes,
734 .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes),
735
736 .timebases = &timebases,
737 .num_timebases = ARRAY_SIZE(timebases),
738
739 .vdivs = &vdivs,
740 .num_vdivs = ARRAY_SIZE(vdivs),
741
aac30633
GT
742 .num_ydivs = 8,
743
744 .scpi_dialect = &rohde_schwarz_log_not_pod_scpi_dialect,
745 },
13f2b9d7
DJ
746};
747
329733d9 748static void scope_state_dump(const struct scope_config *config,
13f2b9d7
DJ
749 struct scope_state *state)
750{
751 unsigned int i;
8de2dc3b 752 char *tmp;
13f2b9d7 753
0a1f7b09 754 for (i = 0; i < config->analog_channels; i++) {
8de2dc3b
DJ
755 tmp = sr_voltage_string((*config->vdivs)[state->analog_channels[i].vdiv][0],
756 (*config->vdivs)[state->analog_channels[i].vdiv][1]);
d9251a2c 757 sr_info("State of analog channel %d -> %s : %s (coupling) %s (vdiv) %2.2e (offset)",
8de2dc3b 758 i + 1, state->analog_channels[i].state ? "On" : "Off",
13f2b9d7 759 (*config->coupling_options)[state->analog_channels[i].coupling],
8de2dc3b 760 tmp, state->analog_channels[i].vertical_offset);
13f2b9d7
DJ
761 }
762
0a1f7b09 763 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
764 sr_info("State of digital channel %d -> %s", i,
765 state->digital_channels[i] ? "On" : "Off");
766 }
767
0a1f7b09 768 for (i = 0; i < config->digital_pods; i++) {
aac30633
GT
769 if (!strncmp("USER", (*config->logic_threshold)[state->digital_pods[i].threshold], 4) ||
770 !strcmp("MAN", (*config->logic_threshold)[state->digital_pods[i].threshold]))
262061ff 771 sr_info("State of digital POD %d -> %s : %E (threshold)", i + 1,
e131be0a
GT
772 state->digital_pods[i].state ? "On" : "Off",
773 state->digital_pods[i].user_threshold);
aac30633
GT
774 else
775 sr_info("State of digital POD %d -> %s : %s (threshold)", i + 1,
776 state->digital_pods[i].state ? "On" : "Off",
777 (*config->logic_threshold)[state->digital_pods[i].threshold]);
13f2b9d7
DJ
778 }
779
6984cfb2
SA
780 tmp = sr_period_string((*config->timebases)[state->timebase][0],
781 (*config->timebases)[state->timebase][1]);
8de2dc3b
DJ
782 sr_info("Current timebase: %s", tmp);
783 g_free(tmp);
784
14a2f74d
DJ
785 tmp = sr_samplerate_string(state->sample_rate);
786 sr_info("Current samplerate: %s", tmp);
787 g_free(tmp);
788
4fa4db2c
GT
789 if (!strcmp("PATT", (*config->trigger_sources)[state->trigger_source]))
790 sr_info("Current trigger: %s (pattern), %.2f (offset)",
791 state->trigger_pattern,
792 state->horiz_triggerpos);
793 else // Edge (slope) trigger
794 sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
795 (*config->trigger_sources)[state->trigger_source],
796 (*config->trigger_slopes)[state->trigger_slope],
797 state->horiz_triggerpos);
13f2b9d7
DJ
798}
799
23f43dff 800static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi,
692716f5 801 const char *command, const char *(*array)[], unsigned int n, int *result)
13f2b9d7
DJ
802{
803 char *tmp;
bd633efa 804 int idx;
13f2b9d7 805
67398969 806 if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK)
13f2b9d7 807 return SR_ERR;
13f2b9d7 808
bd633efa 809 if ((idx = std_str_idx_s(tmp, *array, n)) < 0) {
13f2b9d7 810 g_free(tmp);
bd633efa 811 return SR_ERR_ARG;
13f2b9d7
DJ
812 }
813
bd633efa
UH
814 *result = idx;
815
816 g_free(tmp);
817
13f2b9d7
DJ
818 return SR_OK;
819}
820
8fff7519 821/**
a53acd7d
SB
822 * This function takes a value of the form "2.000E-03" and returns the index
823 * of an array where a matching pair was found.
8fff7519
SA
824 *
825 * @param value The string to be parsed.
826 * @param array The array of s/f pairs.
827 * @param array_len The number of pairs in the array.
828 * @param result The index at which a matching pair was found.
829 *
830 * @return SR_ERR on any parsing error, SR_OK otherwise.
831 */
832static int array_float_get(gchar *value, const uint64_t array[][2],
650847e7 833 int array_len, unsigned int *result)
8fff7519 834{
a53acd7d
SB
835 struct sr_rational rval;
836 struct sr_rational aval;
8cccbac8 837
a53acd7d 838 if (sr_parse_rational(value, &rval) != SR_OK)
8fff7519
SA
839 return SR_ERR;
840
a53acd7d
SB
841 for (int i = 0; i < array_len; i++) {
842 sr_rational_set(&aval, array[i][0], array[i][1]);
843 if (sr_rational_eq(&rval, &aval)) {
8fff7519
SA
844 *result = i;
845 return SR_OK;
846 }
847 }
848
849 return SR_ERR;
850}
851
bd70ec4b
SB
852static struct sr_channel *get_channel_by_index_and_type(GSList *channel_lhead,
853 int index, int type)
854{
855 while (channel_lhead) {
856 struct sr_channel *ch = channel_lhead->data;
857 if (ch->index == index && ch->type == type)
858 return ch;
859
860 channel_lhead = channel_lhead->next;
861 }
862
863 return 0;
864}
865
866static int analog_channel_state_get(struct sr_dev_inst *sdi,
329733d9 867 const struct scope_config *config,
13f2b9d7
DJ
868 struct scope_state *state)
869{
8de2dc3b 870 unsigned int i, j;
13f2b9d7 871 char command[MAX_COMMAND_SIZE];
8fff7519 872 char *tmp_str;
bd70ec4b
SB
873 struct sr_channel *ch;
874 struct sr_scpi_dev_inst *scpi = sdi->conn;
13f2b9d7 875
0a1f7b09 876 for (i = 0; i < config->analog_channels; i++) {
13f2b9d7
DJ
877 g_snprintf(command, sizeof(command),
878 (*config->scpi_dialect)[SCPI_CMD_GET_ANALOG_CHAN_STATE],
879 i + 1);
880
23f43dff 881 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
882 &state->analog_channels[i].state) != SR_OK)
883 return SR_ERR;
884
bd70ec4b
SB
885 ch = get_channel_by_index_and_type(sdi->channels, i, SR_CHANNEL_ANALOG);
886 if (ch)
887 ch->enabled = state->analog_channels[i].state;
888
13f2b9d7 889 g_snprintf(command, sizeof(command),
66ddc22a 890 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_SCALE],
13f2b9d7
DJ
891 i + 1);
892
8fff7519 893 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
8de2dc3b 894 return SR_ERR;
8fff7519 895
53012da6 896 if (array_float_get(tmp_str, ARRAY_AND_SIZE(vdivs), &j) != SR_OK) {
8fff7519 897 g_free(tmp_str);
b4e31d2a 898 sr_err("Could not determine array index for vertical div scale.");
13f2b9d7 899 return SR_ERR;
b4e31d2a 900 }
13f2b9d7 901
8fff7519
SA
902 g_free(tmp_str);
903 state->analog_channels[i].vdiv = j;
904
13f2b9d7
DJ
905 g_snprintf(command, sizeof(command),
906 (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_OFFSET],
907 i + 1);
908
23f43dff 909 if (sr_scpi_get_float(scpi, command,
13f2b9d7
DJ
910 &state->analog_channels[i].vertical_offset) != SR_OK)
911 return SR_ERR;
912
913 g_snprintf(command, sizeof(command),
914 (*config->scpi_dialect)[SCPI_CMD_GET_COUPLING],
915 i + 1);
916
23f43dff 917 if (scope_state_get_array_option(scpi, command, config->coupling_options,
692716f5 918 config->num_coupling_options,
13f2b9d7
DJ
919 &state->analog_channels[i].coupling) != SR_OK)
920 return SR_ERR;
448e81b1
SB
921
922 g_snprintf(command, sizeof(command),
923 (*config->scpi_dialect)[SCPI_CMD_GET_PROBE_UNIT],
924 i + 1);
925
926 if (sr_scpi_get_string(scpi, command, &tmp_str) != SR_OK)
927 return SR_ERR;
928
929 if (tmp_str[0] == 'A')
930 state->analog_channels[i].probe_unit = 'A';
931 else
932 state->analog_channels[i].probe_unit = 'V';
933 g_free(tmp_str);
13f2b9d7
DJ
934 }
935
936 return SR_OK;
937}
938
bd70ec4b 939static int digital_channel_state_get(struct sr_dev_inst *sdi,
329733d9 940 const struct scope_config *config,
13f2b9d7
DJ
941 struct scope_state *state)
942{
aac30633 943 unsigned int i, idx;
e131be0a
GT
944 int result = SR_ERR;
945 static char *logic_threshold_short[] = {};
13f2b9d7 946 char command[MAX_COMMAND_SIZE];
bd70ec4b
SB
947 struct sr_channel *ch;
948 struct sr_scpi_dev_inst *scpi = sdi->conn;
13f2b9d7 949
0a1f7b09 950 for (i = 0; i < config->digital_channels; i++) {
13f2b9d7
DJ
951 g_snprintf(command, sizeof(command),
952 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_CHAN_STATE],
953 i);
954
23f43dff 955 if (sr_scpi_get_bool(scpi, command,
13f2b9d7
DJ
956 &state->digital_channels[i]) != SR_OK)
957 return SR_ERR;
bd70ec4b
SB
958
959 ch = get_channel_by_index_and_type(sdi->channels, i, SR_CHANNEL_LOGIC);
960 if (ch)
961 ch->enabled = state->digital_channels[i];
13f2b9d7
DJ
962 }
963
aac30633
GT
964 /* According to the SCPI standard, on models that support multiple
965 * user-defined logic threshold settings the response to the command
e131be0a
GT
966 * SCPI_CMD_GET_DIG_POD_THRESHOLD might return "USER" instead of
967 * "USER1".
968 *
969 * This makes more difficult to validate the response when the logic
970 * threshold is set to "USER1" and therefore we need to prevent device
971 * opening failures in such configuration case...
972 */
973 for (i = 0; i < config->num_logic_threshold; i++) {
974 logic_threshold_short[i] = g_strdup((*config->logic_threshold)[i]);
975 if (!strcmp("USER1", (*config->logic_threshold)[i]))
976 g_strlcpy(logic_threshold_short[i],
977 (*config->logic_threshold)[i], strlen((*config->logic_threshold)[i]));
978 }
979
0a1f7b09 980 for (i = 0; i < config->digital_pods; i++) {
13f2b9d7
DJ
981 g_snprintf(command, sizeof(command),
982 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_STATE],
983 i + 1);
984
23f43dff 985 if (sr_scpi_get_bool(scpi, command,
e131be0a
GT
986 &state->digital_pods[i].state) != SR_OK)
987 goto exit;
988
aac30633
GT
989 /* Check if the threshold command is based on the POD or digital channel index. */
990 if (config->logic_threshold_for_pod)
991 idx = i + 1;
992 else
a12456f1 993 idx = i * DIGITAL_CHANNELS_PER_POD;
aac30633 994
e131be0a
GT
995 g_snprintf(command, sizeof(command),
996 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_THRESHOLD],
aac30633 997 idx);
e131be0a
GT
998
999 /* Check for both standard and shortened responses. */
1000 if (scope_state_get_array_option(scpi, command, config->logic_threshold,
1001 config->num_logic_threshold,
1002 &state->digital_pods[i].threshold) != SR_OK)
1003 if (scope_state_get_array_option(scpi, command, (const char * (*)[]) &logic_threshold_short,
1004 config->num_logic_threshold,
1005 &state->digital_pods[i].threshold) != SR_OK)
1006 goto exit;
1007
aac30633 1008 /* If used-defined or custom threshold is active, get the level. */
e131be0a
GT
1009 if (!strcmp("USER1", (*config->logic_threshold)[state->digital_pods[i].threshold]))
1010 g_snprintf(command, sizeof(command),
1011 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_USER_THRESHOLD],
aac30633
GT
1012 idx, 1); /* USER1 logic threshold setting. */
1013 else if (!strcmp("USER2", (*config->logic_threshold)[state->digital_pods[i].threshold]))
e131be0a
GT
1014 g_snprintf(command, sizeof(command),
1015 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_USER_THRESHOLD],
aac30633
GT
1016 idx, 2); /* USER2 for custom logic_threshold setting. */
1017 else if (!strcmp("USER", (*config->logic_threshold)[state->digital_pods[i].threshold]) ||
1018 !strcmp("MAN", (*config->logic_threshold)[state->digital_pods[i].threshold]))
1019 g_snprintf(command, sizeof(command),
1020 (*config->scpi_dialect)[SCPI_CMD_GET_DIG_POD_USER_THRESHOLD],
1021 idx); /* USER or MAN for custom logic_threshold setting. */
e131be0a 1022 if (!strcmp("USER1", (*config->logic_threshold)[state->digital_pods[i].threshold]) ||
aac30633
GT
1023 !strcmp("USER2", (*config->logic_threshold)[state->digital_pods[i].threshold]) ||
1024 !strcmp("USER", (*config->logic_threshold)[state->digital_pods[i].threshold]) ||
1025 !strcmp("MAN", (*config->logic_threshold)[state->digital_pods[i].threshold]))
e131be0a
GT
1026 if (sr_scpi_get_float(scpi, command,
1027 &state->digital_pods[i].user_threshold) != SR_OK)
1028 goto exit;
13f2b9d7
DJ
1029 }
1030
e131be0a
GT
1031 result = SR_OK;
1032
1033exit:
1034 for (i = 0; i < config->num_logic_threshold; i++)
1035 g_free(logic_threshold_short[i]);
1036
1037 return result;
13f2b9d7
DJ
1038}
1039
14a2f74d
DJ
1040SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi)
1041{
1042 struct dev_context *devc;
1043 struct scope_state *state;
329733d9 1044 const struct scope_config *config;
14a2f74d 1045 float tmp_float;
14a2f74d
DJ
1046
1047 devc = sdi->priv;
1048 config = devc->model_config;
1049 state = devc->model_state;
14a2f74d 1050
39e19723
GT
1051 if (sr_scpi_get_float(sdi->conn,
1052 (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE],
1053 &tmp_float) != SR_OK)
1054 return SR_ERR;
c06c24d2 1055
39e19723 1056 state->sample_rate = tmp_float;
14a2f74d
DJ
1057
1058 return SR_OK;
1059}
1060
719eff68 1061SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi)
13f2b9d7
DJ
1062{
1063 struct dev_context *devc;
1064 struct scope_state *state;
329733d9 1065 const struct scope_config *config;
8de2dc3b
DJ
1066 float tmp_float;
1067 unsigned int i;
8cccbac8 1068 char *tmp_str;
13f2b9d7
DJ
1069
1070 devc = sdi->priv;
1071 config = devc->model_config;
1072 state = devc->model_state;
1073
8de2dc3b
DJ
1074 sr_info("Fetching scope state");
1075
bd70ec4b 1076 if (analog_channel_state_get(sdi, config, state) != SR_OK)
13f2b9d7
DJ
1077 return SR_ERR;
1078
bd70ec4b 1079 if (digital_channel_state_get(sdi, config, state) != SR_OK)
13f2b9d7
DJ
1080 return SR_ERR;
1081
8cccbac8
SA
1082 if (sr_scpi_get_string(sdi->conn,
1083 (*config->scpi_dialect)[SCPI_CMD_GET_TIMEBASE],
1084 &tmp_str) != SR_OK)
1085 return SR_ERR;
1086
53012da6 1087 if (array_float_get(tmp_str, ARRAY_AND_SIZE(timebases), &i) != SR_OK) {
8cccbac8 1088 g_free(tmp_str);
b4e31d2a 1089 sr_err("Could not determine array index for time base.");
13f2b9d7 1090 return SR_ERR;
b4e31d2a 1091 }
e5b7eef7 1092 g_free(tmp_str);
13f2b9d7 1093
8cccbac8
SA
1094 state->timebase = i;
1095
29a9b1a0
GT
1096 /* Determine the number of horizontal (x) divisions. */
1097 if (sr_scpi_get_int(sdi->conn,
1098 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZONTAL_DIV],
1099 (int *)&config->num_xdivs) != SR_OK)
1100 return SR_ERR;
1101
89280b1a
UH
1102 if (sr_scpi_get_float(sdi->conn,
1103 (*config->scpi_dialect)[SCPI_CMD_GET_HORIZ_TRIGGERPOS],
422a1c0d 1104 &tmp_float) != SR_OK)
13f2b9d7 1105 return SR_ERR;
422a1c0d
DJ
1106 state->horiz_triggerpos = tmp_float /
1107 (((double) (*config->timebases)[state->timebase][0] /
1108 (*config->timebases)[state->timebase][1]) * config->num_xdivs);
1109 state->horiz_triggerpos -= 0.5;
1110 state->horiz_triggerpos *= -1;
13f2b9d7 1111
89280b1a
UH
1112 if (scope_state_get_array_option(sdi->conn,
1113 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SOURCE],
692716f5
UH
1114 config->trigger_sources, config->num_trigger_sources,
1115 &state->trigger_source) != SR_OK)
13f2b9d7
DJ
1116 return SR_ERR;
1117
89280b1a 1118 if (scope_state_get_array_option(sdi->conn,
692716f5
UH
1119 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_SLOPE],
1120 config->trigger_slopes, config->num_trigger_slopes,
1121 &state->trigger_slope) != SR_OK)
13f2b9d7
DJ
1122 return SR_ERR;
1123
4fa4db2c
GT
1124 if (sr_scpi_get_string(sdi->conn,
1125 (*config->scpi_dialect)[SCPI_CMD_GET_TRIGGER_PATTERN],
396af5ad 1126 &tmp_str) != SR_OK)
4fa4db2c 1127 return SR_ERR;
396af5ad
GT
1128 strncpy(state->trigger_pattern,
1129 sr_scpi_unquote_string(tmp_str),
1130 MAX_ANALOG_CHANNEL_COUNT + MAX_DIGITAL_CHANNEL_COUNT);
1131 g_free(tmp_str);
4fa4db2c 1132
97a00074
GT
1133 if (sr_scpi_get_string(sdi->conn,
1134 (*config->scpi_dialect)[SCPI_CMD_GET_HIGH_RESOLUTION],
1135 &tmp_str) != SR_OK)
1136 return SR_ERR;
1137 if (!strcmp("OFF", tmp_str))
1138 state->high_resolution = FALSE;
1139 else
1140 state->high_resolution = TRUE;
1141 g_free(tmp_str);
1142
1143 if (sr_scpi_get_string(sdi->conn,
1144 (*config->scpi_dialect)[SCPI_CMD_GET_PEAK_DETECTION],
1145 &tmp_str) != SR_OK)
1146 return SR_ERR;
1147 if (!strcmp("OFF", tmp_str))
1148 state->peak_detection = FALSE;
1149 else
1150 state->peak_detection = TRUE;
1151 g_free(tmp_str);
1152
14a2f74d
DJ
1153 if (hmo_update_sample_rate(sdi) != SR_OK)
1154 return SR_ERR;
1155
8de2dc3b
DJ
1156 sr_info("Fetching finished.");
1157
13f2b9d7
DJ
1158 scope_state_dump(config, state);
1159
1160 return SR_OK;
1161}
1162
329733d9 1163static struct scope_state *scope_state_new(const struct scope_config *config)
13f2b9d7
DJ
1164{
1165 struct scope_state *state;
1166
a95f142e
UH
1167 state = g_malloc0(sizeof(struct scope_state));
1168 state->analog_channels = g_malloc0_n(config->analog_channels,
1169 sizeof(struct analog_channel_state));
1170 state->digital_channels = g_malloc0_n(
1171 config->digital_channels, sizeof(gboolean));
1172 state->digital_pods = g_malloc0_n(config->digital_pods,
e131be0a 1173 sizeof(struct digital_pod_state));
13f2b9d7
DJ
1174
1175 return state;
13f2b9d7
DJ
1176}
1177
719eff68 1178SR_PRIV void hmo_scope_state_free(struct scope_state *state)
13f2b9d7
DJ
1179{
1180 g_free(state->analog_channels);
1181 g_free(state->digital_channels);
1182 g_free(state->digital_pods);
1183 g_free(state);
1184}
1185
1186SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi)
1187{
13f2b9d7 1188 int model_index;
2d224dba 1189 unsigned int i, j, group;
ba7dd8bb 1190 struct sr_channel *ch;
13f2b9d7 1191 struct dev_context *devc;
eac9fcd2 1192 int ret;
13f2b9d7
DJ
1193
1194 devc = sdi->priv;
1195 model_index = -1;
1196
89280b1a 1197 /* Find the exact model. */
13f2b9d7
DJ
1198 for (i = 0; i < ARRAY_SIZE(scope_models); i++) {
1199 for (j = 0; scope_models[i].name[j]; j++) {
1200 if (!strcmp(sdi->model, scope_models[i].name[j])) {
1201 model_index = i;
1202 break;
1203 }
1204 }
1205 if (model_index != -1)
1206 break;
1207 }
1208
1209 if (model_index == -1) {
e35ebc6a 1210 sr_dbg("Unsupported device.");
13f2b9d7
DJ
1211 return SR_ERR_NA;
1212 }
29a9b1a0 1213
a12456f1
GT
1214 /* Configure the number of PODs given the number of digital channels. */
1215 scope_models[model_index].digital_pods = scope_models[model_index].digital_channels / DIGITAL_CHANNELS_PER_POD;
13f2b9d7 1216
562b7ae5
SA
1217 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
1218 scope_models[model_index].analog_channels);
562b7ae5
SA
1219 devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) *
1220 scope_models[model_index].digital_pods);
b0e80e9a
GS
1221 if (!devc->analog_groups || !devc->digital_groups) {
1222 g_free(devc->analog_groups);
1223 g_free(devc->digital_groups);
1224 return SR_ERR_MALLOC;
1225 }
13f2b9d7 1226
89280b1a 1227 /* Add analog channels. */
13f2b9d7 1228 for (i = 0; i < scope_models[model_index].analog_channels; i++) {
5e23fcab 1229 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE,
c368e6f3 1230 (*scope_models[model_index].analog_names)[i]);
13f2b9d7 1231
562b7ae5
SA
1232 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
1233
1234 devc->analog_groups[i]->name = g_strdup(
1235 (char *)(*scope_models[model_index].analog_names)[i]);
1236 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
13f2b9d7 1237
660e398f 1238 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 1239 devc->analog_groups[i]);
13f2b9d7
DJ
1240 }
1241
660e398f 1242 /* Add digital channel groups. */
eac9fcd2 1243 ret = SR_OK;
0a1f7b09 1244 for (i = 0; i < scope_models[model_index].digital_pods; i++) {
562b7ae5 1245 devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
eac9fcd2
GS
1246 if (!devc->digital_groups[i]) {
1247 ret = SR_ERR_MALLOC;
1248 break;
1249 }
262061ff 1250 devc->digital_groups[i]->name = g_strdup_printf("POD%d", i + 1);
660e398f 1251 sdi->channel_groups = g_slist_append(sdi->channel_groups,
2d224dba 1252 devc->digital_groups[i]);
13f2b9d7 1253 }
eac9fcd2
GS
1254 if (ret != SR_OK)
1255 return ret;
13f2b9d7 1256
89280b1a 1257 /* Add digital channels. */
13f2b9d7 1258 for (i = 0; i < scope_models[model_index].digital_channels; i++) {
5e23fcab 1259 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE,
c368e6f3 1260 (*scope_models[model_index].digital_names)[i]);
13f2b9d7 1261
a12456f1 1262 group = i / DIGITAL_CHANNELS_PER_POD;
2d224dba
GS
1263 devc->digital_groups[group]->channels = g_slist_append(
1264 devc->digital_groups[group]->channels, ch);
13f2b9d7
DJ
1265 }
1266
1267 devc->model_config = &scope_models[model_index];
d779dcac 1268 devc->samples_limit = 0;
13f2b9d7
DJ
1269 devc->frame_limit = 0;
1270
1271 if (!(devc->model_state = scope_state_new(devc->model_config)))
1272 return SR_ERR_MALLOC;
1273
1274 return SR_OK;
1275}
1276
e06875b2
GS
1277/* Queue data of one channel group, for later submission. */
1278SR_PRIV void hmo_queue_logic_data(struct dev_context *devc,
1279 size_t group, GByteArray *pod_data)
1280{
1281 size_t size;
1282 GByteArray *store;
1283 uint8_t *logic_data;
1284 size_t idx, logic_step;
1285
1286 /*
1287 * Upon first invocation, allocate the array which can hold the
1288 * combined logic data for all channels. Assume that each channel
1289 * will yield an identical number of samples per receive call.
1290 *
1291 * As a poor man's safety measure: (Silently) skip processing
1292 * for unexpected sample counts, and ignore samples for
1293 * unexpected channel groups. Don't bother with complicated
1294 * resize logic, considering that many models only support one
1295 * pod, and the most capable supported models have two pods of
1296 * identical size. We haven't yet seen any "odd" configuration.
1297 */
1298 if (!devc->logic_data) {
1299 size = pod_data->len * devc->pod_count;
1300 store = g_byte_array_sized_new(size);
1301 memset(store->data, 0, size);
1302 store = g_byte_array_set_size(store, size);
1303 devc->logic_data = store;
1304 } else {
1305 store = devc->logic_data;
1306 size = store->len / devc->pod_count;
e06875b2
GS
1307 if (group >= devc->pod_count)
1308 return;
1309 }
1310
1311 /*
1312 * Fold the data of the most recently received channel group into
1313 * the storage, where data resides for all channels combined.
1314 */
1315 logic_data = store->data;
1316 logic_data += group;
1317 logic_step = devc->pod_count;
1318 for (idx = 0; idx < pod_data->len; idx++) {
1319 *logic_data = pod_data->data[idx];
1320 logic_data += logic_step;
1321 }
d779dcac
GT
1322
1323 /* Truncate acquisition if a smaller number of samples has been requested. */
1324 if (devc->samples_limit > 0 && devc->logic_data->len > devc->samples_limit * devc->pod_count)
1325 devc->logic_data->len = devc->samples_limit * devc->pod_count;
e06875b2
GS
1326}
1327
1328/* Submit data for all channels, after the individual groups got collected. */
1329SR_PRIV void hmo_send_logic_packet(struct sr_dev_inst *sdi,
1330 struct dev_context *devc)
1331{
1332 struct sr_datafeed_packet packet;
1333 struct sr_datafeed_logic logic;
1334
1335 if (!devc->logic_data)
1336 return;
1337
1338 logic.data = devc->logic_data->data;
1339 logic.length = devc->logic_data->len;
1340 logic.unitsize = devc->pod_count;
1341
1342 packet.type = SR_DF_LOGIC;
1343 packet.payload = &logic;
1344
1345 sr_session_send(sdi, &packet);
1346}
1347
1348/* Undo previous resource allocation. */
1349SR_PRIV void hmo_cleanup_logic_data(struct dev_context *devc)
1350{
1351
1352 if (devc->logic_data) {
1353 g_byte_array_free(devc->logic_data, TRUE);
1354 devc->logic_data = NULL;
1355 }
1356 /*
1357 * Keep 'pod_count'! It's required when more frames will be
1358 * received, and does not harm when kept after acquisition.
1359 */
1360}
1361
719eff68 1362SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data)
06a3e78a 1363{
ba7dd8bb 1364 struct sr_channel *ch;
13f2b9d7 1365 struct sr_dev_inst *sdi;
06a3e78a 1366 struct dev_context *devc;
401b83a1 1367 struct scope_state *state;
13f2b9d7 1368 struct sr_datafeed_packet packet;
401b83a1
SB
1369 GByteArray *data;
1370 struct sr_datafeed_analog analog;
1371 struct sr_analog_encoding encoding;
1372 struct sr_analog_meaning meaning;
1373 struct sr_analog_spec spec;
89280b1a 1374 struct sr_datafeed_logic logic;
e06875b2 1375 size_t group;
06a3e78a
DJ
1376
1377 (void)fd;
f0729866 1378 (void)revents;
06a3e78a 1379
f62f595b
MK
1380 data = NULL;
1381
06a3e78a
DJ
1382 if (!(sdi = cb_data))
1383 return TRUE;
1384
1385 if (!(devc = sdi->priv))
1386 return TRUE;
1387
f4f273ce
SB
1388 /* Although this is correct in general, the USBTMC libusb implementation
1389 * currently does not generate an event prior to the first read. Often
1390 * it is ok to start reading just after the 50ms timeout. See bug #785.
dc89faea
UH
1391 if (revents != G_IO_IN)
1392 return TRUE;
f4f273ce 1393 */
13f2b9d7 1394
dc89faea 1395 ch = devc->current_channel->data;
401b83a1 1396 state = devc->model_state;
13f2b9d7 1397
b23eb1d4
GS
1398 /*
1399 * Send "frame begin" packet upon reception of data for the
1400 * first enabled channel.
1401 */
1402 if (devc->current_channel == devc->enabled_channels) {
1403 packet.type = SR_DF_FRAME_BEGIN;
1404 sr_session_send(sdi, &packet);
1405 }
1406
1407 /*
1408 * Pass on the received data of the channel(s).
1409 */
dc89faea
UH
1410 switch (ch->type) {
1411 case SR_CHANNEL_ANALOG:
401b83a1 1412 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
dc89faea 1413 if (data)
401b83a1 1414 g_byte_array_free(data, TRUE);
dc89faea 1415 return TRUE;
13f2b9d7
DJ
1416 }
1417
401b83a1
SB
1418 packet.type = SR_DF_ANALOG;
1419
1420 analog.data = data->data;
1421 analog.num_samples = data->len / sizeof(float);
d779dcac
GT
1422 /* Truncate acquisition if a smaller number of samples has been requested. */
1423 if (devc->samples_limit > 0 && analog.num_samples > devc->samples_limit)
1424 analog.num_samples = devc->samples_limit;
401b83a1
SB
1425 analog.encoding = &encoding;
1426 analog.meaning = &meaning;
1427 analog.spec = &spec;
1428
1429 encoding.unitsize = sizeof(float);
1430 encoding.is_signed = TRUE;
1431 encoding.is_float = TRUE;
65a6794e
GS
1432#ifdef WORDS_BIGENDIAN
1433 encoding.is_bigendian = TRUE;
1434#else
d1ad8b10 1435 encoding.is_bigendian = FALSE;
65a6794e 1436#endif
7dcaddd3
UH
1437 /* TODO: Use proper 'digits' value for this device (and its modes). */
1438 encoding.digits = 2;
401b83a1
SB
1439 encoding.is_digits_decimal = FALSE;
1440 encoding.scale.p = 1;
1441 encoding.scale.q = 1;
1442 encoding.offset.p = 0;
1443 encoding.offset.q = 1;
1444 if (state->analog_channels[ch->index].probe_unit == 'V') {
1445 meaning.mq = SR_MQ_VOLTAGE;
1446 meaning.unit = SR_UNIT_VOLT;
1447 } else {
1448 meaning.mq = SR_MQ_CURRENT;
1449 meaning.unit = SR_UNIT_AMPERE;
1450 }
1451 meaning.mqflags = 0;
1452 meaning.channels = g_slist_append(NULL, ch);
7dcaddd3
UH
1453 /* TODO: Use proper 'digits' value for this device (and its modes). */
1454 spec.spec_digits = 2;
dc89faea 1455 packet.payload = &analog;
695dc859 1456 sr_session_send(sdi, &packet);
d779dcac 1457 devc->num_samples = data->len / sizeof(float);
401b83a1
SB
1458 g_slist_free(meaning.channels);
1459 g_byte_array_free(data, TRUE);
dc89faea
UH
1460 data = NULL;
1461 break;
1462 case SR_CHANNEL_LOGIC:
401b83a1 1463 if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) {
14cb6aa4
GT
1464 if (data)
1465 g_byte_array_free(data, TRUE);
dc89faea 1466 return TRUE;
13f2b9d7 1467 }
dc89faea 1468
e06875b2
GS
1469 /*
1470 * If only data from the first pod is involved in the
1471 * acquisition, then the raw input bytes can get passed
1472 * forward for performance reasons. When the second pod
1473 * is involved (either alone, or in combination with the
1474 * first pod), then the received bytes need to be put
1475 * into memory in such a layout that all channel groups
1476 * get combined, and a unitsize larger than a single byte
1477 * applies. The "queue" logic transparently copes with
1478 * any such configuration. This works around the lack
1479 * of support for "meaning" to logic data, which is used
1480 * above for analog data.
1481 */
1482 if (devc->pod_count == 1) {
1483 packet.type = SR_DF_LOGIC;
1484 logic.data = data->data;
1485 logic.length = data->len;
d779dcac
GT
1486 /* Truncate acquisition if a smaller number of samples has been requested. */
1487 if (devc->samples_limit > 0 && logic.length > devc->samples_limit)
1488 logic.length = devc->samples_limit;
e06875b2
GS
1489 logic.unitsize = 1;
1490 packet.payload = &logic;
1491 sr_session_send(sdi, &packet);
1492 } else {
a12456f1 1493 group = ch->index / DIGITAL_CHANNELS_PER_POD;
e06875b2
GS
1494 hmo_queue_logic_data(devc, group, data);
1495 }
dc89faea 1496
d779dcac 1497 devc->num_samples = data->len / devc->pod_count;
401b83a1 1498 g_byte_array_free(data, TRUE);
dc89faea
UH
1499 data = NULL;
1500 break;
1501 default:
1502 sr_err("Invalid channel type.");
1503 break;
1504 }
1505
b23eb1d4
GS
1506 /*
1507 * Advance to the next enabled channel. When data for all enabled
e06875b2
GS
1508 * channels was received, then flush potentially queued logic data,
1509 * and send the "frame end" packet.
b23eb1d4 1510 */
dc89faea
UH
1511 if (devc->current_channel->next) {
1512 devc->current_channel = devc->current_channel->next;
1513 hmo_request_data(sdi);
b23eb1d4
GS
1514 return TRUE;
1515 }
e06875b2
GS
1516 hmo_send_logic_packet(sdi, devc);
1517
1518 /*
1519 * Release the logic data storage after each frame. This copes
1520 * with sample counts that differ in length per frame. -- Is
1521 * this a real constraint when acquiring multiple frames with
1522 * identical device settings?
1523 */
1524 hmo_cleanup_logic_data(devc);
1525
b23eb1d4
GS
1526 packet.type = SR_DF_FRAME_END;
1527 sr_session_send(sdi, &packet);
1528
1529 /*
1530 * End of frame was reached. Stop acquisition after the specified
d779dcac
GT
1531 * number of frames or after the specified number of samples, or
1532 * continue reception by starting over at the first enabled channel.
b23eb1d4 1533 */
d779dcac 1534 if (++devc->num_frames >= devc->frame_limit || devc->num_samples >= devc->samples_limit) {
d2f7c417 1535 sr_dev_acquisition_stop(sdi);
e06875b2 1536 hmo_cleanup_logic_data(devc);
dc89faea
UH
1537 } else {
1538 devc->current_channel = devc->enabled_channels;
1539 hmo_request_data(sdi);
06a3e78a
DJ
1540 }
1541
1542 return TRUE;
1543}