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