]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
rigol-ds: Select channels before issuing RUN command.
[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 244 if (strncmp(resource, usbtmc_prefix, strlen(usbtmc_prefix)) == 0) {
7cf1a98d 245 sr_dbg("Opening USBTMC device %s.", resource);
3520422f
ML
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) {
7cf1a98d 249 sr_dbg("Opening TCP connection %s.", resource);
3520422f
ML
250 tokens = g_strsplit(resource + strlen(tcp_prefix), "/", 0);
251 address = tokens[0];
252 port = tokens[1];
253 if (!address || !port || tokens[2]) {
7cf1a98d 254 sr_err("Invalid parameters.");
3520422f
ML
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 {
7cf1a98d 263 sr_dbg("Opening serial device %s.", resource);
3520422f 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);
b4936bae 282 sr_scpi_close(scpi);
ae1bc1cc 283 sr_scpi_free(scpi);
ca55277c
ML
284 return SR_ERR_NA;
285 }
fb6e5ba8 286
ca55277c 287 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
ae1bc1cc 288 if (!strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 289 model = &supported_models[i];
ca55277c 290 break;
fb6e5ba8 291 }
ca55277c 292 }
fb6e5ba8 293
bafd4890 294 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
ae1bc1cc
ML
295 hw_info->manufacturer, hw_info->model,
296 hw_info->firmware_version))) {
297 sr_scpi_hw_info_free(hw_info);
b4936bae 298 sr_scpi_close(scpi);
ae1bc1cc 299 sr_scpi_free(scpi);
ca55277c
ML
300 return SR_ERR_NA;
301 }
fb6e5ba8 302
ae1bc1cc 303 sr_scpi_hw_info_free(hw_info);
b4936bae 304 sr_scpi_close(scpi);
ae1bc1cc
ML
305
306 sdi->conn = scpi;
fb6e5ba8 307
cc9fd2d2 308 sdi->driver = di;
ae1bc1cc 309 sdi->inst_type = SR_INST_SCPI;
512bb890 310
cc9fd2d2 311 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 312 return SR_ERR_MALLOC;
ae1bc1cc 313
cc9fd2d2 314 devc->limit_frames = 0;
bafd4890 315 devc->model = model;
512bb890 316
ca55277c 317 for (i = 0; i < 2; i++) {
3d3a601e
ML
318 channel_name = (i == 0 ? "CH1" : "CH2");
319 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name)))
ca55277c
ML
320 return SR_ERR_MALLOC;
321 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
322 devc->analog_groups[i].name = channel_name;
323 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
324 sdi->probe_groups = g_slist_append(sdi->probe_groups,
325 &devc->analog_groups[i]);
ca55277c 326 }
512bb890 327
bafd4890 328 if (devc->model->has_digital) {
ca55277c
ML
329 for (i = 0; i < 16; i++) {
330 if (!(channel_name = g_strdup_printf("D%d", i)))
331 return SR_ERR_MALLOC;
332 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
333 g_free(channel_name);
334 if (!probe)
335 return SR_ERR_MALLOC;
336 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
337 devc->digital_group.probes = g_slist_append(
338 devc->digital_group.probes, probe);
512bb890 339 }
b3916147
ML
340 devc->digital_group.name = "LA";
341 sdi->probe_groups = g_slist_append(sdi->probe_groups,
342 &devc->digital_group);
ca55277c 343 }
bafd4890
ML
344
345 for (i = 0; i < NUM_TIMEBASE; i++) {
346 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
347 devc->timebases = &timebases[i];
348 if (!memcmp(&devc->model->max_timebase, &timebases[i], sizeof(uint64_t[2])))
349 devc->num_timebases = &timebases[i] - devc->timebases + 1;
350 }
351
352 for (i = 0; i < NUM_VDIV; i++) {
353 if (!memcmp(&devc->model->min_vdiv, &vdivs[i], sizeof(uint64_t[2]))) {
6ff1394e
ML
354 devc->vdivs = &vdivs[i];
355 devc->num_vdivs = NUM_VDIV - (&vdivs[i] - &vdivs[0]);
bafd4890
ML
356 }
357 }
358
babab622
ML
359 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
360 return SR_ERR_MALLOC;
361 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
362 return SR_ERR_MALLOC;
363
364 devc->data_source = DATA_SOURCE_LIVE;
365
cc9fd2d2
BV
366 sdi->priv = devc;
367
368 *devices = g_slist_append(NULL, sdi);
512bb890 369
ca55277c
ML
370 return SR_OK;
371}
512bb890 372
6078d2c9 373static GSList *scan(GSList *options)
ca55277c
ML
374{
375 struct drv_context *drvc;
ca55277c 376 struct sr_config *src;
cc9fd2d2 377 GSList *l, *devices;
ca55277c 378 GDir *dir;
ca55277c 379 int ret;
cc9fd2d2
BV
380 const gchar *dev_name;
381 gchar *port = NULL;
0dc7b43e 382 gchar *serialcomm = NULL;
fb6e5ba8 383
ca55277c 384 drvc = di->priv;
d2e0b1fa 385
ca55277c
ML
386 for (l = options; l; l = l->next) {
387 src = l->data;
0dc7b43e
ML
388 switch (src->key) {
389 case SR_CONF_CONN:
cc9fd2d2 390 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 391 break;
0dc7b43e
ML
392 case SR_CONF_SERIALCOMM:
393 serialcomm = (char *)g_variant_get_string(src->data, NULL);
394 break;
fb6e5ba8 395 }
ca55277c 396 }
fb6e5ba8 397
46a743c1 398 devices = NULL;
cc9fd2d2 399 if (port) {
0dc7b43e
ML
400 if (probe_port(port, serialcomm, &devices) == SR_ERR_MALLOC) {
401 g_free(port);
402 if (serialcomm)
403 g_free(serialcomm);
ca55277c 404 return NULL;
0dc7b43e 405 }
ca55277c 406 } else {
da970d24
BV
407 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
408 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
409 return NULL;
ca55277c 410 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 411 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 412 continue;
cc9fd2d2 413 port = g_strconcat("/dev/", dev_name, NULL);
0dc7b43e 414 ret = probe_port(port, serialcomm, &devices);
cc9fd2d2 415 g_free(port);
0dc7b43e
ML
416 if (serialcomm)
417 g_free(serialcomm);
ca55277c
ML
418 if (ret == SR_ERR_MALLOC) {
419 g_dir_close(dir);
ca55277c 420 return NULL;
6bb192bc
ML
421 }
422 }
ca55277c
ML
423 g_dir_close(dir);
424 }
f4816ac6 425
46a743c1
BV
426 /* Tack a copy of the newly found devices onto the driver list. */
427 l = g_slist_copy(devices);
428 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 429
f4816ac6
ML
430 return devices;
431}
432
6078d2c9 433static GSList *dev_list(void)
f4816ac6 434{
0e94d524 435 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
436}
437
6078d2c9 438static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 439{
ae1bc1cc 440 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 441
ae1bc1cc 442 if (sr_scpi_open(scpi) < 0)
e0b7d23c 443 return SR_ERR;
e0b7d23c 444
3086efdd 445 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 446 return SR_ERR;
f4816ac6 447
46a743c1 448 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 449
f4816ac6
ML
450 return SR_OK;
451}
452
6078d2c9 453static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 454{
ae1bc1cc
ML
455 struct sr_scpi_dev_inst *scpi;
456
457 scpi = sdi->conn;
e0b7d23c 458
ae1bc1cc
ML
459 if (scpi) {
460 if (sr_scpi_close(scpi) < 0)
461 return SR_ERR;
cc9fd2d2
BV
462 sdi->status = SR_ST_INACTIVE;
463 }
f4816ac6
ML
464
465 return SR_OK;
466}
467
6078d2c9 468static int cleanup(void)
f4816ac6 469{
3b412e3a 470 return dev_clear();
f4816ac6
ML
471}
472
8f996b89
ML
473static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
474 const struct sr_probe_group *probe_group)
d62d7ad1 475{
e43fdd8d 476 struct dev_context *devc;
f48e0249 477 unsigned int i;
d62d7ad1 478
e43fdd8d
BV
479 if (!sdi || !(devc = sdi->priv))
480 return SR_ERR_ARG;
481
be60a9e4
BV
482 /* If a probe group is specified, it must be a valid one. */
483 if (probe_group) {
484 if (probe_group != &devc->analog_groups[0]
485 && probe_group != &devc->analog_groups[1]) {
486 sr_err("Invalid probe group specified.");
487 return SR_ERR;
488 }
489 }
490
d62d7ad1
BV
491 switch (id) {
492 case SR_CONF_NUM_TIMEBASE:
bafd4890 493 *data = g_variant_new_int32(devc->num_timebases);
d62d7ad1
BV
494 break;
495 case SR_CONF_NUM_VDIV:
be60a9e4
BV
496 if (!probe_group) {
497 sr_err("No probe group specified.");
498 return SR_ERR_PROBE_GROUP;
499 }
f48e0249 500 for (i = 0; i < 2; i++) {
e43fdd8d 501 if (probe_group == &devc->analog_groups[i]) {
bafd4890 502 *data = g_variant_new_int32(devc->num_vdivs);
f48e0249
ML
503 return SR_OK;
504 }
505 }
506 return SR_ERR_NA;
babab622
ML
507 case SR_CONF_DATA_SOURCE:
508 if (devc->data_source == DATA_SOURCE_LIVE)
509 *data = g_variant_new_string("Live");
510 else if (devc->data_source == DATA_SOURCE_MEMORY)
511 *data = g_variant_new_string("Memory");
512 else
513 *data = g_variant_new_string("Segmented");
514 break;
d62d7ad1 515 default:
bd6fbf62 516 return SR_ERR_NA;
d62d7ad1
BV
517 }
518
519 return SR_OK;
520}
521
8f996b89
ML
522static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
523 const struct sr_probe_group *probe_group)
f4816ac6 524{
29d957ce 525 struct dev_context *devc;
f6a0ac9f 526 uint64_t tmp_u64, p, q;
254dd102 527 double t_dbl;
f48e0249 528 unsigned int i, j;
254dd102
BV
529 int ret;
530 const char *tmp_str;
f4816ac6 531
e43fdd8d
BV
532 if (!(devc = sdi->priv))
533 return SR_ERR_ARG;
29d957ce 534
e73ffd42
BV
535 if (sdi->status != SR_ST_ACTIVE)
536 return SR_ERR_DEV_CLOSED;
f4816ac6 537
be60a9e4
BV
538 /* If a probe group is specified, it must be a valid one. */
539 if (probe_group) {
540 if (probe_group != &devc->analog_groups[0]
541 && probe_group != &devc->analog_groups[1]) {
542 sr_err("Invalid probe group specified.");
543 return SR_ERR;
544 }
545 }
546
f4816ac6 547 ret = SR_OK;
035a1078 548 switch (id) {
1953564a 549 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 550 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 551 break;
1953564a 552 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 553 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
554 if (tmp_u64 != 0 && tmp_u64 != 1)
555 return SR_ERR;
556 g_free(devc->trigger_slope);
557 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
558 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 559 break;
1953564a 560 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
561 t_dbl = g_variant_get_double(data);
562 if (t_dbl < 0.0 || t_dbl > 1.0)
563 return SR_ERR;
564 devc->horiz_triggerpos = t_dbl;
565 /* We have the trigger offset as a percentage of the frame, but
566 * need to express this in seconds. */
bafd4890 567 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 568 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 569 break;
1953564a 570 case SR_CONF_TIMEBASE:
f6a0ac9f 571 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
572 for (i = 0; i < devc->num_timebases; i++) {
573 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
574 devc->timebase = (float)p / q;
575 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
576 break;
577 }
578 }
bafd4890 579 if (i == devc->num_timebases)
254dd102 580 ret = SR_ERR_ARG;
e0b7d23c 581 break;
1953564a 582 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 583 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
584 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
585 if (!strcmp(trigger_sources[i], tmp_str)) {
586 g_free(devc->trigger_source);
587 devc->trigger_source = g_strdup(trigger_sources[i]);
588 if (!strcmp(devc->trigger_source, "AC Line"))
589 tmp_str = "ACL";
590 else if (!strcmp(devc->trigger_source, "CH1"))
591 tmp_str = "CHAN1";
592 else if (!strcmp(devc->trigger_source, "CH2"))
593 tmp_str = "CHAN2";
594 else
595 tmp_str = (char *)devc->trigger_source;
596 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
597 break;
598 }
4e108ace 599 }
254dd102
BV
600 if (i == ARRAY_SIZE(trigger_sources))
601 ret = SR_ERR_ARG;
e0b7d23c 602 break;
1953564a 603 case SR_CONF_VDIV:
be60a9e4
BV
604 if (!probe_group) {
605 sr_err("No probe group specified.");
606 return SR_ERR_PROBE_GROUP;
607 }
f6a0ac9f 608 g_variant_get(data, "(tt)", &p, &q);
f48e0249 609 for (i = 0; i < 2; i++) {
78bcc55a
BV
610 if (probe_group == &devc->analog_groups[i]) {
611 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
612 if (vdivs[j][0] != p || vdivs[j][1] != q)
613 continue;
614 devc->vdiv[i] = (float)p / q;
615 return set_cfg(sdi, ":CHAN%d:SCAL %.3f", i + 1,
616 devc->vdiv[i]);
617 }
618 return SR_ERR_ARG;
619 }
e0b7d23c 620 }
f48e0249 621 return SR_ERR_NA;
1953564a 622 case SR_CONF_COUPLING:
78bcc55a
BV
623 if (!probe_group) {
624 sr_err("No probe group specified.");
625 return SR_ERR_PROBE_GROUP;
626 }
f6a0ac9f 627 tmp_str = g_variant_get_string(data, NULL);
f48e0249 628 for (i = 0; i < 2; i++) {
78bcc55a
BV
629 if (probe_group == &devc->analog_groups[i]) {
630 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
631 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
632 g_free(devc->coupling[i]);
633 devc->coupling[i] = g_strdup(coupling[j]);
634 return set_cfg(sdi, ":CHAN%d:COUP %s", i + 1,
635 devc->coupling[i]);
636 }
637 }
638 return SR_ERR_ARG;
e0b7d23c
ML
639 }
640 }
f48e0249 641 return SR_ERR_NA;
babab622
ML
642 case SR_CONF_DATA_SOURCE:
643 tmp_str = g_variant_get_string(data, NULL);
644 if (!strcmp(tmp_str, "Live"))
645 devc->data_source = DATA_SOURCE_LIVE;
646 else if (!strcmp(tmp_str, "Memory"))
647 devc->data_source = DATA_SOURCE_MEMORY;
648 else if (devc->model->protocol == PROTOCOL_IEEE488_2
649 && !strcmp(tmp_str, "Segmented"))
650 devc->data_source = DATA_SOURCE_SEGMENTED;
651 else
652 return SR_ERR;
653 break;
f4816ac6 654 default:
bd6fbf62 655 ret = SR_ERR_NA;
29d957ce 656 break;
f4816ac6
ML
657 }
658
659 return ret;
660}
661
8f996b89
ML
662static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
663 const struct sr_probe_group *probe_group)
a1c743fc 664{
861c447b
BV
665 GVariant *tuple, *rational[2];
666 GVariantBuilder gvb;
667 unsigned int i;
7cc1a550
ML
668 struct dev_context *devc = NULL;
669
670 if (sdi)
671 devc = sdi->priv;
8f996b89 672
e43fdd8d 673 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
674 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
675 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d
BV
676 return SR_OK;
677 } else if (key == SR_CONF_DEVICE_OPTIONS && probe_group == NULL) {
678 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
679 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
680 return SR_OK;
681 }
682
683 /* Every other option requires a valid device instance. */
684 if (!sdi || !(devc = sdi->priv))
685 return SR_ERR_ARG;
686
be60a9e4
BV
687 /* If a probe group is specified, it must be a valid one. */
688 if (probe_group) {
689 if (probe_group != &devc->analog_groups[0]
690 && probe_group != &devc->analog_groups[1]) {
691 sr_err("Invalid probe group specified.");
692 return SR_ERR;
693 }
694 }
695
e43fdd8d 696 switch (key) {
ca55277c 697 break;
9a6517d1 698 case SR_CONF_DEVICE_OPTIONS:
be60a9e4
BV
699 if (!probe_group) {
700 sr_err("No probe group specified.");
701 return SR_ERR_PROBE_GROUP;
702 }
e43fdd8d 703 if (probe_group == &devc->digital_group) {
f48e0249
ML
704 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
705 NULL, 0, sizeof(int32_t));
706 return SR_OK;
707 } else {
708 for (i = 0; i < 2; i++) {
709 if (probe_group == &devc->analog_groups[i]) {
710 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
711 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
712 return SR_OK;
713 }
714 }
715 return SR_ERR_NA;
716 }
5f77dffc 717 break;
2a7b113d 718 case SR_CONF_COUPLING:
be60a9e4
BV
719 if (!probe_group) {
720 sr_err("No probe group specified.");
721 return SR_ERR_PROBE_GROUP;
f48e0249 722 }
58f43369
BV
723 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
724 break;
e4f2b2ad 725 case SR_CONF_VDIV:
7cc1a550
ML
726 if (!devc)
727 /* Can't know this until we have the exact model. */
728 return SR_ERR_ARG;
be60a9e4
BV
729 if (!probe_group) {
730 sr_err("No probe group specified.");
731 return SR_ERR_PROBE_GROUP;
861c447b 732 }
58f43369 733 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
734 for (i = 0; i < devc->num_vdivs; i++) {
735 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
736 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
737 tuple = g_variant_new_tuple(rational, 2);
738 g_variant_builder_add_value(&gvb, tuple);
739 }
740 *data = g_variant_builder_end(&gvb);
741 break;
41f5bd09 742 case SR_CONF_TIMEBASE:
7cc1a550
ML
743 if (!devc)
744 /* Can't know this until we have the exact model. */
745 return SR_ERR_ARG;
861c447b 746 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
747 for (i = 0; i < devc->num_timebases; i++) {
748 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
749 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
750 tuple = g_variant_new_tuple(rational, 2);
751 g_variant_builder_add_value(&gvb, tuple);
752 }
753 *data = g_variant_builder_end(&gvb);
41f5bd09 754 break;
328bafab 755 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
756 if (!devc)
757 /* Can't know this until we have the exact model. */
758 return SR_ERR_ARG;
f6a0ac9f 759 *data = g_variant_new_strv(trigger_sources,
bafd4890 760 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 761 break;
babab622
ML
762 case SR_CONF_DATA_SOURCE:
763 if (!devc)
764 /* Can't know this until we have the exact model. */
765 return SR_ERR_ARG;
766 /* This needs tweaking by series/model! */
767 if (devc->model->series == RIGOL_DS2000)
768 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
769 else
770 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
771 break;
a1c743fc 772 default:
bd6fbf62 773 return SR_ERR_NA;
a1c743fc
BV
774 }
775
776 return SR_OK;
777}
778
254dd102 779static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 780{
ae1bc1cc 781 struct sr_scpi_dev_inst *scpi;
29d957ce 782 struct dev_context *devc;
254dd102
BV
783 struct sr_probe *probe;
784 GSList *l;
254dd102 785 char cmd[256];
29d957ce 786
e73ffd42
BV
787 if (sdi->status != SR_ST_ACTIVE)
788 return SR_ERR_DEV_CLOSED;
e0b7d23c 789
ae1bc1cc 790 scpi = sdi->conn;
29d957ce
UH
791 devc = sdi->priv;
792
254dd102
BV
793 for (l = sdi->probes; l; l = l->next) {
794 probe = l->data;
6bb192bc
ML
795 sr_dbg("handling probe %s", probe->name);
796 if (probe->type == SR_PROBE_ANALOG) {
797 if (probe->enabled)
798 devc->enabled_analog_probes = g_slist_append(
799 devc->enabled_analog_probes, probe);
800 if (probe->enabled != devc->analog_channels[probe->index]) {
801 /* Enabled channel is currently disabled, or vice versa. */
802 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
803 probe->enabled ? "ON" : "OFF");
17b5b202 804 if (sr_scpi_send(sdi->conn, cmd) != SR_OK)
6bb192bc
ML
805 return SR_ERR;
806 }
807 } else if (probe->type == SR_PROBE_LOGIC) {
808 if (probe->enabled)
809 devc->enabled_digital_probes = g_slist_append(
810 devc->enabled_digital_probes, probe);
811 if (probe->enabled != devc->digital_channels[probe->index]) {
812 /* Enabled channel is currently disabled, or vice versa. */
813 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
814 probe->enabled ? "ON" : "OFF");
17b5b202 815 if (sr_scpi_send(sdi->conn, cmd) != SR_OK)
6bb192bc
ML
816 return SR_ERR;
817 }
254dd102
BV
818 }
819 }
1fed20cb 820
6bb192bc 821 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 822 return SR_ERR;
e0b7d23c 823
1fed20cb
ML
824 if (devc->data_source == DATA_SOURCE_LIVE) {
825 if (sr_scpi_send(sdi->conn, ":RUN") != SR_OK)
826 return SR_ERR;
827 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
828 if (devc->model->series != RIGOL_DS2000) {
829 sr_err("Data source 'Memory' not supported for this device");
830 return SR_ERR;
831 }
832 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
833 sr_err("Data source 'Segmented' not yet supported");
834 return SR_ERR;
835 }
836
ae1bc1cc 837 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
838
839 /* Send header packet to the session bus. */
29a27196 840 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 841
babab622 842 if (devc->model->protocol == PROTOCOL_LEGACY) {
677f85d0 843 devc->analog_frame_size = DS1000_ANALOG_LIVE_WAVEFORM_SIZE;
bafd4890 844 /* Fetch the first frame. */
677f85d0 845 if (devc->enabled_analog_probes)
0d87bd93 846 devc->channel = devc->enabled_analog_probes->data;
677f85d0 847 else
0d87bd93 848 devc->channel = devc->enabled_digital_probes->data;
677f85d0
ML
849 if (rigol_ds_channel_start(sdi) != SR_OK)
850 return SR_ERR;
6bb192bc 851 } else {
bafd4890 852 if (devc->enabled_analog_probes) {
babab622
ML
853 if (devc->data_source == DATA_SOURCE_MEMORY)
854 {
855 if (g_slist_length(devc->enabled_analog_probes) == 1)
856 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
857 else
858 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
859 /* Apparently for the DS2000 the memory
860 * depth can only be set in Running state -
861 * this matches the behaviour of the UI. */
17b5b202 862 if (sr_scpi_send(sdi->conn, ":RUN") != SR_OK)
babab622 863 return SR_ERR;
17b5b202 864 if (sr_scpi_send(sdi->conn, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 865 return SR_ERR;
17b5b202 866 if (sr_scpi_send(sdi->conn, ":STOP") != SR_OK)
babab622
ML
867 return SR_ERR;
868 } else
869 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
0d87bd93 870 devc->channel = devc->enabled_analog_probes->data;
babab622 871 if (rigol_ds_capture_start(sdi) != SR_OK)
bafd4890
ML
872 return SR_ERR;
873 }
6bb192bc 874 }
f4816ac6
ML
875
876 return SR_OK;
877}
878
254dd102 879static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 880{
29d957ce 881 struct dev_context *devc;
ae1bc1cc 882 struct sr_scpi_dev_inst *scpi;
29d957ce 883
f4816ac6
ML
884 (void)cb_data;
885
29d957ce
UH
886 devc = sdi->priv;
887
f4816ac6
ML
888 if (sdi->status != SR_ST_ACTIVE) {
889 sr_err("Device inactive, can't stop acquisition.");
890 return SR_ERR;
891 }
892
6bb192bc
ML
893 g_slist_free(devc->enabled_analog_probes);
894 g_slist_free(devc->enabled_digital_probes);
895 devc->enabled_analog_probes = NULL;
896 devc->enabled_digital_probes = NULL;
ae1bc1cc
ML
897 scpi = sdi->conn;
898 sr_scpi_source_remove(scpi);
f4816ac6
ML
899
900 return SR_OK;
901}
902
3086efdd
ML
903SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
904 .name = "rigol-ds",
905 .longname = "Rigol DS",
f4816ac6 906 .api_version = 1,
6078d2c9
UH
907 .init = init,
908 .cleanup = cleanup,
909 .scan = scan,
910 .dev_list = dev_list,
3b412e3a 911 .dev_clear = dev_clear,
d62d7ad1 912 .config_get = config_get,
035a1078 913 .config_set = config_set,
a1c743fc 914 .config_list = config_list,
6078d2c9
UH
915 .dev_open = dev_open,
916 .dev_close = dev_close,
254dd102
BV
917 .dev_acquisition_start = dev_acquisition_start,
918 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
919 .priv = NULL,
920};