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