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