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