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