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