]> sigrok.org Git - libsigrok.git/blame - src/hardware/rigol-ds/api.c
rigol-ds: improve robustness in samplerate getting code path
[libsigrok.git] / src / hardware / rigol-ds / api.c
CommitLineData
f4816ac6
ML
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
88e429c9 5 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
bafd4890 6 * Copyright (C) 2013 Mathias Grimmberger <mgri@zaphod.sax.de>
f4816ac6
ML
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
6ec6c43b 22#include <config.h>
e0b7d23c
ML
23#include <fcntl.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <string.h>
ba464a12 27#include <strings.h>
2b0e4a46 28#include <math.h>
f4816ac6 29#include <glib.h>
c1aae900 30#include <libsigrok/libsigrok.h>
f4816ac6 31#include "libsigrok-internal.h"
5a1afc09 32#include "scpi.h"
f4816ac6
ML
33#include "protocol.h"
34
a0e0bb41 35static const uint32_t scanopts[] = {
ca55277c 36 SR_CONF_CONN,
05199c0a 37 SR_CONF_SERIALCOMM,
ca55277c
ML
38};
39
d73aacf1 40static const uint32_t drvopts[] = {
1953564a 41 SR_CONF_OSCILLOSCOPE,
d73aacf1
SA
42};
43
44static const uint32_t devopts[] = {
1b8a37c6 45 SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
86621306 46 SR_CONF_SAMPLERATE | SR_CONF_GET,
5827f61b 47 SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
86621306
UH
48 SR_CONF_NUM_HDIV | SR_CONF_GET,
49 SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_SET,
5827f61b 50 SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
b0c9d1d1 51 SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
9ea62f2e 52 SR_CONF_TRIGGER_LEVEL | SR_CONF_GET | SR_CONF_SET,
f579d08b 53 SR_CONF_DATA_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
f48e0249
ML
54};
55
6b82c3e5 56static const uint32_t devopts_cg_analog[] = {
5827f61b
BV
57 SR_CONF_NUM_VDIV | SR_CONF_GET,
58 SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
59 SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
934cf6cf 60 SR_CONF_PROBE_FACTOR | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
e0b7d23c
ML
61};
62
f6a0ac9f 63static const uint64_t timebases[][2] = {
e0b7d23c 64 /* nanoseconds */
8e06edf5 65 { 1, 1000000000 },
e0b7d23c
ML
66 { 2, 1000000000 },
67 { 5, 1000000000 },
68 { 10, 1000000000 },
69 { 20, 1000000000 },
70 { 50, 1000000000 },
71 { 100, 1000000000 },
72 { 500, 1000000000 },
73 /* microseconds */
74 { 1, 1000000 },
75 { 2, 1000000 },
76 { 5, 1000000 },
77 { 10, 1000000 },
78 { 20, 1000000 },
79 { 50, 1000000 },
80 { 100, 1000000 },
81 { 200, 1000000 },
82 { 500, 1000000 },
83 /* milliseconds */
84 { 1, 1000 },
85 { 2, 1000 },
86 { 5, 1000 },
87 { 10, 1000 },
88 { 20, 1000 },
89 { 50, 1000 },
90 { 100, 1000 },
91 { 200, 1000 },
92 { 500, 1000 },
93 /* seconds */
94 { 1, 1 },
95 { 2, 1 },
96 { 5, 1 },
97 { 10, 1 },
98 { 20, 1 },
99 { 50, 1 },
bafd4890
ML
100 { 100, 1 },
101 { 200, 1 },
102 { 500, 1 },
8e06edf5 103 { 1000, 1 },
e0b7d23c
ML
104};
105
f6a0ac9f 106static const uint64_t vdivs[][2] = {
bafd4890
ML
107 /* microvolts */
108 { 500, 1000000 },
e0b7d23c 109 /* millivolts */
bafd4890 110 { 1, 1000 },
e0b7d23c
ML
111 { 2, 1000 },
112 { 5, 1000 },
113 { 10, 1000 },
114 { 20, 1000 },
115 { 50, 1000 },
116 { 100, 1000 },
117 { 200, 1000 },
118 { 500, 1000 },
119 /* volts */
120 { 1, 1 },
121 { 2, 1 },
122 { 5, 1 },
123 { 10, 1 },
d50725e0
UH
124 { 20, 1 },
125 { 50, 1 },
126 { 100, 1 },
e0b7d23c
ML
127};
128
6bcc81ac
VO
129static const char *trigger_sources_2_chans[] = {
130 "CH1", "CH2",
131 "EXT", "AC Line",
132 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
133 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
134};
643c8824 135
6bcc81ac 136static const char *trigger_sources_4_chans[] = {
f8195cb2
UH
137 "CH1", "CH2", "CH3", "CH4",
138 "EXT", "AC Line",
139 "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
140 "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15",
e0b7d23c
ML
141};
142
5d336f11 143static const char *trigger_slopes[] = {
f8195cb2 144 "r", "f",
5d336f11
AJ
145};
146
e0b7d23c 147static const char *coupling[] = {
f8195cb2 148 "AC", "DC", "GND",
e0b7d23c
ML
149};
150
934cf6cf 151static const uint64_t probe_factor[] = {
f8195cb2 152 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000,
934cf6cf
AJ
153};
154
babab622
ML
155/* Do not change the order of entries */
156static const char *data_sources[] = {
157 "Live",
158 "Memory",
159 "Segmented",
160};
161
0f523f2b
UH
162static const struct rigol_ds_command std_cmd[] = {
163 { CMD_GET_HORIZ_TRIGGERPOS, ":TIM:OFFS?" },
164 { CMD_SET_HORIZ_TRIGGERPOS, ":TIM:OFFS %s" },
165};
166
167static const struct rigol_ds_command mso7000a_cmd[] = {
168 { CMD_GET_HORIZ_TRIGGERPOS, ":TIM:POS?" },
169 { CMD_SET_HORIZ_TRIGGERPOS, ":TIM:POS %s" },
170};
171
569d4dbd
ML
172enum vendor {
173 RIGOL,
174 AGILENT,
175};
176
177enum series {
178 VS5000,
179 DS1000,
180 DS2000,
181 DS2000A,
182 DSO1000,
744d683c 183 DSO1000B,
702f42e8 184 DS1000Z,
6b04525b 185 DS4000,
f6129c8f 186 MSO5000,
0f523f2b 187 MSO7000A,
569d4dbd 188};
10afee13 189
569d4dbd
ML
190/* short name, full name */
191static const struct rigol_ds_vendor supported_vendors[] = {
192 [RIGOL] = {"Rigol", "Rigol Technologies"},
14e1aa6d 193 [AGILENT] = {"Agilent", "Agilent Technologies"},
569d4dbd
ML
194};
195
196#define VENDOR(x) &supported_vendors[x]
0f8bee71
UH
197/* vendor, series/name, protocol, data format, max timebase, min vdiv,
198 * number of horizontal divs, live waveform samples, memory buffer samples */
569d4dbd
ML
199static const struct rigol_ds_series supported_series[] = {
200 [VS5000] = {VENDOR(RIGOL), "VS5000", PROTOCOL_V1, FORMAT_RAW,
201 {50, 1}, {2, 1000}, 14, 2048, 0},
202 [DS1000] = {VENDOR(RIGOL), "DS1000", PROTOCOL_V2, FORMAT_IEEE488_2,
203 {50, 1}, {2, 1000}, 12, 600, 1048576},
204 [DS2000] = {VENDOR(RIGOL), "DS2000", PROTOCOL_V3, FORMAT_IEEE488_2,
96cb7faa 205 {500, 1}, {500, 1000000}, 14, 1400, 14000},
569d4dbd
ML
206 [DS2000A] = {VENDOR(RIGOL), "DS2000A", PROTOCOL_V3, FORMAT_IEEE488_2,
207 {1000, 1}, {500, 1000000}, 14, 1400, 14000},
208 [DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2,
209 {50, 1}, {2, 1000}, 12, 600, 20480},
744d683c
NM
210 [DSO1000B] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2,
211 {50, 1}, {2, 1000}, 12, 600, 20480},
702f42e8
ML
212 [DS1000Z] = {VENDOR(RIGOL), "DS1000Z", PROTOCOL_V4, FORMAT_IEEE488_2,
213 {50, 1}, {1, 1000}, 12, 1200, 12000000},
6b04525b 214 [DS4000] = {VENDOR(RIGOL), "DS4000", PROTOCOL_V4, FORMAT_IEEE488_2,
47b821dc 215 {1000, 1}, {1, 1000}, 14, 1400, 0},
f6129c8f
SR
216 [MSO5000] = {VENDOR(RIGOL), "MSO5000", PROTOCOL_V5, FORMAT_IEEE488_2,
217 {1000, 1}, {500, 1000000}, 10, 1000, 0},
0f523f2b
UH
218 [MSO7000A] = {VENDOR(AGILENT), "MSO7000A", PROTOCOL_V4, FORMAT_IEEE488_2,
219 {50, 1}, {2, 1000}, 10, 1000, 8000000},
569d4dbd 220};
10afee13 221
569d4dbd 222#define SERIES(x) &supported_series[x]
643c8824
VO
223/*
224 * Use a macro to select the correct list of trigger sources and its length
225 * based on the number of analog channels and presence of digital channels.
226 */
227#define CH_INFO(num, digital) \
228 num, digital, trigger_sources_##num##_chans, \
229 digital ? ARRAY_SIZE(trigger_sources_##num##_chans) : (num + 2)
569d4dbd 230/* series, model, min timebase, analog channels, digital */
bafd4890 231static const struct rigol_ds_model supported_models[] = {
0f523f2b
UH
232 {SERIES(VS5000), "VS5022", {20, 1000000000}, CH_INFO(2, false), std_cmd},
233 {SERIES(VS5000), "VS5042", {10, 1000000000}, CH_INFO(2, false), std_cmd},
234 {SERIES(VS5000), "VS5062", {5, 1000000000}, CH_INFO(2, false), std_cmd},
235 {SERIES(VS5000), "VS5102", {2, 1000000000}, CH_INFO(2, false), std_cmd},
236 {SERIES(VS5000), "VS5202", {2, 1000000000}, CH_INFO(2, false), std_cmd},
237 {SERIES(VS5000), "VS5022D", {20, 1000000000}, CH_INFO(2, true), std_cmd},
238 {SERIES(VS5000), "VS5042D", {10, 1000000000}, CH_INFO(2, true), std_cmd},
239 {SERIES(VS5000), "VS5062D", {5, 1000000000}, CH_INFO(2, true), std_cmd},
240 {SERIES(VS5000), "VS5102D", {2, 1000000000}, CH_INFO(2, true), std_cmd},
241 {SERIES(VS5000), "VS5202D", {2, 1000000000}, CH_INFO(2, true), std_cmd},
242 {SERIES(DS1000), "DS1052E", {5, 1000000000}, CH_INFO(2, false), std_cmd},
243 {SERIES(DS1000), "DS1102E", {2, 1000000000}, CH_INFO(2, false), std_cmd},
244 {SERIES(DS1000), "DS1152E", {2, 1000000000}, CH_INFO(2, false), std_cmd},
c4a46475 245 {SERIES(DS1000), "DS1152E-EDU", {2, 1000000000}, CH_INFO(2, false), std_cmd},
0f523f2b
UH
246 {SERIES(DS1000), "DS1052D", {5, 1000000000}, CH_INFO(2, true), std_cmd},
247 {SERIES(DS1000), "DS1102D", {2, 1000000000}, CH_INFO(2, true), std_cmd},
248 {SERIES(DS1000), "DS1152D", {2, 1000000000}, CH_INFO(2, true), std_cmd},
249 {SERIES(DS2000), "DS2072", {5, 1000000000}, CH_INFO(2, false), std_cmd},
250 {SERIES(DS2000), "DS2102", {5, 1000000000}, CH_INFO(2, false), std_cmd},
251 {SERIES(DS2000), "DS2202", {2, 1000000000}, CH_INFO(2, false), std_cmd},
252 {SERIES(DS2000), "DS2302", {1, 1000000000}, CH_INFO(2, false), std_cmd},
253 {SERIES(DS2000A), "DS2072A", {5, 1000000000}, CH_INFO(2, false), std_cmd},
254 {SERIES(DS2000A), "DS2102A", {5, 1000000000}, CH_INFO(2, false), std_cmd},
255 {SERIES(DS2000A), "DS2202A", {2, 1000000000}, CH_INFO(2, false), std_cmd},
256 {SERIES(DS2000A), "DS2302A", {1, 1000000000}, CH_INFO(2, false), std_cmd},
257 {SERIES(DS2000A), "MSO2072A", {5, 1000000000}, CH_INFO(2, true), std_cmd},
258 {SERIES(DS2000A), "MSO2102A", {5, 1000000000}, CH_INFO(2, true), std_cmd},
259 {SERIES(DS2000A), "MSO2202A", {2, 1000000000}, CH_INFO(2, true), std_cmd},
260 {SERIES(DS2000A), "MSO2302A", {1, 1000000000}, CH_INFO(2, true), std_cmd},
261 {SERIES(DSO1000), "DSO1002A", {5, 1000000000}, CH_INFO(2, false), std_cmd},
262 {SERIES(DSO1000), "DSO1004A", {5, 1000000000}, CH_INFO(4, false), std_cmd},
263 {SERIES(DSO1000), "DSO1012A", {2, 1000000000}, CH_INFO(2, false), std_cmd},
264 {SERIES(DSO1000), "DSO1014A", {2, 1000000000}, CH_INFO(4, false), std_cmd},
265 {SERIES(DSO1000), "DSO1022A", {2, 1000000000}, CH_INFO(2, false), std_cmd},
266 {SERIES(DSO1000), "DSO1024A", {2, 1000000000}, CH_INFO(4, false), std_cmd},
744d683c
NM
267 {SERIES(DSO1000B), "DSO1052B", {2, 1000000000}, CH_INFO(2, false), std_cmd},
268 {SERIES(DSO1000B), "DSO1072B", {2, 1000000000}, CH_INFO(2, false), std_cmd},
269 {SERIES(DSO1000B), "DSO1102B", {2, 1000000000}, CH_INFO(2, false), std_cmd},
270 {SERIES(DSO1000B), "DSO1152B", {2, 1000000000}, CH_INFO(2, false), std_cmd},
0f523f2b
UH
271 {SERIES(DS1000Z), "DS1054Z", {5, 1000000000}, CH_INFO(4, false), std_cmd},
272 {SERIES(DS1000Z), "DS1074Z", {5, 1000000000}, CH_INFO(4, false), std_cmd},
273 {SERIES(DS1000Z), "DS1104Z", {5, 1000000000}, CH_INFO(4, false), std_cmd},
274 {SERIES(DS1000Z), "DS1074Z-S", {5, 1000000000}, CH_INFO(4, false), std_cmd},
275 {SERIES(DS1000Z), "DS1104Z-S", {5, 1000000000}, CH_INFO(4, false), std_cmd},
276 {SERIES(DS1000Z), "DS1074Z Plus", {5, 1000000000}, CH_INFO(4, false), std_cmd},
277 {SERIES(DS1000Z), "DS1104Z Plus", {5, 1000000000}, CH_INFO(4, false), std_cmd},
0f5dcee6 278 {SERIES(DS1000Z), "DS1102Z-E", {2, 1000000000}, CH_INFO(2, false), std_cmd},
77f3c5e5 279 {SERIES(DS1000Z), "DS1202Z-E", {2, 1000000000}, CH_INFO(2, false), std_cmd},
0f523f2b
UH
280 {SERIES(DS1000Z), "MSO1074Z", {5, 1000000000}, CH_INFO(4, true), std_cmd},
281 {SERIES(DS1000Z), "MSO1104Z", {5, 1000000000}, CH_INFO(4, true), std_cmd},
282 {SERIES(DS1000Z), "MSO1074Z-S", {5, 1000000000}, CH_INFO(4, true), std_cmd},
283 {SERIES(DS1000Z), "MSO1104Z-S", {5, 1000000000}, CH_INFO(4, true), std_cmd},
284 {SERIES(DS4000), "DS4024", {1, 1000000000}, CH_INFO(4, false), std_cmd},
f6129c8f
SR
285 {SERIES(MSO5000), "MSO5072", {1, 1000000000}, CH_INFO(2, true), std_cmd},
286 {SERIES(MSO5000), "MSO5074", {1, 1000000000}, CH_INFO(4, true), std_cmd},
287 {SERIES(MSO5000), "MSO5102", {1, 1000000000}, CH_INFO(2, true), std_cmd},
288 {SERIES(MSO5000), "MSO5104", {1, 1000000000}, CH_INFO(4, true), std_cmd},
289 {SERIES(MSO5000), "MSO5204", {1, 1000000000}, CH_INFO(4, true), std_cmd},
290 {SERIES(MSO5000), "MSO5354", {1, 1000000000}, CH_INFO(4, true), std_cmd},
0f523f2b
UH
291 /* TODO: Digital channels are not yet supported on MSO7000A. */
292 {SERIES(MSO7000A), "MSO7034A", {2, 1000000000}, CH_INFO(4, false), mso7000a_cmd},
512bb890
BV
293};
294
dd5c48a6 295static struct sr_dev_driver rigol_ds_driver_info;
f4816ac6 296
16e96ca3
VO
297static int analog_frame_size(const struct sr_dev_inst *);
298
3553451f 299static void clear_helper(struct dev_context *devc)
f4816ac6 300{
effb9dd1 301 unsigned int i;
f4816ac6 302
babab622
ML
303 g_free(devc->data);
304 g_free(devc->buffer);
effb9dd1
AJ
305 for (i = 0; i < ARRAY_SIZE(devc->coupling); i++)
306 g_free(devc->coupling[i]);
fa85f376
UH
307 g_free(devc->trigger_source);
308 g_free(devc->trigger_slope);
562b7ae5 309 g_free(devc->analog_groups);
fa85f376 310}
f4816ac6 311
4f840ce9 312static int dev_clear(const struct sr_dev_driver *di)
fa85f376 313{
3553451f 314 return std_dev_clear_with_callback(di, (std_dev_clear_callback)clear_helper);
f4816ac6
ML
315}
316
9d3ae01b 317static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
f4816ac6 318{
cc9fd2d2
BV
319 struct dev_context *devc;
320 struct sr_dev_inst *sdi;
ae1bc1cc 321 struct sr_scpi_hw_info *hw_info;
ba7dd8bb 322 struct sr_channel *ch;
8dd0b290 323 long n[3];
f6a0ac9f 324 unsigned int i;
bafd4890 325 const struct rigol_ds_model *model = NULL;
569d4dbd 326 gchar *channel_name, **version;
fb6e5ba8 327
ae1bc1cc 328 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
05238d28
ML
329 sr_info("Couldn't get IDN response, retrying.");
330 sr_scpi_close(scpi);
331 sr_scpi_open(scpi);
332 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
333 sr_info("Couldn't get IDN response.");
334 return NULL;
335 }
ca55277c 336 }
e0b7d23c 337
ca55277c 338 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
34577da6 339 if (!g_ascii_strcasecmp(hw_info->manufacturer,
569d4dbd 340 supported_models[i].series->vendor->full_name) &&
10afee13 341 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 342 model = &supported_models[i];
ca55277c 343 break;
fb6e5ba8 344 }
ca55277c 345 }
fb6e5ba8 346
0af636be 347 if (!model) {
ae1bc1cc 348 sr_scpi_hw_info_free(hw_info);
9d3ae01b 349 return NULL;
ca55277c 350 }
fb6e5ba8 351
aac29cc1 352 sdi = g_malloc0(sizeof(struct sr_dev_inst));
0af636be
UH
353 sdi->vendor = g_strdup(model->series->vendor->name);
354 sdi->model = g_strdup(model->name);
355 sdi->version = g_strdup(hw_info->firmware_version);
ae1bc1cc 356 sdi->conn = scpi;
4f840ce9 357 sdi->driver = &rigol_ds_driver_info;
ae1bc1cc 358 sdi->inst_type = SR_INST_SCPI;
b3fccc85 359 sdi->serial_num = g_strdup(hw_info->serial_number);
f57d8ffe 360 devc = g_malloc0(sizeof(struct dev_context));
cc9fd2d2 361 devc->limit_frames = 0;
bafd4890 362 devc->model = model;
569d4dbd 363 devc->format = model->series->format;
8dd0b290 364
569d4dbd
ML
365 /* DS1000 models with firmware before 0.2.4 used the old data format. */
366 if (model->series == SERIES(DS1000)) {
8dd0b290
BV
367 version = g_strsplit(hw_info->firmware_version, ".", 0);
368 do {
369 if (!version[0] || !version[1] || !version[2])
370 break;
371 if (version[0][0] == 0 || version[1][0] == 0 || version[2][0] == 0)
372 break;
373 for (i = 0; i < 3; i++) {
374 if (sr_atol(version[i], &n[i]) != SR_OK)
375 break;
376 }
377 if (i != 3)
378 break;
de285cce
BV
379 scpi->firmware_version = n[0] * 100 + n[1] * 10 + n[2];
380 if (scpi->firmware_version < 24) {
381 sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
382 devc->format = FORMAT_RAW;
383 }
384 break;
0c5f2abc 385 } while (0);
8dd0b290
BV
386 g_strfreev(version);
387 }
388
389 sr_scpi_hw_info_free(hw_info);
512bb890 390
562b7ae5
SA
391 devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) *
392 model->analog_channels);
393
821fbcad 394 for (i = 0; i < model->analog_channels; i++) {
eac0c613 395 channel_name = g_strdup_printf("CH%d", i + 1);
5e23fcab 396 ch = sr_channel_new(sdi, i, SR_CHANNEL_ANALOG, TRUE, channel_name);
562b7ae5
SA
397
398 devc->analog_groups[i] = g_malloc0(sizeof(struct sr_channel_group));
399
400 devc->analog_groups[i]->name = channel_name;
401 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
660e398f 402 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 403 devc->analog_groups[i]);
ca55277c 404 }
512bb890 405
bafd4890 406 if (devc->model->has_digital) {
16aca766 407 devc->digital_group = g_malloc0(sizeof(struct sr_channel_group));
562b7ae5 408
effb9dd1 409 for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) {
eac0c613 410 channel_name = g_strdup_printf("D%d", i);
5e23fcab 411 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
ca55277c 412 g_free(channel_name);
562b7ae5
SA
413 devc->digital_group->channels = g_slist_append(
414 devc->digital_group->channels, ch);
512bb890 415 }
562b7ae5 416 devc->digital_group->name = g_strdup("LA");
660e398f 417 sdi->channel_groups = g_slist_append(sdi->channel_groups,
562b7ae5 418 devc->digital_group);
ca55277c 419 }
bafd4890 420
396cdca0 421 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
bafd4890
ML
422 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
423 devc->timebases = &timebases[i];
569d4dbd 424 if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2])))
bafd4890
ML
425 devc->num_timebases = &timebases[i] - devc->timebases + 1;
426 }
427
396cdca0 428 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
a95f142e
UH
429 if (!memcmp(&devc->model->series->min_vdiv,
430 &vdivs[i], sizeof(uint64_t[2]))) {
6ff1394e 431 devc->vdivs = &vdivs[i];
396cdca0 432 devc->num_vdivs = ARRAY_SIZE(vdivs) - i;
81b85663 433 }
a95f142e 434 }
bafd4890 435
a95f142e
UH
436 devc->buffer = g_malloc(ACQ_BUFFER_SIZE);
437 devc->data = g_malloc(ACQ_BUFFER_SIZE * sizeof(float));
babab622
ML
438
439 devc->data_source = DATA_SOURCE_LIVE;
440
cc9fd2d2
BV
441 sdi->priv = devc;
442
9d3ae01b 443 return sdi;
ca55277c 444}
512bb890 445
4f840ce9 446static GSList *scan(struct sr_dev_driver *di, GSList *options)
ca55277c 447{
41812aca 448 return sr_scpi_scan(di->context, options, probe_device);
f4816ac6
ML
449}
450
6078d2c9 451static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 452{
e1b5b7e7 453 int ret;
ae1bc1cc 454 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 455
e1b5b7e7
UH
456 if ((ret = sr_scpi_open(scpi)) < 0) {
457 sr_err("Failed to open SCPI device: %s.", sr_strerror(ret));
e0b7d23c 458 return SR_ERR;
e1b5b7e7 459 }
e0b7d23c 460
e1b5b7e7
UH
461 if ((ret = rigol_ds_get_dev_cfg(sdi)) < 0) {
462 sr_err("Failed to get device config: %s.", sr_strerror(ret));
254dd102 463 return SR_ERR;
e1b5b7e7 464 }
f4816ac6
ML
465
466 return SR_OK;
467}
468
6078d2c9 469static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 470{
ae1bc1cc 471 struct sr_scpi_dev_inst *scpi;
22c19688 472 struct dev_context *devc;
ae1bc1cc
ML
473
474 scpi = sdi->conn;
22c19688
ML
475 devc = sdi->priv;
476
f1ba6b4b
UH
477 if (!scpi)
478 return SR_ERR_BUG;
479
6e94eb41 480 if (devc->model->series->protocol == PROTOCOL_V2)
38354d9d 481 rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE");
e0b7d23c 482
f1ba6b4b 483 return sr_scpi_close(scpi);
f4816ac6
ML
484}
485
5415e602
ML
486static int analog_frame_size(const struct sr_dev_inst *sdi)
487{
488 struct dev_context *devc = sdi->priv;
ba7dd8bb
UH
489 struct sr_channel *ch;
490 int analog_channels = 0;
5415e602
ML
491 GSList *l;
492
ba7dd8bb
UH
493 for (l = sdi->channels; l; l = l->next) {
494 ch = l->data;
3f239f08 495 if (ch->type == SR_CHANNEL_ANALOG && ch->enabled)
ba7dd8bb 496 analog_channels++;
569d4dbd
ML
497 }
498
ba7dd8bb 499 if (analog_channels == 0)
824eb2ac
ML
500 return 0;
501
569d4dbd
ML
502 switch (devc->data_source) {
503 case DATA_SOURCE_LIVE:
504 return devc->model->series->live_samples;
505 case DATA_SOURCE_MEMORY:
8cbe5339 506 case DATA_SOURCE_SEGMENTED:
ba7dd8bb 507 return devc->model->series->buffer_samples / analog_channels;
470140fc 508 default:
569d4dbd 509 return 0;
5415e602
ML
510 }
511}
512
d22250a9
ML
513static int digital_frame_size(const struct sr_dev_inst *sdi)
514{
515 struct dev_context *devc = sdi->priv;
516
569d4dbd
ML
517 switch (devc->data_source) {
518 case DATA_SOURCE_LIVE:
519 return devc->model->series->live_samples * 2;
520 case DATA_SOURCE_MEMORY:
8cbe5339 521 case DATA_SOURCE_SEGMENTED:
569d4dbd 522 return devc->model->series->buffer_samples * 2;
d22250a9
ML
523 default:
524 return 0;
525 }
526}
527
dd7a72ea
UH
528static int config_get(uint32_t key, GVariant **data,
529 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
d62d7ad1 530{
e43fdd8d 531 struct dev_context *devc;
ba7dd8bb 532 struct sr_channel *ch;
2b0e4a46 533 const char *tmp_str;
2b0e4a46 534 int analog_channel = -1;
c33ff377 535 float smallest_diff = INFINITY;
2b0e4a46
AJ
536 int idx = -1;
537 unsigned i;
d62d7ad1 538
709468ba 539 if (!sdi)
e43fdd8d
BV
540 return SR_ERR_ARG;
541
709468ba
UH
542 devc = sdi->priv;
543
660e398f 544 /* If a channel group is specified, it must be a valid one. */
53b4680f 545 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 546 sr_err("Invalid channel group specified.");
969edf63 547 return SR_ERR;
be60a9e4
BV
548 }
549
53b4680f 550 if (cg) {
ba7dd8bb
UH
551 ch = g_slist_nth_data(cg->channels, 0);
552 if (!ch)
2b0e4a46 553 return SR_ERR;
3f239f08 554 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 555 if (ch->name[2] < '1' || ch->name[2] > '4')
2b0e4a46 556 return SR_ERR;
ba7dd8bb 557 analog_channel = ch->name[2] - '1';
2b0e4a46
AJ
558 }
559 }
560
584560f1 561 switch (key) {
bf622e6d 562 case SR_CONF_NUM_HDIV:
569d4dbd 563 *data = g_variant_new_int32(devc->model->series->num_horizontal_divs);
d62d7ad1
BV
564 break;
565 case SR_CONF_NUM_VDIV:
81b85663 566 *data = g_variant_new_int32(devc->num_vdivs);
f44f7e61 567 break;
babab622
ML
568 case SR_CONF_DATA_SOURCE:
569 if (devc->data_source == DATA_SOURCE_LIVE)
570 *data = g_variant_new_string("Live");
571 else if (devc->data_source == DATA_SOURCE_MEMORY)
572 *data = g_variant_new_string("Memory");
573 else
574 *data = g_variant_new_string("Segmented");
575 break;
1b8a37c6
VO
576 case SR_CONF_LIMIT_FRAMES:
577 *data = g_variant_new_uint64(devc->limit_frames);
578 break;
4914dd4b 579 case SR_CONF_SAMPLERATE:
1cbb3b1c 580 *data = g_variant_new_uint64(devc->sample_rate);
4914dd4b 581 break;
2b0e4a46
AJ
582 case SR_CONF_TRIGGER_SOURCE:
583 if (!strcmp(devc->trigger_source, "ACL"))
584 tmp_str = "AC Line";
585 else if (!strcmp(devc->trigger_source, "CHAN1"))
586 tmp_str = "CH1";
587 else if (!strcmp(devc->trigger_source, "CHAN2"))
588 tmp_str = "CH2";
589 else if (!strcmp(devc->trigger_source, "CHAN3"))
590 tmp_str = "CH3";
591 else if (!strcmp(devc->trigger_source, "CHAN4"))
592 tmp_str = "CH4";
593 else
594 tmp_str = devc->trigger_source;
595 *data = g_variant_new_string(tmp_str);
596 break;
5d336f11 597 case SR_CONF_TRIGGER_SLOPE:
e1b5b7e7 598 if (!strncmp(devc->trigger_slope, "POS", 3)) {
5d336f11 599 tmp_str = "r";
e1b5b7e7 600 } else if (!strncmp(devc->trigger_slope, "NEG", 3)) {
5d336f11 601 tmp_str = "f";
e1b5b7e7
UH
602 } else {
603 sr_dbg("Unknown trigger slope: '%s'.", devc->trigger_slope);
5d336f11 604 return SR_ERR_NA;
e1b5b7e7 605 }
5d336f11
AJ
606 *data = g_variant_new_string(tmp_str);
607 break;
9ea62f2e
AJ
608 case SR_CONF_TRIGGER_LEVEL:
609 *data = g_variant_new_double(devc->trigger_level);
610 break;
2b0e4a46
AJ
611 case SR_CONF_TIMEBASE:
612 for (i = 0; i < devc->num_timebases; i++) {
613 float tb = (float)devc->timebases[i][0] / devc->timebases[i][1];
614 float diff = fabs(devc->timebase - tb);
615 if (diff < smallest_diff) {
616 smallest_diff = diff;
617 idx = i;
618 }
619 }
e1b5b7e7
UH
620 if (idx < 0) {
621 sr_dbg("Negative timebase index: %d.", idx);
2b0e4a46 622 return SR_ERR_NA;
e1b5b7e7 623 }
2b0e4a46
AJ
624 *data = g_variant_new("(tt)", devc->timebases[idx][0],
625 devc->timebases[idx][1]);
626 break;
627 case SR_CONF_VDIV:
e1b5b7e7
UH
628 if (analog_channel < 0) {
629 sr_dbg("Negative analog channel: %d.", analog_channel);
2b0e4a46 630 return SR_ERR_NA;
e1b5b7e7 631 }
2b0e4a46
AJ
632 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
633 float vdiv = (float)vdivs[i][0] / vdivs[i][1];
634 float diff = fabs(devc->vdiv[analog_channel] - vdiv);
635 if (diff < smallest_diff) {
636 smallest_diff = diff;
637 idx = i;
638 }
639 }
e1b5b7e7
UH
640 if (idx < 0) {
641 sr_dbg("Negative vdiv index: %d.", idx);
2b0e4a46 642 return SR_ERR_NA;
e1b5b7e7 643 }
2b0e4a46
AJ
644 *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]);
645 break;
646 case SR_CONF_COUPLING:
e1b5b7e7
UH
647 if (analog_channel < 0) {
648 sr_dbg("Negative analog channel: %d.", analog_channel);
2b0e4a46 649 return SR_ERR_NA;
e1b5b7e7 650 }
2b0e4a46
AJ
651 *data = g_variant_new_string(devc->coupling[analog_channel]);
652 break;
934cf6cf
AJ
653 case SR_CONF_PROBE_FACTOR:
654 if (analog_channel < 0) {
655 sr_dbg("Negative analog channel: %d.", analog_channel);
656 return SR_ERR_NA;
657 }
658 *data = g_variant_new_uint64(devc->attenuation[analog_channel]);
659 break;
d62d7ad1 660 default:
bd6fbf62 661 return SR_ERR_NA;
d62d7ad1
BV
662 }
663
664 return SR_OK;
665}
666
dd7a72ea
UH
667static int config_set(uint32_t key, GVariant *data,
668 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
f4816ac6 669{
29d957ce 670 struct dev_context *devc;
697fb6dd 671 uint64_t p;
254dd102 672 double t_dbl;
fcd6a8bd 673 int ret, idx, i;
254dd102 674 const char *tmp_str;
889ef4a0 675 char buffer[16];
f4816ac6 676
b0baddef 677 devc = sdi->priv;
29d957ce 678
660e398f 679 /* If a channel group is specified, it must be a valid one. */
53b4680f 680 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 681 sr_err("Invalid channel group specified.");
969edf63 682 return SR_ERR;
be60a9e4
BV
683 }
684
584560f1 685 switch (key) {
1953564a 686 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 687 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 688 break;
1953564a 689 case SR_CONF_TRIGGER_SLOPE:
697fb6dd 690 if ((idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_slopes))) < 0)
ca9b9f48 691 return SR_ERR_ARG;
254dd102 692 g_free(devc->trigger_slope);
697fb6dd 693 devc->trigger_slope = g_strdup((trigger_slopes[idx][0] == 'r') ? "POS" : "NEG");
758906aa 694 return rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
1953564a 695 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102 696 t_dbl = g_variant_get_double(data);
e1b5b7e7
UH
697 if (t_dbl < 0.0 || t_dbl > 1.0) {
698 sr_err("Invalid horiz. trigger position: %g.", t_dbl);
254dd102 699 return SR_ERR;
e1b5b7e7 700 }
254dd102
BV
701 devc->horiz_triggerpos = t_dbl;
702 /* We have the trigger offset as a percentage of the frame, but
703 * need to express this in seconds. */
bafd4890 704 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
889ef4a0 705 g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl);
0f523f2b
UH
706 return rigol_ds_config_set(sdi,
707 devc->model->cmds[CMD_SET_HORIZ_TRIGGERPOS].str, buffer);
9ea62f2e
AJ
708 case SR_CONF_TRIGGER_LEVEL:
709 t_dbl = g_variant_get_double(data);
710 g_ascii_formatd(buffer, sizeof(buffer), "%.3f", t_dbl);
711 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:LEV %s", buffer);
712 if (ret == SR_OK)
713 devc->trigger_level = t_dbl;
758906aa 714 return ret;
1953564a 715 case SR_CONF_TIMEBASE:
697fb6dd
UH
716 if ((idx = std_u64_tuple_idx(data, devc->timebases, devc->num_timebases)) < 0)
717 return SR_ERR_ARG;
718 devc->timebase = (float)devc->timebases[idx][0] / devc->timebases[idx][1];
719 g_ascii_formatd(buffer, sizeof(buffer), "%.9f",
720 devc->timebase);
758906aa 721 return rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer);
1953564a 722 case SR_CONF_TRIGGER_SOURCE:
6bcc81ac 723 if ((idx = std_str_idx(data, devc->model->trigger_sources, devc->model->num_trigger_sources)) < 0)
697fb6dd
UH
724 return SR_ERR_ARG;
725 g_free(devc->trigger_source);
6bcc81ac 726 devc->trigger_source = g_strdup(devc->model->trigger_sources[idx]);
697fb6dd
UH
727 if (!strcmp(devc->trigger_source, "AC Line"))
728 tmp_str = "ACL";
729 else if (!strcmp(devc->trigger_source, "CH1"))
730 tmp_str = "CHAN1";
731 else if (!strcmp(devc->trigger_source, "CH2"))
732 tmp_str = "CHAN2";
733 else if (!strcmp(devc->trigger_source, "CH3"))
734 tmp_str = "CHAN3";
735 else if (!strcmp(devc->trigger_source, "CH4"))
736 tmp_str = "CHAN4";
737 else
738 tmp_str = (char *)devc->trigger_source;
758906aa 739 return rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
1953564a 740 case SR_CONF_VDIV:
9e411f4b 741 if (!cg)
660e398f 742 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
743 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
744 return SR_ERR_ARG;
745 if ((idx = std_u64_tuple_idx(data, ARRAY_AND_SIZE(vdivs))) < 0)
746 return SR_ERR_ARG;
747 devc->vdiv[i] = (float)vdivs[idx][0] / vdivs[idx][1];
748 g_ascii_formatd(buffer, sizeof(buffer), "%.3f", devc->vdiv[i]);
749 return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1, buffer);
1953564a 750 case SR_CONF_COUPLING:
9e411f4b 751 if (!cg)
660e398f 752 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
753 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
754 return SR_ERR_ARG;
755 if ((idx = std_str_idx(data, ARRAY_AND_SIZE(coupling))) < 0)
756 return SR_ERR_ARG;
757 g_free(devc->coupling[i]);
758 devc->coupling[i] = g_strdup(coupling[idx]);
759 return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1, devc->coupling[i]);
934cf6cf 760 case SR_CONF_PROBE_FACTOR:
9e411f4b 761 if (!cg)
934cf6cf 762 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
763 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
764 return SR_ERR_ARG;
765 if ((idx = std_u64_idx(data, ARRAY_AND_SIZE(probe_factor))) < 0)
766 return SR_ERR_ARG;
934cf6cf 767 p = g_variant_get_uint64(data);
fcd6a8bd
UH
768 devc->attenuation[i] = probe_factor[idx];
769 ret = rigol_ds_config_set(sdi, ":CHAN%d:PROB %"PRIu64, i + 1, p);
770 if (ret == SR_OK)
771 rigol_ds_get_dev_cfg_vertical(sdi);
772 return ret;
babab622
ML
773 case SR_CONF_DATA_SOURCE:
774 tmp_str = g_variant_get_string(data, NULL);
775 if (!strcmp(tmp_str, "Live"))
776 devc->data_source = DATA_SOURCE_LIVE;
569d4dbd
ML
777 else if (devc->model->series->protocol >= PROTOCOL_V2
778 && !strcmp(tmp_str, "Memory"))
babab622 779 devc->data_source = DATA_SOURCE_MEMORY;
569d4dbd 780 else if (devc->model->series->protocol >= PROTOCOL_V3
babab622
ML
781 && !strcmp(tmp_str, "Segmented"))
782 devc->data_source = DATA_SOURCE_SEGMENTED;
e1b5b7e7
UH
783 else {
784 sr_err("Unknown data source: '%s'.", tmp_str);
babab622 785 return SR_ERR;
e1b5b7e7 786 }
babab622 787 break;
f4816ac6 788 default:
dcd438ee 789 return SR_ERR_NA;
f4816ac6
ML
790 }
791
758906aa 792 return SR_OK;
f4816ac6
ML
793}
794
dd7a72ea
UH
795static int config_list(uint32_t key, GVariant **data,
796 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
a1c743fc 797{
e66d1892 798 struct dev_context *devc;
e43fdd8d 799
e66d1892 800 devc = (sdi) ? sdi->priv : NULL;
be60a9e4 801
e43fdd8d 802 switch (key) {
e66d1892 803 case SR_CONF_SCAN_OPTIONS:
9a6517d1 804 case SR_CONF_DEVICE_OPTIONS:
e66d1892
UH
805 if (!cg)
806 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
0306ae30
GS
807 if (!devc)
808 return SR_ERR_ARG;
562b7ae5 809 if (cg == devc->digital_group) {
105df674 810 *data = std_gvar_array_u32(NULL, 0);
f48e0249
ML
811 return SR_OK;
812 } else {
fcd6a8bd
UH
813 if (std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels) < 0)
814 return SR_ERR_ARG;
815 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_analog));
816 return SR_OK;
f48e0249 817 }
5f77dffc 818 break;
2a7b113d 819 case SR_CONF_COUPLING:
e66d1892 820 if (!cg)
660e398f 821 return SR_ERR_CHANNEL_GROUP;
53012da6 822 *data = g_variant_new_strv(ARRAY_AND_SIZE(coupling));
58f43369 823 break;
934cf6cf 824 case SR_CONF_PROBE_FACTOR:
e66d1892 825 if (!cg)
934cf6cf 826 return SR_ERR_CHANNEL_GROUP;
53012da6 827 *data = std_gvar_array_u64(ARRAY_AND_SIZE(probe_factor));
934cf6cf 828 break;
e4f2b2ad 829 case SR_CONF_VDIV:
7cc1a550
ML
830 if (!devc)
831 /* Can't know this until we have the exact model. */
832 return SR_ERR_ARG;
e66d1892 833 if (!cg)
660e398f 834 return SR_ERR_CHANNEL_GROUP;
58ffcf97 835 *data = std_gvar_tuple_array(devc->vdivs, devc->num_vdivs);
58f43369 836 break;
41f5bd09 837 case SR_CONF_TIMEBASE:
7cc1a550
ML
838 if (!devc)
839 /* Can't know this until we have the exact model. */
840 return SR_ERR_ARG;
a31b2ccb
AJ
841 if (devc->num_timebases <= 0)
842 return SR_ERR_NA;
58ffcf97 843 *data = std_gvar_tuple_array(devc->timebases, devc->num_timebases);
41f5bd09 844 break;
328bafab 845 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
846 if (!devc)
847 /* Can't know this until we have the exact model. */
848 return SR_ERR_ARG;
6bcc81ac 849 *data = g_variant_new_strv(devc->model->trigger_sources, devc->model->num_trigger_sources);
328bafab 850 break;
5d336f11 851 case SR_CONF_TRIGGER_SLOPE:
53012da6 852 *data = g_variant_new_strv(ARRAY_AND_SIZE(trigger_slopes));
5d336f11 853 break;
babab622
ML
854 case SR_CONF_DATA_SOURCE:
855 if (!devc)
856 /* Can't know this until we have the exact model. */
857 return SR_ERR_ARG;
569d4dbd
ML
858 switch (devc->model->series->protocol) {
859 case PROTOCOL_V1:
860 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
861 break;
862 case PROTOCOL_V2:
babab622 863 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
569d4dbd
ML
864 break;
865 default:
53012da6 866 *data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
569d4dbd
ML
867 break;
868 }
babab622 869 break;
a1c743fc 870 default:
bd6fbf62 871 return SR_ERR_NA;
a1c743fc
BV
872 }
873
874 return SR_OK;
875}
876
695dc859 877static int dev_acquisition_start(const struct sr_dev_inst *sdi)
f4816ac6 878{
ae1bc1cc 879 struct sr_scpi_dev_inst *scpi;
29d957ce 880 struct dev_context *devc;
ba7dd8bb 881 struct sr_channel *ch;
702f42e8 882 gboolean some_digital;
254dd102 883 GSList *l;
f6129c8f 884 char *cmd;
06ed999a 885 int protocol;
713a3f35 886 int ret;
29d957ce 887
ae1bc1cc 888 scpi = sdi->conn;
29d957ce 889 devc = sdi->priv;
06ed999a 890 protocol = devc->model->series->protocol;
29d957ce 891
51b294cd 892 devc->num_frames = 0;
8cbe5339 893 devc->num_frames_segmented = 0;
51b294cd 894
702f42e8 895 some_digital = FALSE;
ba7dd8bb
UH
896 for (l = sdi->channels; l; l = l->next) {
897 ch = l->data;
898 sr_dbg("handling channel %s", ch->name);
3f239f08 899 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 900 if (ch->enabled)
702f42e8
ML
901 devc->enabled_channels = g_slist_append(
902 devc->enabled_channels, ch);
ba7dd8bb 903 if (ch->enabled != devc->analog_channels[ch->index]) {
6bb192bc 904 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
905 if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1,
906 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 907 return SR_ERR;
ba7dd8bb 908 devc->analog_channels[ch->index] = ch->enabled;
6bb192bc 909 }
3f239f08 910 } else if (ch->type == SR_CHANNEL_LOGIC) {
01dd7a4c
ML
911 /* Only one list entry for older protocols. All channels are
912 * retrieved together when this entry is processed. */
702f42e8 913 if (ch->enabled && (
06ed999a 914 protocol > PROTOCOL_V3 ||
702f42e8
ML
915 !some_digital))
916 devc->enabled_channels = g_slist_append(
917 devc->enabled_channels, ch);
ba7dd8bb 918 if (ch->enabled) {
702f42e8 919 some_digital = TRUE;
04e8e01e
ML
920 /* Turn on LA module if currently off. */
921 if (!devc->la_enabled) {
06ed999a 922 if (rigol_ds_config_set(sdi, protocol >= PROTOCOL_V3 ?
702f42e8 923 ":LA:STAT ON" : ":LA:DISP ON") != SR_OK)
04e8e01e
ML
924 return SR_ERR;
925 devc->la_enabled = TRUE;
926 }
927 }
ba7dd8bb 928 if (ch->enabled != devc->digital_channels[ch->index]) {
6bb192bc 929 /* Enabled channel is currently disabled, or vice versa. */
06ed999a 930 if (protocol >= PROTOCOL_V5)
f6129c8f 931 cmd = ":LA:DISP D%d,%s";
06ed999a 932 else if (protocol >= PROTOCOL_V3)
f6129c8f
SR
933 cmd = ":LA:DIG%d:DISP %s";
934 else
935 cmd = ":DIG%d:TURN %s";
936
937 if (rigol_ds_config_set(sdi, cmd, ch->index,
ba7dd8bb 938 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 939 return SR_ERR;
ba7dd8bb 940 devc->digital_channels[ch->index] = ch->enabled;
6bb192bc 941 }
254dd102
BV
942 }
943 }
1fed20cb 944
702f42e8 945 if (!devc->enabled_channels)
254dd102 946 return SR_ERR;
e0b7d23c 947
ba7dd8bb 948 /* Turn off LA module if on and no digital channels selected. */
702f42e8
ML
949 if (devc->la_enabled && !some_digital)
950 if (rigol_ds_config_set(sdi,
01dd7a4c 951 devc->model->series->protocol >= PROTOCOL_V3 ?
702f42e8 952 ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK)
04e8e01e
ML
953 return SR_ERR;
954
e086b750
ML
955 /* Set memory mode. */
956 if (devc->data_source == DATA_SOURCE_SEGMENTED) {
06ed999a
VO
957 switch (protocol) {
958 case PROTOCOL_V1:
959 case PROTOCOL_V2:
960 /* V1 and V2 do not have segmented data */
961 sr_err("Data source 'Segmented' not supported on this model");
962 break;
963 case PROTOCOL_V3:
19f31c8a
VO
964 case PROTOCOL_V4:
965 {
8cbe5339 966 int frames = 0;
06ed999a
VO
967 if (sr_scpi_get_int(sdi->conn,
968 protocol == PROTOCOL_V4 ? "FUNC:WREP:FEND?" :
969 "FUNC:WREP:FMAX?", &frames) != SR_OK)
970 return SR_ERR;
8cbe5339
VO
971 if (frames <= 0) {
972 sr_err("No segmented data available");
973 return SR_ERR;
974 }
975 devc->num_frames_segmented = frames;
19f31c8a
VO
976 break;
977 }
978 case PROTOCOL_V5:
979 /* The frame limit has to be read on the fly, just set up
980 * reading of the first frame */
981 if (rigol_ds_config_set(sdi, "REC:CURR 1") != SR_OK)
982 return SR_ERR;
983 break;
984 default:
8cbe5339
VO
985 sr_err("Data source 'Segmented' not yet supported");
986 return SR_ERR;
987 }
e086b750
ML
988 }
989
990 devc->analog_frame_size = analog_frame_size(sdi);
991 devc->digital_frame_size = digital_frame_size(sdi);
992
569d4dbd
ML
993 switch (devc->model->series->protocol) {
994 case PROTOCOL_V2:
99af83b7 995 if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK)
e086b750 996 return SR_ERR;
569d4dbd
ML
997 break;
998 case PROTOCOL_V3:
e086b750
ML
999 /* Apparently for the DS2000 the memory
1000 * depth can only be set in Running state -
1001 * this matches the behaviour of the UI. */
38354d9d 1002 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1fed20cb 1003 return SR_ERR;
e086b750
ML
1004 if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d",
1005 devc->analog_frame_size) != SR_OK)
1006 return SR_ERR;
1007 if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
1fed20cb 1008 return SR_ERR;
569d4dbd
ML
1009 break;
1010 default:
1011 break;
1fed20cb
ML
1012 }
1013
e086b750
ML
1014 if (devc->data_source == DATA_SOURCE_LIVE)
1015 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1016 return SR_ERR;
1017
102f1239
BV
1018 sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
1019 rigol_ds_receive, (void *)sdi);
e0b7d23c 1020
bee2b016 1021 std_session_send_df_header(sdi);
e0b7d23c 1022
702f42e8 1023 devc->channel_entry = devc->enabled_channels;
821fbcad 1024
713a3f35
GS
1025 if (devc->data_source == DATA_SOURCE_LIVE) {
1026 devc->sample_rate = analog_frame_size(sdi) /
1cbb3b1c 1027 (devc->timebase * devc->model->series->num_horizontal_divs);
713a3f35 1028 } else {
1cbb3b1c 1029 float xinc;
713a3f35
GS
1030 if (devc->model->series->protocol < PROTOCOL_V3) {
1031 sr_err("Cannot get samplerate (below V3).");
1032 return SR_ERR;
1033 }
1034 ret = sr_scpi_get_float(sdi->conn, "WAV:XINC?", &xinc);
1035 if (ret != SR_OK) {
1036 sr_err("Cannot get samplerate (WAV:XINC? failed).");
1037 return SR_ERR;
1038 }
1039 if (!xinc) {
1040 sr_err("Cannot get samplerate (zero XINC value).");
1cbb3b1c
VO
1041 return SR_ERR;
1042 }
1043 devc->sample_rate = 1. / xinc;
1044 }
1045
e086b750
ML
1046 if (rigol_ds_capture_start(sdi) != SR_OK)
1047 return SR_ERR;
f4816ac6 1048
f76c24f6 1049 /* Start of first frame. */
4c5f7006 1050 std_session_send_df_frame_begin(sdi);
f76c24f6 1051
f4816ac6
ML
1052 return SR_OK;
1053}
1054
695dc859 1055static int dev_acquisition_stop(struct sr_dev_inst *sdi)
f4816ac6 1056{
29d957ce 1057 struct dev_context *devc;
ae1bc1cc 1058 struct sr_scpi_dev_inst *scpi;
29d957ce 1059
29d957ce
UH
1060 devc = sdi->priv;
1061
bee2b016 1062 std_session_send_df_end(sdi);
b751cf7a 1063
702f42e8
ML
1064 g_slist_free(devc->enabled_channels);
1065 devc->enabled_channels = NULL;
ae1bc1cc 1066 scpi = sdi->conn;
102f1239 1067 sr_scpi_source_remove(sdi->session, scpi);
f4816ac6
ML
1068
1069 return SR_OK;
1070}
1071
dd5c48a6 1072static struct sr_dev_driver rigol_ds_driver_info = {
3086efdd
ML
1073 .name = "rigol-ds",
1074 .longname = "Rigol DS",
f4816ac6 1075 .api_version = 1,
c2fdcc25 1076 .init = std_init,
700d6b64 1077 .cleanup = std_cleanup,
6078d2c9 1078 .scan = scan,
c01bf34c 1079 .dev_list = std_dev_list,
3b412e3a 1080 .dev_clear = dev_clear,
d62d7ad1 1081 .config_get = config_get,
035a1078 1082 .config_set = config_set,
a1c743fc 1083 .config_list = config_list,
6078d2c9
UH
1084 .dev_open = dev_open,
1085 .dev_close = dev_close,
254dd102
BV
1086 .dev_acquisition_start = dev_acquisition_start,
1087 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 1088 .context = NULL,
f4816ac6 1089};
dd5c48a6 1090SR_REGISTER_DEV_DRIVER(rigol_ds_driver_info);