]> sigrok.org Git - libsigrok.git/blame - src/hardware/rigol-ds/api.c
tcp: check for poll(2) and select(2), workaround for shutdown(2) API
[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 397
d810901a
GS
398 devc->analog_groups[i] = sr_channel_group_new(sdi,
399 channel_name, NULL);
562b7ae5 400 devc->analog_groups[i]->channels = g_slist_append(NULL, ch);
ca55277c 401 }
512bb890 402
bafd4890 403 if (devc->model->has_digital) {
d810901a 404 devc->digital_group = sr_channel_group_new(sdi, "LA", NULL);
effb9dd1 405 for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) {
eac0c613 406 channel_name = g_strdup_printf("D%d", i);
5e23fcab 407 ch = sr_channel_new(sdi, i, SR_CHANNEL_LOGIC, TRUE, channel_name);
ca55277c 408 g_free(channel_name);
562b7ae5
SA
409 devc->digital_group->channels = g_slist_append(
410 devc->digital_group->channels, ch);
512bb890 411 }
ca55277c 412 }
bafd4890 413
396cdca0 414 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
bafd4890
ML
415 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
416 devc->timebases = &timebases[i];
569d4dbd 417 if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2])))
bafd4890
ML
418 devc->num_timebases = &timebases[i] - devc->timebases + 1;
419 }
420
396cdca0 421 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
a95f142e
UH
422 if (!memcmp(&devc->model->series->min_vdiv,
423 &vdivs[i], sizeof(uint64_t[2]))) {
6ff1394e 424 devc->vdivs = &vdivs[i];
396cdca0 425 devc->num_vdivs = ARRAY_SIZE(vdivs) - i;
81b85663 426 }
a95f142e 427 }
bafd4890 428
a95f142e
UH
429 devc->buffer = g_malloc(ACQ_BUFFER_SIZE);
430 devc->data = g_malloc(ACQ_BUFFER_SIZE * sizeof(float));
babab622
ML
431
432 devc->data_source = DATA_SOURCE_LIVE;
433
cc9fd2d2
BV
434 sdi->priv = devc;
435
9d3ae01b 436 return sdi;
ca55277c 437}
512bb890 438
4f840ce9 439static GSList *scan(struct sr_dev_driver *di, GSList *options)
ca55277c 440{
41812aca 441 return sr_scpi_scan(di->context, options, probe_device);
f4816ac6
ML
442}
443
6078d2c9 444static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 445{
e1b5b7e7 446 int ret;
ae1bc1cc 447 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 448
e1b5b7e7
UH
449 if ((ret = sr_scpi_open(scpi)) < 0) {
450 sr_err("Failed to open SCPI device: %s.", sr_strerror(ret));
e0b7d23c 451 return SR_ERR;
e1b5b7e7 452 }
e0b7d23c 453
e1b5b7e7
UH
454 if ((ret = rigol_ds_get_dev_cfg(sdi)) < 0) {
455 sr_err("Failed to get device config: %s.", sr_strerror(ret));
254dd102 456 return SR_ERR;
e1b5b7e7 457 }
f4816ac6
ML
458
459 return SR_OK;
460}
461
6078d2c9 462static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 463{
ae1bc1cc 464 struct sr_scpi_dev_inst *scpi;
22c19688 465 struct dev_context *devc;
ae1bc1cc
ML
466
467 scpi = sdi->conn;
22c19688
ML
468 devc = sdi->priv;
469
f1ba6b4b
UH
470 if (!scpi)
471 return SR_ERR_BUG;
472
6e94eb41 473 if (devc->model->series->protocol == PROTOCOL_V2)
38354d9d 474 rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE");
e0b7d23c 475
f1ba6b4b 476 return sr_scpi_close(scpi);
f4816ac6
ML
477}
478
5415e602
ML
479static int analog_frame_size(const struct sr_dev_inst *sdi)
480{
481 struct dev_context *devc = sdi->priv;
ba7dd8bb
UH
482 struct sr_channel *ch;
483 int analog_channels = 0;
5415e602
ML
484 GSList *l;
485
ba7dd8bb
UH
486 for (l = sdi->channels; l; l = l->next) {
487 ch = l->data;
3f239f08 488 if (ch->type == SR_CHANNEL_ANALOG && ch->enabled)
ba7dd8bb 489 analog_channels++;
569d4dbd
ML
490 }
491
ba7dd8bb 492 if (analog_channels == 0)
824eb2ac
ML
493 return 0;
494
569d4dbd
ML
495 switch (devc->data_source) {
496 case DATA_SOURCE_LIVE:
497 return devc->model->series->live_samples;
498 case DATA_SOURCE_MEMORY:
8cbe5339 499 case DATA_SOURCE_SEGMENTED:
ba7dd8bb 500 return devc->model->series->buffer_samples / analog_channels;
470140fc 501 default:
569d4dbd 502 return 0;
5415e602
ML
503 }
504}
505
d22250a9
ML
506static int digital_frame_size(const struct sr_dev_inst *sdi)
507{
508 struct dev_context *devc = sdi->priv;
509
569d4dbd
ML
510 switch (devc->data_source) {
511 case DATA_SOURCE_LIVE:
512 return devc->model->series->live_samples * 2;
513 case DATA_SOURCE_MEMORY:
8cbe5339 514 case DATA_SOURCE_SEGMENTED:
569d4dbd 515 return devc->model->series->buffer_samples * 2;
d22250a9
ML
516 default:
517 return 0;
518 }
519}
520
dd7a72ea
UH
521static int config_get(uint32_t key, GVariant **data,
522 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
d62d7ad1 523{
e43fdd8d 524 struct dev_context *devc;
ba7dd8bb 525 struct sr_channel *ch;
2b0e4a46 526 const char *tmp_str;
2b0e4a46 527 int analog_channel = -1;
c33ff377 528 float smallest_diff = INFINITY;
2b0e4a46
AJ
529 int idx = -1;
530 unsigned i;
d62d7ad1 531
709468ba 532 if (!sdi)
e43fdd8d
BV
533 return SR_ERR_ARG;
534
709468ba
UH
535 devc = sdi->priv;
536
660e398f 537 /* If a channel group is specified, it must be a valid one. */
53b4680f 538 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 539 sr_err("Invalid channel group specified.");
969edf63 540 return SR_ERR;
be60a9e4
BV
541 }
542
53b4680f 543 if (cg) {
ba7dd8bb
UH
544 ch = g_slist_nth_data(cg->channels, 0);
545 if (!ch)
2b0e4a46 546 return SR_ERR;
3f239f08 547 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 548 if (ch->name[2] < '1' || ch->name[2] > '4')
2b0e4a46 549 return SR_ERR;
ba7dd8bb 550 analog_channel = ch->name[2] - '1';
2b0e4a46
AJ
551 }
552 }
553
584560f1 554 switch (key) {
bf622e6d 555 case SR_CONF_NUM_HDIV:
569d4dbd 556 *data = g_variant_new_int32(devc->model->series->num_horizontal_divs);
d62d7ad1
BV
557 break;
558 case SR_CONF_NUM_VDIV:
81b85663 559 *data = g_variant_new_int32(devc->num_vdivs);
f44f7e61 560 break;
babab622
ML
561 case SR_CONF_DATA_SOURCE:
562 if (devc->data_source == DATA_SOURCE_LIVE)
563 *data = g_variant_new_string("Live");
564 else if (devc->data_source == DATA_SOURCE_MEMORY)
565 *data = g_variant_new_string("Memory");
566 else
567 *data = g_variant_new_string("Segmented");
568 break;
1b8a37c6
VO
569 case SR_CONF_LIMIT_FRAMES:
570 *data = g_variant_new_uint64(devc->limit_frames);
571 break;
4914dd4b 572 case SR_CONF_SAMPLERATE:
1cbb3b1c 573 *data = g_variant_new_uint64(devc->sample_rate);
4914dd4b 574 break;
2b0e4a46
AJ
575 case SR_CONF_TRIGGER_SOURCE:
576 if (!strcmp(devc->trigger_source, "ACL"))
577 tmp_str = "AC Line";
578 else if (!strcmp(devc->trigger_source, "CHAN1"))
579 tmp_str = "CH1";
580 else if (!strcmp(devc->trigger_source, "CHAN2"))
581 tmp_str = "CH2";
582 else if (!strcmp(devc->trigger_source, "CHAN3"))
583 tmp_str = "CH3";
584 else if (!strcmp(devc->trigger_source, "CHAN4"))
585 tmp_str = "CH4";
586 else
587 tmp_str = devc->trigger_source;
588 *data = g_variant_new_string(tmp_str);
589 break;
5d336f11 590 case SR_CONF_TRIGGER_SLOPE:
e1b5b7e7 591 if (!strncmp(devc->trigger_slope, "POS", 3)) {
5d336f11 592 tmp_str = "r";
e1b5b7e7 593 } else if (!strncmp(devc->trigger_slope, "NEG", 3)) {
5d336f11 594 tmp_str = "f";
e1b5b7e7
UH
595 } else {
596 sr_dbg("Unknown trigger slope: '%s'.", devc->trigger_slope);
5d336f11 597 return SR_ERR_NA;
e1b5b7e7 598 }
5d336f11
AJ
599 *data = g_variant_new_string(tmp_str);
600 break;
9ea62f2e
AJ
601 case SR_CONF_TRIGGER_LEVEL:
602 *data = g_variant_new_double(devc->trigger_level);
603 break;
2b0e4a46
AJ
604 case SR_CONF_TIMEBASE:
605 for (i = 0; i < devc->num_timebases; i++) {
606 float tb = (float)devc->timebases[i][0] / devc->timebases[i][1];
607 float diff = fabs(devc->timebase - tb);
608 if (diff < smallest_diff) {
609 smallest_diff = diff;
610 idx = i;
611 }
612 }
e1b5b7e7
UH
613 if (idx < 0) {
614 sr_dbg("Negative timebase index: %d.", idx);
2b0e4a46 615 return SR_ERR_NA;
e1b5b7e7 616 }
2b0e4a46
AJ
617 *data = g_variant_new("(tt)", devc->timebases[idx][0],
618 devc->timebases[idx][1]);
619 break;
620 case SR_CONF_VDIV:
e1b5b7e7
UH
621 if (analog_channel < 0) {
622 sr_dbg("Negative analog channel: %d.", analog_channel);
2b0e4a46 623 return SR_ERR_NA;
e1b5b7e7 624 }
2b0e4a46
AJ
625 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
626 float vdiv = (float)vdivs[i][0] / vdivs[i][1];
627 float diff = fabs(devc->vdiv[analog_channel] - vdiv);
628 if (diff < smallest_diff) {
629 smallest_diff = diff;
630 idx = i;
631 }
632 }
e1b5b7e7
UH
633 if (idx < 0) {
634 sr_dbg("Negative vdiv index: %d.", idx);
2b0e4a46 635 return SR_ERR_NA;
e1b5b7e7 636 }
2b0e4a46
AJ
637 *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]);
638 break;
639 case SR_CONF_COUPLING:
e1b5b7e7
UH
640 if (analog_channel < 0) {
641 sr_dbg("Negative analog channel: %d.", analog_channel);
2b0e4a46 642 return SR_ERR_NA;
e1b5b7e7 643 }
2b0e4a46
AJ
644 *data = g_variant_new_string(devc->coupling[analog_channel]);
645 break;
934cf6cf
AJ
646 case SR_CONF_PROBE_FACTOR:
647 if (analog_channel < 0) {
648 sr_dbg("Negative analog channel: %d.", analog_channel);
649 return SR_ERR_NA;
650 }
651 *data = g_variant_new_uint64(devc->attenuation[analog_channel]);
652 break;
d62d7ad1 653 default:
bd6fbf62 654 return SR_ERR_NA;
d62d7ad1
BV
655 }
656
657 return SR_OK;
658}
659
dd7a72ea
UH
660static int config_set(uint32_t key, GVariant *data,
661 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
f4816ac6 662{
29d957ce 663 struct dev_context *devc;
697fb6dd 664 uint64_t p;
254dd102 665 double t_dbl;
fcd6a8bd 666 int ret, idx, i;
254dd102 667 const char *tmp_str;
889ef4a0 668 char buffer[16];
f4816ac6 669
b0baddef 670 devc = sdi->priv;
29d957ce 671
660e398f 672 /* If a channel group is specified, it must be a valid one. */
53b4680f 673 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 674 sr_err("Invalid channel group specified.");
969edf63 675 return SR_ERR;
be60a9e4
BV
676 }
677
584560f1 678 switch (key) {
1953564a 679 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 680 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 681 break;
1953564a 682 case SR_CONF_TRIGGER_SLOPE:
697fb6dd 683 if ((idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_slopes))) < 0)
ca9b9f48 684 return SR_ERR_ARG;
254dd102 685 g_free(devc->trigger_slope);
697fb6dd 686 devc->trigger_slope = g_strdup((trigger_slopes[idx][0] == 'r') ? "POS" : "NEG");
758906aa 687 return rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
1953564a 688 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102 689 t_dbl = g_variant_get_double(data);
e1b5b7e7
UH
690 if (t_dbl < 0.0 || t_dbl > 1.0) {
691 sr_err("Invalid horiz. trigger position: %g.", t_dbl);
254dd102 692 return SR_ERR;
e1b5b7e7 693 }
254dd102
BV
694 devc->horiz_triggerpos = t_dbl;
695 /* We have the trigger offset as a percentage of the frame, but
696 * need to express this in seconds. */
bafd4890 697 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
889ef4a0 698 g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl);
0f523f2b
UH
699 return rigol_ds_config_set(sdi,
700 devc->model->cmds[CMD_SET_HORIZ_TRIGGERPOS].str, buffer);
9ea62f2e
AJ
701 case SR_CONF_TRIGGER_LEVEL:
702 t_dbl = g_variant_get_double(data);
703 g_ascii_formatd(buffer, sizeof(buffer), "%.3f", t_dbl);
704 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:LEV %s", buffer);
705 if (ret == SR_OK)
706 devc->trigger_level = t_dbl;
758906aa 707 return ret;
1953564a 708 case SR_CONF_TIMEBASE:
697fb6dd
UH
709 if ((idx = std_u64_tuple_idx(data, devc->timebases, devc->num_timebases)) < 0)
710 return SR_ERR_ARG;
711 devc->timebase = (float)devc->timebases[idx][0] / devc->timebases[idx][1];
712 g_ascii_formatd(buffer, sizeof(buffer), "%.9f",
713 devc->timebase);
758906aa 714 return rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer);
1953564a 715 case SR_CONF_TRIGGER_SOURCE:
6bcc81ac 716 if ((idx = std_str_idx(data, devc->model->trigger_sources, devc->model->num_trigger_sources)) < 0)
697fb6dd
UH
717 return SR_ERR_ARG;
718 g_free(devc->trigger_source);
6bcc81ac 719 devc->trigger_source = g_strdup(devc->model->trigger_sources[idx]);
697fb6dd
UH
720 if (!strcmp(devc->trigger_source, "AC Line"))
721 tmp_str = "ACL";
722 else if (!strcmp(devc->trigger_source, "CH1"))
723 tmp_str = "CHAN1";
724 else if (!strcmp(devc->trigger_source, "CH2"))
725 tmp_str = "CHAN2";
726 else if (!strcmp(devc->trigger_source, "CH3"))
727 tmp_str = "CHAN3";
728 else if (!strcmp(devc->trigger_source, "CH4"))
729 tmp_str = "CHAN4";
730 else
731 tmp_str = (char *)devc->trigger_source;
758906aa 732 return rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
1953564a 733 case SR_CONF_VDIV:
9e411f4b 734 if (!cg)
660e398f 735 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
736 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
737 return SR_ERR_ARG;
738 if ((idx = std_u64_tuple_idx(data, ARRAY_AND_SIZE(vdivs))) < 0)
739 return SR_ERR_ARG;
740 devc->vdiv[i] = (float)vdivs[idx][0] / vdivs[idx][1];
741 g_ascii_formatd(buffer, sizeof(buffer), "%.3f", devc->vdiv[i]);
742 return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1, buffer);
1953564a 743 case SR_CONF_COUPLING:
9e411f4b 744 if (!cg)
660e398f 745 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
746 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
747 return SR_ERR_ARG;
748 if ((idx = std_str_idx(data, ARRAY_AND_SIZE(coupling))) < 0)
749 return SR_ERR_ARG;
750 g_free(devc->coupling[i]);
751 devc->coupling[i] = g_strdup(coupling[idx]);
752 return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1, devc->coupling[i]);
934cf6cf 753 case SR_CONF_PROBE_FACTOR:
9e411f4b 754 if (!cg)
934cf6cf 755 return SR_ERR_CHANNEL_GROUP;
fcd6a8bd
UH
756 if ((i = std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels)) < 0)
757 return SR_ERR_ARG;
758 if ((idx = std_u64_idx(data, ARRAY_AND_SIZE(probe_factor))) < 0)
759 return SR_ERR_ARG;
934cf6cf 760 p = g_variant_get_uint64(data);
fcd6a8bd
UH
761 devc->attenuation[i] = probe_factor[idx];
762 ret = rigol_ds_config_set(sdi, ":CHAN%d:PROB %"PRIu64, i + 1, p);
763 if (ret == SR_OK)
764 rigol_ds_get_dev_cfg_vertical(sdi);
765 return ret;
babab622
ML
766 case SR_CONF_DATA_SOURCE:
767 tmp_str = g_variant_get_string(data, NULL);
768 if (!strcmp(tmp_str, "Live"))
769 devc->data_source = DATA_SOURCE_LIVE;
569d4dbd
ML
770 else if (devc->model->series->protocol >= PROTOCOL_V2
771 && !strcmp(tmp_str, "Memory"))
babab622 772 devc->data_source = DATA_SOURCE_MEMORY;
569d4dbd 773 else if (devc->model->series->protocol >= PROTOCOL_V3
babab622
ML
774 && !strcmp(tmp_str, "Segmented"))
775 devc->data_source = DATA_SOURCE_SEGMENTED;
e1b5b7e7
UH
776 else {
777 sr_err("Unknown data source: '%s'.", tmp_str);
babab622 778 return SR_ERR;
e1b5b7e7 779 }
babab622 780 break;
f4816ac6 781 default:
dcd438ee 782 return SR_ERR_NA;
f4816ac6
ML
783 }
784
758906aa 785 return SR_OK;
f4816ac6
ML
786}
787
dd7a72ea
UH
788static int config_list(uint32_t key, GVariant **data,
789 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
a1c743fc 790{
e66d1892 791 struct dev_context *devc;
e43fdd8d 792
e66d1892 793 devc = (sdi) ? sdi->priv : NULL;
be60a9e4 794
e43fdd8d 795 switch (key) {
e66d1892 796 case SR_CONF_SCAN_OPTIONS:
9a6517d1 797 case SR_CONF_DEVICE_OPTIONS:
e66d1892
UH
798 if (!cg)
799 return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
0306ae30
GS
800 if (!devc)
801 return SR_ERR_ARG;
562b7ae5 802 if (cg == devc->digital_group) {
105df674 803 *data = std_gvar_array_u32(NULL, 0);
f48e0249
ML
804 return SR_OK;
805 } else {
fcd6a8bd
UH
806 if (std_cg_idx(cg, devc->analog_groups, devc->model->analog_channels) < 0)
807 return SR_ERR_ARG;
808 *data = std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg_analog));
809 return SR_OK;
f48e0249 810 }
5f77dffc 811 break;
2a7b113d 812 case SR_CONF_COUPLING:
e66d1892 813 if (!cg)
660e398f 814 return SR_ERR_CHANNEL_GROUP;
53012da6 815 *data = g_variant_new_strv(ARRAY_AND_SIZE(coupling));
58f43369 816 break;
934cf6cf 817 case SR_CONF_PROBE_FACTOR:
e66d1892 818 if (!cg)
934cf6cf 819 return SR_ERR_CHANNEL_GROUP;
53012da6 820 *data = std_gvar_array_u64(ARRAY_AND_SIZE(probe_factor));
934cf6cf 821 break;
e4f2b2ad 822 case SR_CONF_VDIV:
7cc1a550
ML
823 if (!devc)
824 /* Can't know this until we have the exact model. */
825 return SR_ERR_ARG;
e66d1892 826 if (!cg)
660e398f 827 return SR_ERR_CHANNEL_GROUP;
58ffcf97 828 *data = std_gvar_tuple_array(devc->vdivs, devc->num_vdivs);
58f43369 829 break;
41f5bd09 830 case SR_CONF_TIMEBASE:
7cc1a550
ML
831 if (!devc)
832 /* Can't know this until we have the exact model. */
833 return SR_ERR_ARG;
a31b2ccb
AJ
834 if (devc->num_timebases <= 0)
835 return SR_ERR_NA;
58ffcf97 836 *data = std_gvar_tuple_array(devc->timebases, devc->num_timebases);
41f5bd09 837 break;
328bafab 838 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
839 if (!devc)
840 /* Can't know this until we have the exact model. */
841 return SR_ERR_ARG;
6bcc81ac 842 *data = g_variant_new_strv(devc->model->trigger_sources, devc->model->num_trigger_sources);
328bafab 843 break;
5d336f11 844 case SR_CONF_TRIGGER_SLOPE:
53012da6 845 *data = g_variant_new_strv(ARRAY_AND_SIZE(trigger_slopes));
5d336f11 846 break;
babab622
ML
847 case SR_CONF_DATA_SOURCE:
848 if (!devc)
849 /* Can't know this until we have the exact model. */
850 return SR_ERR_ARG;
569d4dbd
ML
851 switch (devc->model->series->protocol) {
852 case PROTOCOL_V1:
853 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
854 break;
855 case PROTOCOL_V2:
babab622 856 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
569d4dbd
ML
857 break;
858 default:
53012da6 859 *data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources));
569d4dbd
ML
860 break;
861 }
babab622 862 break;
a1c743fc 863 default:
bd6fbf62 864 return SR_ERR_NA;
a1c743fc
BV
865 }
866
867 return SR_OK;
868}
869
695dc859 870static int dev_acquisition_start(const struct sr_dev_inst *sdi)
f4816ac6 871{
ae1bc1cc 872 struct sr_scpi_dev_inst *scpi;
29d957ce 873 struct dev_context *devc;
ba7dd8bb 874 struct sr_channel *ch;
702f42e8 875 gboolean some_digital;
254dd102 876 GSList *l;
f6129c8f 877 char *cmd;
06ed999a 878 int protocol;
713a3f35 879 int ret;
29d957ce 880
ae1bc1cc 881 scpi = sdi->conn;
29d957ce 882 devc = sdi->priv;
06ed999a 883 protocol = devc->model->series->protocol;
29d957ce 884
51b294cd 885 devc->num_frames = 0;
8cbe5339 886 devc->num_frames_segmented = 0;
51b294cd 887
702f42e8 888 some_digital = FALSE;
ba7dd8bb
UH
889 for (l = sdi->channels; l; l = l->next) {
890 ch = l->data;
891 sr_dbg("handling channel %s", ch->name);
3f239f08 892 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 893 if (ch->enabled)
702f42e8
ML
894 devc->enabled_channels = g_slist_append(
895 devc->enabled_channels, ch);
ba7dd8bb 896 if (ch->enabled != devc->analog_channels[ch->index]) {
6bb192bc 897 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
898 if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1,
899 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 900 return SR_ERR;
ba7dd8bb 901 devc->analog_channels[ch->index] = ch->enabled;
6bb192bc 902 }
3f239f08 903 } else if (ch->type == SR_CHANNEL_LOGIC) {
01dd7a4c
ML
904 /* Only one list entry for older protocols. All channels are
905 * retrieved together when this entry is processed. */
702f42e8 906 if (ch->enabled && (
06ed999a 907 protocol > PROTOCOL_V3 ||
702f42e8
ML
908 !some_digital))
909 devc->enabled_channels = g_slist_append(
910 devc->enabled_channels, ch);
ba7dd8bb 911 if (ch->enabled) {
702f42e8 912 some_digital = TRUE;
04e8e01e
ML
913 /* Turn on LA module if currently off. */
914 if (!devc->la_enabled) {
06ed999a 915 if (rigol_ds_config_set(sdi, protocol >= PROTOCOL_V3 ?
702f42e8 916 ":LA:STAT ON" : ":LA:DISP ON") != SR_OK)
04e8e01e
ML
917 return SR_ERR;
918 devc->la_enabled = TRUE;
919 }
920 }
ba7dd8bb 921 if (ch->enabled != devc->digital_channels[ch->index]) {
6bb192bc 922 /* Enabled channel is currently disabled, or vice versa. */
06ed999a 923 if (protocol >= PROTOCOL_V5)
f6129c8f 924 cmd = ":LA:DISP D%d,%s";
06ed999a 925 else if (protocol >= PROTOCOL_V3)
f6129c8f
SR
926 cmd = ":LA:DIG%d:DISP %s";
927 else
928 cmd = ":DIG%d:TURN %s";
929
930 if (rigol_ds_config_set(sdi, cmd, ch->index,
ba7dd8bb 931 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 932 return SR_ERR;
ba7dd8bb 933 devc->digital_channels[ch->index] = ch->enabled;
6bb192bc 934 }
254dd102
BV
935 }
936 }
1fed20cb 937
702f42e8 938 if (!devc->enabled_channels)
254dd102 939 return SR_ERR;
e0b7d23c 940
ba7dd8bb 941 /* Turn off LA module if on and no digital channels selected. */
702f42e8
ML
942 if (devc->la_enabled && !some_digital)
943 if (rigol_ds_config_set(sdi,
01dd7a4c 944 devc->model->series->protocol >= PROTOCOL_V3 ?
702f42e8 945 ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK)
04e8e01e
ML
946 return SR_ERR;
947
e086b750
ML
948 /* Set memory mode. */
949 if (devc->data_source == DATA_SOURCE_SEGMENTED) {
06ed999a
VO
950 switch (protocol) {
951 case PROTOCOL_V1:
952 case PROTOCOL_V2:
953 /* V1 and V2 do not have segmented data */
954 sr_err("Data source 'Segmented' not supported on this model");
955 break;
956 case PROTOCOL_V3:
19f31c8a
VO
957 case PROTOCOL_V4:
958 {
8cbe5339 959 int frames = 0;
06ed999a
VO
960 if (sr_scpi_get_int(sdi->conn,
961 protocol == PROTOCOL_V4 ? "FUNC:WREP:FEND?" :
962 "FUNC:WREP:FMAX?", &frames) != SR_OK)
963 return SR_ERR;
8cbe5339
VO
964 if (frames <= 0) {
965 sr_err("No segmented data available");
966 return SR_ERR;
967 }
968 devc->num_frames_segmented = frames;
19f31c8a
VO
969 break;
970 }
971 case PROTOCOL_V5:
972 /* The frame limit has to be read on the fly, just set up
973 * reading of the first frame */
974 if (rigol_ds_config_set(sdi, "REC:CURR 1") != SR_OK)
975 return SR_ERR;
976 break;
977 default:
8cbe5339
VO
978 sr_err("Data source 'Segmented' not yet supported");
979 return SR_ERR;
980 }
e086b750
ML
981 }
982
983 devc->analog_frame_size = analog_frame_size(sdi);
984 devc->digital_frame_size = digital_frame_size(sdi);
985
569d4dbd
ML
986 switch (devc->model->series->protocol) {
987 case PROTOCOL_V2:
99af83b7 988 if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK)
e086b750 989 return SR_ERR;
569d4dbd
ML
990 break;
991 case PROTOCOL_V3:
e086b750
ML
992 /* Apparently for the DS2000 the memory
993 * depth can only be set in Running state -
994 * this matches the behaviour of the UI. */
38354d9d 995 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1fed20cb 996 return SR_ERR;
e086b750
ML
997 if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d",
998 devc->analog_frame_size) != SR_OK)
999 return SR_ERR;
1000 if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
1fed20cb 1001 return SR_ERR;
569d4dbd
ML
1002 break;
1003 default:
1004 break;
1fed20cb
ML
1005 }
1006
e086b750
ML
1007 if (devc->data_source == DATA_SOURCE_LIVE)
1008 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1009 return SR_ERR;
1010
102f1239
BV
1011 sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
1012 rigol_ds_receive, (void *)sdi);
e0b7d23c 1013
bee2b016 1014 std_session_send_df_header(sdi);
e0b7d23c 1015
702f42e8 1016 devc->channel_entry = devc->enabled_channels;
821fbcad 1017
713a3f35
GS
1018 if (devc->data_source == DATA_SOURCE_LIVE) {
1019 devc->sample_rate = analog_frame_size(sdi) /
1cbb3b1c 1020 (devc->timebase * devc->model->series->num_horizontal_divs);
713a3f35 1021 } else {
1cbb3b1c 1022 float xinc;
713a3f35
GS
1023 if (devc->model->series->protocol < PROTOCOL_V3) {
1024 sr_err("Cannot get samplerate (below V3).");
1025 return SR_ERR;
1026 }
1027 ret = sr_scpi_get_float(sdi->conn, "WAV:XINC?", &xinc);
1028 if (ret != SR_OK) {
1029 sr_err("Cannot get samplerate (WAV:XINC? failed).");
1030 return SR_ERR;
1031 }
1032 if (!xinc) {
1033 sr_err("Cannot get samplerate (zero XINC value).");
1cbb3b1c
VO
1034 return SR_ERR;
1035 }
1036 devc->sample_rate = 1. / xinc;
1037 }
1038
e086b750
ML
1039 if (rigol_ds_capture_start(sdi) != SR_OK)
1040 return SR_ERR;
f4816ac6 1041
f76c24f6 1042 /* Start of first frame. */
4c5f7006 1043 std_session_send_df_frame_begin(sdi);
f76c24f6 1044
f4816ac6
ML
1045 return SR_OK;
1046}
1047
695dc859 1048static int dev_acquisition_stop(struct sr_dev_inst *sdi)
f4816ac6 1049{
29d957ce 1050 struct dev_context *devc;
ae1bc1cc 1051 struct sr_scpi_dev_inst *scpi;
29d957ce 1052
29d957ce
UH
1053 devc = sdi->priv;
1054
bee2b016 1055 std_session_send_df_end(sdi);
b751cf7a 1056
702f42e8
ML
1057 g_slist_free(devc->enabled_channels);
1058 devc->enabled_channels = NULL;
ae1bc1cc 1059 scpi = sdi->conn;
102f1239 1060 sr_scpi_source_remove(sdi->session, scpi);
f4816ac6
ML
1061
1062 return SR_OK;
1063}
1064
dd5c48a6 1065static struct sr_dev_driver rigol_ds_driver_info = {
3086efdd
ML
1066 .name = "rigol-ds",
1067 .longname = "Rigol DS",
f4816ac6 1068 .api_version = 1,
c2fdcc25 1069 .init = std_init,
700d6b64 1070 .cleanup = std_cleanup,
6078d2c9 1071 .scan = scan,
c01bf34c 1072 .dev_list = std_dev_list,
3b412e3a 1073 .dev_clear = dev_clear,
d62d7ad1 1074 .config_get = config_get,
035a1078 1075 .config_set = config_set,
a1c743fc 1076 .config_list = config_list,
6078d2c9
UH
1077 .dev_open = dev_open,
1078 .dev_close = dev_close,
254dd102
BV
1079 .dev_acquisition_start = dev_acquisition_start,
1080 .dev_acquisition_stop = dev_acquisition_stop,
41812aca 1081 .context = NULL,
f4816ac6 1082};
dd5c48a6 1083SR_REGISTER_DEV_DRIVER(rigol_ds_driver_info);