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