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