]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
rigol-ds: Support 4 analog channels.
[libsigrok.git] / 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
e0b7d23c
ML
22#include <fcntl.h>
23#include <unistd.h>
24#include <stdlib.h>
25#include <string.h>
f4816ac6
ML
26#include <glib.h>
27#include "libsigrok.h"
28#include "libsigrok-internal.h"
29#include "protocol.h"
30
ca55277c
ML
31static const int32_t hwopts[] = {
32 SR_CONF_CONN,
0dc7b43e 33 SR_CONF_SERIALCOMM
ca55277c
ML
34};
35
f6a0ac9f 36static const int32_t hwcaps[] = {
1953564a 37 SR_CONF_OSCILLOSCOPE,
1953564a
BV
38 SR_CONF_TIMEBASE,
39 SR_CONF_TRIGGER_SOURCE,
40 SR_CONF_TRIGGER_SLOPE,
41 SR_CONF_HORIZ_TRIGGERPOS,
d62d7ad1 42 SR_CONF_NUM_TIMEBASE,
f48e0249
ML
43};
44
45static const int32_t analog_hwcaps[] = {
d62d7ad1 46 SR_CONF_NUM_VDIV,
f48e0249 47 SR_CONF_VDIV,
78bcc55a 48 SR_CONF_COUPLING,
babab622 49 SR_CONF_DATA_SOURCE,
e0b7d23c
ML
50};
51
f6a0ac9f 52static const uint64_t timebases[][2] = {
e0b7d23c
ML
53 /* nanoseconds */
54 { 2, 1000000000 },
55 { 5, 1000000000 },
56 { 10, 1000000000 },
57 { 20, 1000000000 },
58 { 50, 1000000000 },
59 { 100, 1000000000 },
60 { 500, 1000000000 },
61 /* microseconds */
62 { 1, 1000000 },
63 { 2, 1000000 },
64 { 5, 1000000 },
65 { 10, 1000000 },
66 { 20, 1000000 },
67 { 50, 1000000 },
68 { 100, 1000000 },
69 { 200, 1000000 },
70 { 500, 1000000 },
71 /* milliseconds */
72 { 1, 1000 },
73 { 2, 1000 },
74 { 5, 1000 },
75 { 10, 1000 },
76 { 20, 1000 },
77 { 50, 1000 },
78 { 100, 1000 },
79 { 200, 1000 },
80 { 500, 1000 },
81 /* seconds */
82 { 1, 1 },
83 { 2, 1 },
84 { 5, 1 },
85 { 10, 1 },
86 { 20, 1 },
87 { 50, 1 },
bafd4890
ML
88 { 100, 1 },
89 { 200, 1 },
90 { 500, 1 },
91 /* { 1000, 1 }, Confuses other code? */
e0b7d23c
ML
92};
93
f6a0ac9f 94static const uint64_t vdivs[][2] = {
bafd4890
ML
95 /* microvolts */
96 { 500, 1000000 },
e0b7d23c 97 /* millivolts */
bafd4890 98 { 1, 1000 },
e0b7d23c
ML
99 { 2, 1000 },
100 { 5, 1000 },
101 { 10, 1000 },
102 { 20, 1000 },
103 { 50, 1000 },
104 { 100, 1000 },
105 { 200, 1000 },
106 { 500, 1000 },
107 /* volts */
108 { 1, 1 },
109 { 2, 1 },
110 { 5, 1 },
111 { 10, 1 },
e0b7d23c
ML
112};
113
bafd4890
ML
114#define NUM_TIMEBASE ARRAY_SIZE(timebases)
115#define NUM_VDIV ARRAY_SIZE(vdivs)
116
e0b7d23c
ML
117static const char *trigger_sources[] = {
118 "CH1",
119 "CH2",
821fbcad
ML
120 "CH3",
121 "CH4",
e0b7d23c
ML
122 "EXT",
123 "AC Line",
6bb192bc
ML
124 "D0",
125 "D1",
126 "D2",
127 "D3",
128 "D4",
129 "D5",
130 "D6",
131 "D7",
132 "D8",
133 "D9",
134 "D10",
135 "D11",
136 "D12",
137 "D13",
138 "D14",
139 "D15",
e0b7d23c
ML
140};
141
142static const char *coupling[] = {
143 "AC",
144 "DC",
145 "GND",
e0b7d23c
ML
146};
147
babab622
ML
148/* Do not change the order of entries */
149static const char *data_sources[] = {
150 "Live",
151 "Memory",
152 "Segmented",
153};
154
155/*
156 * name, series, protocol flavor, min timebase, max timebase, min vdiv,
157 * digital channels, number of horizontal divs
158 */
10afee13
ML
159
160#define RIGOL "Rigol Technologies"
161#define AGILENT "Agilent Technologies"
162
bafd4890 163static const struct rigol_ds_model supported_models[] = {
821fbcad
ML
164 {RIGOL, "DS1052E", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
165 {RIGOL, "DS1102E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
166 {RIGOL, "DS1152E", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
167 {RIGOL, "DS1052D", RIGOL_DS1000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
168 {RIGOL, "DS1102D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
169 {RIGOL, "DS1152D", RIGOL_DS1000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 12},
170 {RIGOL, "DS2072", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
171 {RIGOL, "DS2102", RIGOL_DS2000, PROTOCOL_IEEE488_2, {5, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
172 {RIGOL, "DS2202", RIGOL_DS2000, PROTOCOL_IEEE488_2, {2, 1000000000}, {500, 1}, {500, 1000000}, 2, false, 14},
173 {RIGOL, "VS5022", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
174 {RIGOL, "VS5022D", RIGOL_VS5000, PROTOCOL_LEGACY, {20, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
175 {RIGOL, "VS5042", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
176 {RIGOL, "VS5042D", RIGOL_VS5000, PROTOCOL_LEGACY, {10, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
177 {RIGOL, "VS5062", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
178 {RIGOL, "VS5062D", RIGOL_VS5000, PROTOCOL_LEGACY, {5, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
179 {RIGOL, "VS5102", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
180 {RIGOL, "VS5102D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
181 {RIGOL, "VS5202", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 14},
182 {RIGOL, "VS5202D", RIGOL_VS5000, PROTOCOL_LEGACY, {2, 1000000000}, {50, 1}, {2, 1000}, 2, true, 14},
183 {AGILENT, "DSO1014A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
512bb890
BV
184};
185
3086efdd
ML
186SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
187static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 188
fa85f376 189static void clear_helper(void *priv)
f4816ac6 190{
f4816ac6 191 struct dev_context *devc;
f4816ac6 192
ba358ffd 193 devc = priv;
babab622
ML
194 g_free(devc->data);
195 g_free(devc->buffer);
fa85f376
UH
196 g_free(devc->coupling[0]);
197 g_free(devc->coupling[1]);
198 g_free(devc->trigger_source);
199 g_free(devc->trigger_slope);
ba358ffd
BV
200 g_slist_free(devc->analog_groups[0].probes);
201 g_slist_free(devc->analog_groups[1].probes);
202 g_slist_free(devc->digital_group.probes);
fa85f376 203}
f4816ac6 204
3b412e3a 205static int dev_clear(void)
fa85f376
UH
206{
207 return std_dev_clear(di, clear_helper);
f4816ac6
ML
208}
209
254dd102
BV
210static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
211{
254dd102 212 va_list args;
4d7a9a14 213 int ret;
254dd102 214
254dd102 215 va_start(args, format);
4d7a9a14 216 ret = sr_scpi_send_variadic(sdi->conn, format, args);
254dd102 217 va_end(args);
4d7a9a14
ML
218
219 if (ret != SR_OK)
254dd102
BV
220 return SR_ERR;
221
222 /* When setting a bunch of parameters in a row, the DS1052E scrambles
223 * some of them unless there is at least 100ms delay in between. */
8f35be72 224 sr_spew("delay %dms", 100);
e31d410d 225 g_usleep(100000);
254dd102
BV
226
227 return SR_OK;
228}
229
6078d2c9 230static int init(struct sr_context *sr_ctx)
f4816ac6 231{
f6beaac5 232 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
233}
234
3520422f 235static int probe_port(const char *resource, const char *serialcomm, GSList **devices)
f4816ac6 236{
cc9fd2d2
BV
237 struct dev_context *devc;
238 struct sr_dev_inst *sdi;
0dc7b43e 239 const char *usbtmc_prefix = "/dev/usbtmc";
3520422f
ML
240 const char *tcp_prefix = "tcp/";
241 gchar **tokens, *address, *port;
ae1bc1cc
ML
242 struct sr_scpi_dev_inst *scpi;
243 struct sr_scpi_hw_info *hw_info;
cc9fd2d2 244 struct sr_probe *probe;
f6a0ac9f 245 unsigned int i;
bafd4890 246 const struct rigol_ds_model *model = NULL;
ae1bc1cc 247 gchar *channel_name;
fb6e5ba8 248
46a743c1 249 *devices = NULL;
0dc7b43e 250
3520422f 251 if (strncmp(resource, usbtmc_prefix, strlen(usbtmc_prefix)) == 0) {
7cf1a98d 252 sr_dbg("Opening USBTMC device %s.", resource);
3520422f
ML
253 if (!(scpi = scpi_usbtmc_dev_inst_new(resource)))
254 return SR_ERR_MALLOC;
255 } else if (strncmp(resource, tcp_prefix, strlen(tcp_prefix)) == 0) {
7cf1a98d 256 sr_dbg("Opening TCP connection %s.", resource);
3520422f
ML
257 tokens = g_strsplit(resource + strlen(tcp_prefix), "/", 0);
258 address = tokens[0];
259 port = tokens[1];
260 if (!address || !port || tokens[2]) {
7cf1a98d 261 sr_err("Invalid parameters.");
3520422f
ML
262 g_strfreev(tokens);
263 return SR_ERR_ARG;
264 }
265 scpi = scpi_tcp_dev_inst_new(address, port);
266 g_strfreev(tokens);
267 if (!scpi)
0dc7b43e
ML
268 return SR_ERR_MALLOC;
269 } else {
7cf1a98d 270 sr_dbg("Opening serial device %s.", resource);
3520422f 271 if (!(scpi = scpi_serial_dev_inst_new(resource, serialcomm)))
0dc7b43e
ML
272 return SR_ERR_MALLOC;
273 }
9bd4c956 274
ae1bc1cc 275 if (sr_scpi_open(scpi) != SR_OK) {
10afee13 276 sr_info("Couldn't open SCPI device.");
ae1bc1cc 277 sr_scpi_free(scpi);
9bd4c956 278 return SR_ERR;
ae1bc1cc 279 };
9bd4c956 280
ae1bc1cc
ML
281 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
282 sr_info("Couldn't get IDN response.");
283 sr_scpi_close(scpi);
284 sr_scpi_free(scpi);
285 return SR_ERR;
ca55277c 286 }
e0b7d23c 287
ca55277c 288 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
10afee13
ML
289 if (!strcasecmp(hw_info->manufacturer, supported_models[i].vendor) &&
290 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 291 model = &supported_models[i];
ca55277c 292 break;
fb6e5ba8 293 }
ca55277c 294 }
fb6e5ba8 295
bafd4890 296 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
ae1bc1cc
ML
297 hw_info->manufacturer, hw_info->model,
298 hw_info->firmware_version))) {
299 sr_scpi_hw_info_free(hw_info);
b4936bae 300 sr_scpi_close(scpi);
ae1bc1cc 301 sr_scpi_free(scpi);
ca55277c
ML
302 return SR_ERR_NA;
303 }
fb6e5ba8 304
ae1bc1cc 305 sr_scpi_hw_info_free(hw_info);
b4936bae 306 sr_scpi_close(scpi);
ae1bc1cc
ML
307
308 sdi->conn = scpi;
fb6e5ba8 309
cc9fd2d2 310 sdi->driver = di;
ae1bc1cc 311 sdi->inst_type = SR_INST_SCPI;
512bb890 312
cc9fd2d2 313 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 314 return SR_ERR_MALLOC;
ae1bc1cc 315
cc9fd2d2 316 devc->limit_frames = 0;
bafd4890 317 devc->model = model;
512bb890 318
821fbcad
ML
319 for (i = 0; i < model->analog_channels; i++) {
320 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
ca55277c 321 return SR_ERR_MALLOC;
821fbcad 322 probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name);
ca55277c 323 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
324 devc->analog_groups[i].name = channel_name;
325 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
326 sdi->probe_groups = g_slist_append(sdi->probe_groups,
327 &devc->analog_groups[i]);
ca55277c 328 }
512bb890 329
bafd4890 330 if (devc->model->has_digital) {
ca55277c
ML
331 for (i = 0; i < 16; i++) {
332 if (!(channel_name = g_strdup_printf("D%d", i)))
333 return SR_ERR_MALLOC;
334 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
335 g_free(channel_name);
336 if (!probe)
337 return SR_ERR_MALLOC;
338 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
339 devc->digital_group.probes = g_slist_append(
340 devc->digital_group.probes, probe);
512bb890 341 }
b3916147
ML
342 devc->digital_group.name = "LA";
343 sdi->probe_groups = g_slist_append(sdi->probe_groups,
344 &devc->digital_group);
ca55277c 345 }
bafd4890
ML
346
347 for (i = 0; i < NUM_TIMEBASE; i++) {
348 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
349 devc->timebases = &timebases[i];
350 if (!memcmp(&devc->model->max_timebase, &timebases[i], sizeof(uint64_t[2])))
351 devc->num_timebases = &timebases[i] - devc->timebases + 1;
352 }
353
354 for (i = 0; i < NUM_VDIV; i++) {
355 if (!memcmp(&devc->model->min_vdiv, &vdivs[i], sizeof(uint64_t[2]))) {
6ff1394e
ML
356 devc->vdivs = &vdivs[i];
357 devc->num_vdivs = NUM_VDIV - (&vdivs[i] - &vdivs[0]);
bafd4890
ML
358 }
359 }
360
babab622
ML
361 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
362 return SR_ERR_MALLOC;
363 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
364 return SR_ERR_MALLOC;
365
366 devc->data_source = DATA_SOURCE_LIVE;
367
cc9fd2d2
BV
368 sdi->priv = devc;
369
370 *devices = g_slist_append(NULL, sdi);
512bb890 371
ca55277c
ML
372 return SR_OK;
373}
512bb890 374
6078d2c9 375static GSList *scan(GSList *options)
ca55277c
ML
376{
377 struct drv_context *drvc;
ca55277c 378 struct sr_config *src;
cc9fd2d2 379 GSList *l, *devices;
ca55277c 380 GDir *dir;
ca55277c 381 int ret;
cc9fd2d2
BV
382 const gchar *dev_name;
383 gchar *port = NULL;
0dc7b43e 384 gchar *serialcomm = NULL;
fb6e5ba8 385
ca55277c 386 drvc = di->priv;
d2e0b1fa 387
ca55277c
ML
388 for (l = options; l; l = l->next) {
389 src = l->data;
0dc7b43e
ML
390 switch (src->key) {
391 case SR_CONF_CONN:
cc9fd2d2 392 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 393 break;
0dc7b43e
ML
394 case SR_CONF_SERIALCOMM:
395 serialcomm = (char *)g_variant_get_string(src->data, NULL);
396 break;
fb6e5ba8 397 }
ca55277c 398 }
fb6e5ba8 399
46a743c1 400 devices = NULL;
cc9fd2d2 401 if (port) {
0dc7b43e
ML
402 if (probe_port(port, serialcomm, &devices) == SR_ERR_MALLOC) {
403 g_free(port);
404 if (serialcomm)
405 g_free(serialcomm);
ca55277c 406 return NULL;
0dc7b43e 407 }
ca55277c 408 } else {
da970d24
BV
409 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
410 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
411 return NULL;
ca55277c 412 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 413 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 414 continue;
cc9fd2d2 415 port = g_strconcat("/dev/", dev_name, NULL);
0dc7b43e 416 ret = probe_port(port, serialcomm, &devices);
cc9fd2d2 417 g_free(port);
0dc7b43e
ML
418 if (serialcomm)
419 g_free(serialcomm);
ca55277c
ML
420 if (ret == SR_ERR_MALLOC) {
421 g_dir_close(dir);
ca55277c 422 return NULL;
6bb192bc
ML
423 }
424 }
ca55277c
ML
425 g_dir_close(dir);
426 }
f4816ac6 427
46a743c1
BV
428 /* Tack a copy of the newly found devices onto the driver list. */
429 l = g_slist_copy(devices);
430 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 431
f4816ac6
ML
432 return devices;
433}
434
6078d2c9 435static GSList *dev_list(void)
f4816ac6 436{
0e94d524 437 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
438}
439
6078d2c9 440static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 441{
ae1bc1cc 442 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 443
ae1bc1cc 444 if (sr_scpi_open(scpi) < 0)
e0b7d23c 445 return SR_ERR;
e0b7d23c 446
3086efdd 447 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 448 return SR_ERR;
f4816ac6 449
46a743c1 450 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 451
f4816ac6
ML
452 return SR_OK;
453}
454
6078d2c9 455static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 456{
ae1bc1cc
ML
457 struct sr_scpi_dev_inst *scpi;
458
459 scpi = sdi->conn;
e0b7d23c 460
ae1bc1cc
ML
461 if (scpi) {
462 if (sr_scpi_close(scpi) < 0)
463 return SR_ERR;
cc9fd2d2
BV
464 sdi->status = SR_ST_INACTIVE;
465 }
f4816ac6
ML
466
467 return SR_OK;
468}
469
6078d2c9 470static int cleanup(void)
f4816ac6 471{
3b412e3a 472 return dev_clear();
f4816ac6
ML
473}
474
8f996b89
ML
475static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
476 const struct sr_probe_group *probe_group)
d62d7ad1 477{
e43fdd8d 478 struct dev_context *devc;
f48e0249 479 unsigned int i;
d62d7ad1 480
e43fdd8d
BV
481 if (!sdi || !(devc = sdi->priv))
482 return SR_ERR_ARG;
483
be60a9e4
BV
484 /* If a probe group is specified, it must be a valid one. */
485 if (probe_group) {
486 if (probe_group != &devc->analog_groups[0]
487 && probe_group != &devc->analog_groups[1]) {
488 sr_err("Invalid probe group specified.");
489 return SR_ERR;
490 }
491 }
492
d62d7ad1
BV
493 switch (id) {
494 case SR_CONF_NUM_TIMEBASE:
bafd4890 495 *data = g_variant_new_int32(devc->num_timebases);
d62d7ad1
BV
496 break;
497 case SR_CONF_NUM_VDIV:
be60a9e4
BV
498 if (!probe_group) {
499 sr_err("No probe group specified.");
500 return SR_ERR_PROBE_GROUP;
501 }
f48e0249 502 for (i = 0; i < 2; i++) {
e43fdd8d 503 if (probe_group == &devc->analog_groups[i]) {
bafd4890 504 *data = g_variant_new_int32(devc->num_vdivs);
f48e0249
ML
505 return SR_OK;
506 }
507 }
508 return SR_ERR_NA;
babab622
ML
509 case SR_CONF_DATA_SOURCE:
510 if (devc->data_source == DATA_SOURCE_LIVE)
511 *data = g_variant_new_string("Live");
512 else if (devc->data_source == DATA_SOURCE_MEMORY)
513 *data = g_variant_new_string("Memory");
514 else
515 *data = g_variant_new_string("Segmented");
516 break;
d62d7ad1 517 default:
bd6fbf62 518 return SR_ERR_NA;
d62d7ad1
BV
519 }
520
521 return SR_OK;
522}
523
8f996b89
ML
524static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
525 const struct sr_probe_group *probe_group)
f4816ac6 526{
29d957ce 527 struct dev_context *devc;
f6a0ac9f 528 uint64_t tmp_u64, p, q;
254dd102 529 double t_dbl;
f48e0249 530 unsigned int i, j;
254dd102
BV
531 int ret;
532 const char *tmp_str;
f4816ac6 533
e43fdd8d
BV
534 if (!(devc = sdi->priv))
535 return SR_ERR_ARG;
29d957ce 536
e73ffd42
BV
537 if (sdi->status != SR_ST_ACTIVE)
538 return SR_ERR_DEV_CLOSED;
f4816ac6 539
be60a9e4
BV
540 /* If a probe group is specified, it must be a valid one. */
541 if (probe_group) {
542 if (probe_group != &devc->analog_groups[0]
543 && probe_group != &devc->analog_groups[1]) {
544 sr_err("Invalid probe group specified.");
545 return SR_ERR;
546 }
547 }
548
f4816ac6 549 ret = SR_OK;
035a1078 550 switch (id) {
1953564a 551 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 552 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 553 break;
1953564a 554 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 555 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
556 if (tmp_u64 != 0 && tmp_u64 != 1)
557 return SR_ERR;
558 g_free(devc->trigger_slope);
559 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
560 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 561 break;
1953564a 562 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
563 t_dbl = g_variant_get_double(data);
564 if (t_dbl < 0.0 || t_dbl > 1.0)
565 return SR_ERR;
566 devc->horiz_triggerpos = t_dbl;
567 /* We have the trigger offset as a percentage of the frame, but
568 * need to express this in seconds. */
bafd4890 569 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 570 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 571 break;
1953564a 572 case SR_CONF_TIMEBASE:
f6a0ac9f 573 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
574 for (i = 0; i < devc->num_timebases; i++) {
575 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
576 devc->timebase = (float)p / q;
577 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
578 break;
579 }
580 }
bafd4890 581 if (i == devc->num_timebases)
254dd102 582 ret = SR_ERR_ARG;
e0b7d23c 583 break;
1953564a 584 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 585 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
586 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
587 if (!strcmp(trigger_sources[i], tmp_str)) {
588 g_free(devc->trigger_source);
589 devc->trigger_source = g_strdup(trigger_sources[i]);
590 if (!strcmp(devc->trigger_source, "AC Line"))
591 tmp_str = "ACL";
592 else if (!strcmp(devc->trigger_source, "CH1"))
593 tmp_str = "CHAN1";
594 else if (!strcmp(devc->trigger_source, "CH2"))
595 tmp_str = "CHAN2";
821fbcad
ML
596 else if (!strcmp(devc->trigger_source, "CH3"))
597 tmp_str = "CHAN3";
598 else if (!strcmp(devc->trigger_source, "CH4"))
599 tmp_str = "CHAN4";
254dd102
BV
600 else
601 tmp_str = (char *)devc->trigger_source;
602 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
603 break;
604 }
4e108ace 605 }
254dd102
BV
606 if (i == ARRAY_SIZE(trigger_sources))
607 ret = SR_ERR_ARG;
e0b7d23c 608 break;
1953564a 609 case SR_CONF_VDIV:
be60a9e4
BV
610 if (!probe_group) {
611 sr_err("No probe group specified.");
612 return SR_ERR_PROBE_GROUP;
613 }
f6a0ac9f 614 g_variant_get(data, "(tt)", &p, &q);
f48e0249 615 for (i = 0; i < 2; i++) {
78bcc55a
BV
616 if (probe_group == &devc->analog_groups[i]) {
617 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
618 if (vdivs[j][0] != p || vdivs[j][1] != q)
619 continue;
620 devc->vdiv[i] = (float)p / q;
621 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
622 devc->vdiv[i]);
623 }
624 return SR_ERR_ARG;
625 }
e0b7d23c 626 }
f48e0249 627 return SR_ERR_NA;
1953564a 628 case SR_CONF_COUPLING:
78bcc55a
BV
629 if (!probe_group) {
630 sr_err("No probe group specified.");
631 return SR_ERR_PROBE_GROUP;
632 }
f6a0ac9f 633 tmp_str = g_variant_get_string(data, NULL);
f48e0249 634 for (i = 0; i < 2; i++) {
78bcc55a
BV
635 if (probe_group == &devc->analog_groups[i]) {
636 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
637 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
638 g_free(devc->coupling[i]);
639 devc->coupling[i] = g_strdup(coupling[j]);
640 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
641 devc->coupling[i]);
642 }
643 }
644 return SR_ERR_ARG;
e0b7d23c
ML
645 }
646 }
f48e0249 647 return SR_ERR_NA;
babab622
ML
648 case SR_CONF_DATA_SOURCE:
649 tmp_str = g_variant_get_string(data, NULL);
650 if (!strcmp(tmp_str, "Live"))
651 devc->data_source = DATA_SOURCE_LIVE;
652 else if (!strcmp(tmp_str, "Memory"))
653 devc->data_source = DATA_SOURCE_MEMORY;
654 else if (devc->model->protocol == PROTOCOL_IEEE488_2
655 && !strcmp(tmp_str, "Segmented"))
656 devc->data_source = DATA_SOURCE_SEGMENTED;
657 else
658 return SR_ERR;
659 break;
f4816ac6 660 default:
bd6fbf62 661 ret = SR_ERR_NA;
29d957ce 662 break;
f4816ac6
ML
663 }
664
665 return ret;
666}
667
8f996b89
ML
668static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
669 const struct sr_probe_group *probe_group)
a1c743fc 670{
861c447b
BV
671 GVariant *tuple, *rational[2];
672 GVariantBuilder gvb;
673 unsigned int i;
7cc1a550
ML
674 struct dev_context *devc = NULL;
675
676 if (sdi)
677 devc = sdi->priv;
8f996b89 678
e43fdd8d 679 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
680 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
681 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
682 return SR_OK;
683 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
684 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
685 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
686 return SR_OK;
687 }
688
689 /* Every other option requires a valid device instance. */
690 if (!sdi || !(devc = sdi->priv))
691 return SR_ERR_ARG;
692
be60a9e4
BV
693 /* If a probe group is specified, it must be a valid one. */
694 if (probe_group) {
695 if (probe_group != &devc->analog_groups[0]
696 && probe_group != &devc->analog_groups[1]) {
697 sr_err("Invalid probe group specified.");
698 return SR_ERR;
699 }
700 }
701
e43fdd8d 702 switch (key) {
ca55277c 703 break;
9a6517d1 704 case SR_CONF_DEVICE_OPTIONS:
be60a9e4
BV
705 if (!probe_group) {
706 sr_err("No probe group specified.");
707 return SR_ERR_PROBE_GROUP;
708 }
e43fdd8d 709 if (probe_group == &devc->digital_group) {
f48e0249
ML
710 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
711 NULL, 0, sizeof(int32_t));
712 return SR_OK;
713 } else {
714 for (i = 0; i < 2; i++) {
715 if (probe_group == &devc->analog_groups[i]) {
716 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
717 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
718 return SR_OK;
719 }
720 }
721 return SR_ERR_NA;
722 }
5f77dffc 723 break;
2a7b113d 724 case SR_CONF_COUPLING:
be60a9e4
BV
725 if (!probe_group) {
726 sr_err("No probe group specified.");
727 return SR_ERR_PROBE_GROUP;
f48e0249 728 }
58f43369
BV
729 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
730 break;
e4f2b2ad 731 case SR_CONF_VDIV:
7cc1a550
ML
732 if (!devc)
733 /* Can't know this until we have the exact model. */
734 return SR_ERR_ARG;
be60a9e4
BV
735 if (!probe_group) {
736 sr_err("No probe group specified.");
737 return SR_ERR_PROBE_GROUP;
861c447b 738 }
58f43369 739 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
740 for (i = 0; i < devc->num_vdivs; i++) {
741 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
742 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
743 tuple = g_variant_new_tuple(rational, 2);
744 g_variant_builder_add_value(&gvb, tuple);
745 }
746 *data = g_variant_builder_end(&gvb);
747 break;
41f5bd09 748 case SR_CONF_TIMEBASE:
7cc1a550
ML
749 if (!devc)
750 /* Can't know this until we have the exact model. */
751 return SR_ERR_ARG;
861c447b 752 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
753 for (i = 0; i < devc->num_timebases; i++) {
754 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
755 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
756 tuple = g_variant_new_tuple(rational, 2);
757 g_variant_builder_add_value(&gvb, tuple);
758 }
759 *data = g_variant_builder_end(&gvb);
41f5bd09 760 break;
328bafab 761 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
762 if (!devc)
763 /* Can't know this until we have the exact model. */
764 return SR_ERR_ARG;
f6a0ac9f 765 *data = g_variant_new_strv(trigger_sources,
bafd4890 766 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 767 break;
babab622
ML
768 case SR_CONF_DATA_SOURCE:
769 if (!devc)
770 /* Can't know this until we have the exact model. */
771 return SR_ERR_ARG;
772 /* This needs tweaking by series/model! */
773 if (devc->model->series == RIGOL_DS2000)
774 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
775 else
776 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
777 break;
a1c743fc 778 default:
bd6fbf62 779 return SR_ERR_NA;
a1c743fc
BV
780 }
781
782 return SR_OK;
783}
784
254dd102 785static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 786{
ae1bc1cc 787 struct sr_scpi_dev_inst *scpi;
29d957ce 788 struct dev_context *devc;
254dd102
BV
789 struct sr_probe *probe;
790 GSList *l;
29d957ce 791
e73ffd42
BV
792 if (sdi->status != SR_ST_ACTIVE)
793 return SR_ERR_DEV_CLOSED;
e0b7d23c 794
ae1bc1cc 795 scpi = sdi->conn;
29d957ce
UH
796 devc = sdi->priv;
797
254dd102
BV
798 for (l = sdi->probes; l; l = l->next) {
799 probe = l->data;
6bb192bc
ML
800 sr_dbg("handling probe %s", probe->name);
801 if (probe->type == SR_PROBE_ANALOG) {
802 if (probe->enabled)
803 devc->enabled_analog_probes = g_slist_append(
804 devc->enabled_analog_probes, probe);
805 if (probe->enabled != devc->analog_channels[probe->index]) {
806 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
807 if (set_cfg(sdi, ":CHAN%d:DISP %s", probe->index + 1,
808 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
809 return SR_ERR;
810 }
811 } else if (probe->type == SR_PROBE_LOGIC) {
812 if (probe->enabled)
813 devc->enabled_digital_probes = g_slist_append(
814 devc->enabled_digital_probes, probe);
815 if (probe->enabled != devc->digital_channels[probe->index]) {
816 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
817 if (set_cfg(sdi, ":DIG%d:TURN %s", probe->index,
818 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
819 return SR_ERR;
820 }
254dd102
BV
821 }
822 }
1fed20cb 823
6bb192bc 824 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 825 return SR_ERR;
e0b7d23c 826
1fed20cb 827 if (devc->data_source == DATA_SOURCE_LIVE) {
6396b0a7 828 if (set_cfg(sdi, ":RUN") != SR_OK)
1fed20cb
ML
829 return SR_ERR;
830 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
831 if (devc->model->series != RIGOL_DS2000) {
832 sr_err("Data source 'Memory' not supported for this device");
833 return SR_ERR;
834 }
835 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
836 sr_err("Data source 'Segmented' not yet supported");
837 return SR_ERR;
838 }
839
ae1bc1cc 840 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
841
842 /* Send header packet to the session bus. */
29a27196 843 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 844
821fbcad
ML
845 if (devc->enabled_analog_probes)
846 devc->channel_entry = devc->enabled_analog_probes;
847 else
848 devc->channel_entry = devc->enabled_digital_probes;
849
babab622 850 if (devc->model->protocol == PROTOCOL_LEGACY) {
9e4b7d98
ML
851 devc->analog_frame_size = (devc->model->series == RIGOL_VS5000 ?
852 VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
853 DS1000_ANALOG_LIVE_WAVEFORM_SIZE);
bafd4890 854 /* Fetch the first frame. */
677f85d0
ML
855 if (rigol_ds_channel_start(sdi) != SR_OK)
856 return SR_ERR;
6bb192bc 857 } else {
bafd4890 858 if (devc->enabled_analog_probes) {
babab622
ML
859 if (devc->data_source == DATA_SOURCE_MEMORY)
860 {
861 if (g_slist_length(devc->enabled_analog_probes) == 1)
862 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
863 else
864 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
865 /* Apparently for the DS2000 the memory
866 * depth can only be set in Running state -
867 * this matches the behaviour of the UI. */
6396b0a7 868 if (set_cfg(sdi, ":RUN") != SR_OK)
babab622 869 return SR_ERR;
6396b0a7 870 if (set_cfg(sdi, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 871 return SR_ERR;
6396b0a7 872 if (set_cfg(sdi, ":STOP") != SR_OK)
babab622 873 return SR_ERR;
0d9f5a12
ML
874 } else {
875 if (devc->model->series == AGILENT_DSO1000)
876 devc->analog_frame_size = DSO1000_ANALOG_LIVE_WAVEFORM_SIZE;
877 else
878 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
879 }
babab622 880 if (rigol_ds_capture_start(sdi) != SR_OK)
bafd4890
ML
881 return SR_ERR;
882 }
6bb192bc 883 }
f4816ac6
ML
884
885 return SR_OK;
886}
887
254dd102 888static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 889{
29d957ce 890 struct dev_context *devc;
ae1bc1cc 891 struct sr_scpi_dev_inst *scpi;
29d957ce 892
f4816ac6
ML
893 (void)cb_data;
894
29d957ce
UH
895 devc = sdi->priv;
896
f4816ac6
ML
897 if (sdi->status != SR_ST_ACTIVE) {
898 sr_err("Device inactive, can't stop acquisition.");
899 return SR_ERR;
900 }
901
6bb192bc
ML
902 g_slist_free(devc->enabled_analog_probes);
903 g_slist_free(devc->enabled_digital_probes);
904 devc->enabled_analog_probes = NULL;
905 devc->enabled_digital_probes = NULL;
ae1bc1cc
ML
906 scpi = sdi->conn;
907 sr_scpi_source_remove(scpi);
f4816ac6
ML
908
909 return SR_OK;
910}
911
3086efdd
ML
912SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
913 .name = "rigol-ds",
914 .longname = "Rigol DS",
f4816ac6 915 .api_version = 1,
6078d2c9
UH
916 .init = init,
917 .cleanup = cleanup,
918 .scan = scan,
919 .dev_list = dev_list,
3b412e3a 920 .dev_clear = dev_clear,
d62d7ad1 921 .config_get = config_get,
035a1078 922 .config_set = config_set,
a1c743fc 923 .config_list = config_list,
6078d2c9
UH
924 .dev_open = dev_open,
925 .dev_close = dev_close,
254dd102
BV
926 .dev_acquisition_start = dev_acquisition_start,
927 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
928 .priv = NULL,
929};