]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
rigol-ds: Correct usage of NUM_TIMEBASE and NUM_VDIV config keys.
[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},
227a0981
ML
183 {AGILENT, "DSO1002A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {5, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
184 {AGILENT, "DSO1004A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {5, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
185 {AGILENT, "DSO1012A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
821fbcad 186 {AGILENT, "DSO1014A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
227a0981
ML
187 {AGILENT, "DSO1022A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 2, false, 12},
188 {AGILENT, "DSO1024A", AGILENT_DSO1000, PROTOCOL_IEEE488_2, {2, 1000000000}, {50, 1}, {2, 1000}, 4, false, 12},
512bb890
BV
189};
190
3086efdd
ML
191SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
192static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 193
fa85f376 194static void clear_helper(void *priv)
f4816ac6 195{
f4816ac6 196 struct dev_context *devc;
f4816ac6 197
ba358ffd 198 devc = priv;
babab622
ML
199 g_free(devc->data);
200 g_free(devc->buffer);
fa85f376
UH
201 g_free(devc->coupling[0]);
202 g_free(devc->coupling[1]);
203 g_free(devc->trigger_source);
204 g_free(devc->trigger_slope);
ba358ffd
BV
205 g_slist_free(devc->analog_groups[0].probes);
206 g_slist_free(devc->analog_groups[1].probes);
207 g_slist_free(devc->digital_group.probes);
fa85f376 208}
f4816ac6 209
3b412e3a 210static int dev_clear(void)
fa85f376
UH
211{
212 return std_dev_clear(di, clear_helper);
f4816ac6
ML
213}
214
254dd102
BV
215static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
216{
254dd102 217 va_list args;
4d7a9a14 218 int ret;
254dd102 219
254dd102 220 va_start(args, format);
4d7a9a14 221 ret = sr_scpi_send_variadic(sdi->conn, format, args);
254dd102 222 va_end(args);
4d7a9a14
ML
223
224 if (ret != SR_OK)
254dd102
BV
225 return SR_ERR;
226
227 /* When setting a bunch of parameters in a row, the DS1052E scrambles
228 * some of them unless there is at least 100ms delay in between. */
8f35be72 229 sr_spew("delay %dms", 100);
e31d410d 230 g_usleep(100000);
254dd102
BV
231
232 return SR_OK;
233}
234
6078d2c9 235static int init(struct sr_context *sr_ctx)
f4816ac6 236{
f6beaac5 237 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
238}
239
3520422f 240static int probe_port(const char *resource, const char *serialcomm, GSList **devices)
f4816ac6 241{
cc9fd2d2
BV
242 struct dev_context *devc;
243 struct sr_dev_inst *sdi;
0dc7b43e 244 const char *usbtmc_prefix = "/dev/usbtmc";
3520422f
ML
245 const char *tcp_prefix = "tcp/";
246 gchar **tokens, *address, *port;
ae1bc1cc
ML
247 struct sr_scpi_dev_inst *scpi;
248 struct sr_scpi_hw_info *hw_info;
cc9fd2d2 249 struct sr_probe *probe;
f6a0ac9f 250 unsigned int i;
bafd4890 251 const struct rigol_ds_model *model = NULL;
ae1bc1cc 252 gchar *channel_name;
fb6e5ba8 253
46a743c1 254 *devices = NULL;
0dc7b43e 255
3520422f 256 if (strncmp(resource, usbtmc_prefix, strlen(usbtmc_prefix)) == 0) {
7cf1a98d 257 sr_dbg("Opening USBTMC device %s.", resource);
3520422f
ML
258 if (!(scpi = scpi_usbtmc_dev_inst_new(resource)))
259 return SR_ERR_MALLOC;
260 } else if (strncmp(resource, tcp_prefix, strlen(tcp_prefix)) == 0) {
7cf1a98d 261 sr_dbg("Opening TCP connection %s.", resource);
3520422f
ML
262 tokens = g_strsplit(resource + strlen(tcp_prefix), "/", 0);
263 address = tokens[0];
264 port = tokens[1];
265 if (!address || !port || tokens[2]) {
7cf1a98d 266 sr_err("Invalid parameters.");
3520422f
ML
267 g_strfreev(tokens);
268 return SR_ERR_ARG;
269 }
270 scpi = scpi_tcp_dev_inst_new(address, port);
271 g_strfreev(tokens);
272 if (!scpi)
0dc7b43e
ML
273 return SR_ERR_MALLOC;
274 } else {
7cf1a98d 275 sr_dbg("Opening serial device %s.", resource);
3520422f 276 if (!(scpi = scpi_serial_dev_inst_new(resource, serialcomm)))
0dc7b43e
ML
277 return SR_ERR_MALLOC;
278 }
9bd4c956 279
ae1bc1cc 280 if (sr_scpi_open(scpi) != SR_OK) {
10afee13 281 sr_info("Couldn't open SCPI device.");
ae1bc1cc 282 sr_scpi_free(scpi);
9bd4c956 283 return SR_ERR;
ae1bc1cc 284 };
9bd4c956 285
ae1bc1cc
ML
286 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
287 sr_info("Couldn't get IDN response.");
288 sr_scpi_close(scpi);
289 sr_scpi_free(scpi);
290 return SR_ERR;
ca55277c 291 }
e0b7d23c 292
ca55277c 293 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
10afee13
ML
294 if (!strcasecmp(hw_info->manufacturer, supported_models[i].vendor) &&
295 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 296 model = &supported_models[i];
ca55277c 297 break;
fb6e5ba8 298 }
ca55277c 299 }
fb6e5ba8 300
bafd4890 301 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
ae1bc1cc
ML
302 hw_info->manufacturer, hw_info->model,
303 hw_info->firmware_version))) {
304 sr_scpi_hw_info_free(hw_info);
b4936bae 305 sr_scpi_close(scpi);
ae1bc1cc 306 sr_scpi_free(scpi);
ca55277c
ML
307 return SR_ERR_NA;
308 }
fb6e5ba8 309
ae1bc1cc 310 sr_scpi_hw_info_free(hw_info);
b4936bae 311 sr_scpi_close(scpi);
ae1bc1cc
ML
312
313 sdi->conn = scpi;
fb6e5ba8 314
cc9fd2d2 315 sdi->driver = di;
ae1bc1cc 316 sdi->inst_type = SR_INST_SCPI;
512bb890 317
cc9fd2d2 318 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
ca55277c 319 return SR_ERR_MALLOC;
ae1bc1cc 320
cc9fd2d2 321 devc->limit_frames = 0;
bafd4890 322 devc->model = model;
512bb890 323
821fbcad
ML
324 for (i = 0; i < model->analog_channels; i++) {
325 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
ca55277c 326 return SR_ERR_MALLOC;
821fbcad 327 probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE, channel_name);
ca55277c 328 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
329 devc->analog_groups[i].name = channel_name;
330 devc->analog_groups[i].probes = g_slist_append(NULL, probe);
331 sdi->probe_groups = g_slist_append(sdi->probe_groups,
332 &devc->analog_groups[i]);
ca55277c 333 }
512bb890 334
bafd4890 335 if (devc->model->has_digital) {
ca55277c
ML
336 for (i = 0; i < 16; i++) {
337 if (!(channel_name = g_strdup_printf("D%d", i)))
338 return SR_ERR_MALLOC;
339 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
340 g_free(channel_name);
341 if (!probe)
342 return SR_ERR_MALLOC;
343 sdi->probes = g_slist_append(sdi->probes, probe);
3d3a601e
ML
344 devc->digital_group.probes = g_slist_append(
345 devc->digital_group.probes, probe);
512bb890 346 }
b3916147
ML
347 devc->digital_group.name = "LA";
348 sdi->probe_groups = g_slist_append(sdi->probe_groups,
349 &devc->digital_group);
ca55277c 350 }
bafd4890
ML
351
352 for (i = 0; i < NUM_TIMEBASE; i++) {
353 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
354 devc->timebases = &timebases[i];
355 if (!memcmp(&devc->model->max_timebase, &timebases[i], sizeof(uint64_t[2])))
356 devc->num_timebases = &timebases[i] - devc->timebases + 1;
357 }
358
0709197d
ML
359 for (i = 0; i < NUM_VDIV; i++)
360 if (!memcmp(&devc->model->min_vdiv, &vdivs[i], sizeof(uint64_t[2])))
6ff1394e 361 devc->vdivs = &vdivs[i];
bafd4890 362
babab622
ML
363 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
364 return SR_ERR_MALLOC;
365 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
366 return SR_ERR_MALLOC;
367
368 devc->data_source = DATA_SOURCE_LIVE;
369
cc9fd2d2
BV
370 sdi->priv = devc;
371
372 *devices = g_slist_append(NULL, sdi);
512bb890 373
ca55277c
ML
374 return SR_OK;
375}
512bb890 376
6078d2c9 377static GSList *scan(GSList *options)
ca55277c
ML
378{
379 struct drv_context *drvc;
ca55277c 380 struct sr_config *src;
cc9fd2d2 381 GSList *l, *devices;
ca55277c 382 GDir *dir;
ca55277c 383 int ret;
cc9fd2d2
BV
384 const gchar *dev_name;
385 gchar *port = NULL;
0dc7b43e 386 gchar *serialcomm = NULL;
fb6e5ba8 387
ca55277c 388 drvc = di->priv;
d2e0b1fa 389
ca55277c
ML
390 for (l = options; l; l = l->next) {
391 src = l->data;
0dc7b43e
ML
392 switch (src->key) {
393 case SR_CONF_CONN:
cc9fd2d2 394 port = (char *)g_variant_get_string(src->data, NULL);
ca55277c 395 break;
0dc7b43e
ML
396 case SR_CONF_SERIALCOMM:
397 serialcomm = (char *)g_variant_get_string(src->data, NULL);
398 break;
fb6e5ba8 399 }
ca55277c 400 }
fb6e5ba8 401
46a743c1 402 devices = NULL;
cc9fd2d2 403 if (port) {
0dc7b43e
ML
404 if (probe_port(port, serialcomm, &devices) == SR_ERR_MALLOC) {
405 g_free(port);
406 if (serialcomm)
407 g_free(serialcomm);
ca55277c 408 return NULL;
0dc7b43e 409 }
ca55277c 410 } else {
da970d24
BV
411 if (!(dir = g_dir_open("/sys/class/usbmisc/", 0, NULL)))
412 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
413 return NULL;
ca55277c 414 while ((dev_name = g_dir_read_name(dir))) {
cc9fd2d2 415 if (strncmp(dev_name, "usbtmc", 6))
ca55277c 416 continue;
cc9fd2d2 417 port = g_strconcat("/dev/", dev_name, NULL);
0dc7b43e 418 ret = probe_port(port, serialcomm, &devices);
cc9fd2d2 419 g_free(port);
0dc7b43e
ML
420 if (serialcomm)
421 g_free(serialcomm);
ca55277c
ML
422 if (ret == SR_ERR_MALLOC) {
423 g_dir_close(dir);
ca55277c 424 return NULL;
6bb192bc
ML
425 }
426 }
ca55277c
ML
427 g_dir_close(dir);
428 }
f4816ac6 429
46a743c1
BV
430 /* Tack a copy of the newly found devices onto the driver list. */
431 l = g_slist_copy(devices);
432 drvc->instances = g_slist_concat(drvc->instances, l);
cc9fd2d2 433
f4816ac6
ML
434 return devices;
435}
436
6078d2c9 437static GSList *dev_list(void)
f4816ac6 438{
0e94d524 439 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
440}
441
6078d2c9 442static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 443{
ae1bc1cc 444 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 445
ae1bc1cc 446 if (sr_scpi_open(scpi) < 0)
e0b7d23c 447 return SR_ERR;
e0b7d23c 448
3086efdd 449 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 450 return SR_ERR;
f4816ac6 451
46a743c1 452 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 453
f4816ac6
ML
454 return SR_OK;
455}
456
6078d2c9 457static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 458{
ae1bc1cc
ML
459 struct sr_scpi_dev_inst *scpi;
460
461 scpi = sdi->conn;
e0b7d23c 462
ae1bc1cc
ML
463 if (scpi) {
464 if (sr_scpi_close(scpi) < 0)
465 return SR_ERR;
cc9fd2d2
BV
466 sdi->status = SR_ST_INACTIVE;
467 }
f4816ac6
ML
468
469 return SR_OK;
470}
471
6078d2c9 472static int cleanup(void)
f4816ac6 473{
3b412e3a 474 return dev_clear();
f4816ac6
ML
475}
476
8f996b89
ML
477static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
478 const struct sr_probe_group *probe_group)
d62d7ad1 479{
e43fdd8d 480 struct dev_context *devc;
d62d7ad1 481
e43fdd8d
BV
482 if (!sdi || !(devc = sdi->priv))
483 return SR_ERR_ARG;
484
be60a9e4
BV
485 /* If a probe group is specified, it must be a valid one. */
486 if (probe_group) {
487 if (probe_group != &devc->analog_groups[0]
488 && probe_group != &devc->analog_groups[1]) {
489 sr_err("Invalid probe group specified.");
490 return SR_ERR;
491 }
492 }
493
d62d7ad1
BV
494 switch (id) {
495 case SR_CONF_NUM_TIMEBASE:
0709197d 496 *data = g_variant_new_int32(devc->model->num_horizontal_divs);
d62d7ad1
BV
497 break;
498 case SR_CONF_NUM_VDIV:
0709197d 499 *data = g_variant_new_int32(8);
babab622
ML
500 case SR_CONF_DATA_SOURCE:
501 if (devc->data_source == DATA_SOURCE_LIVE)
502 *data = g_variant_new_string("Live");
503 else if (devc->data_source == DATA_SOURCE_MEMORY)
504 *data = g_variant_new_string("Memory");
505 else
506 *data = g_variant_new_string("Segmented");
507 break;
d62d7ad1 508 default:
bd6fbf62 509 return SR_ERR_NA;
d62d7ad1
BV
510 }
511
512 return SR_OK;
513}
514
8f996b89
ML
515static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
516 const struct sr_probe_group *probe_group)
f4816ac6 517{
29d957ce 518 struct dev_context *devc;
f6a0ac9f 519 uint64_t tmp_u64, p, q;
254dd102 520 double t_dbl;
f48e0249 521 unsigned int i, j;
254dd102
BV
522 int ret;
523 const char *tmp_str;
f4816ac6 524
e43fdd8d
BV
525 if (!(devc = sdi->priv))
526 return SR_ERR_ARG;
29d957ce 527
e73ffd42
BV
528 if (sdi->status != SR_ST_ACTIVE)
529 return SR_ERR_DEV_CLOSED;
f4816ac6 530
be60a9e4
BV
531 /* If a probe group is specified, it must be a valid one. */
532 if (probe_group) {
533 if (probe_group != &devc->analog_groups[0]
534 && probe_group != &devc->analog_groups[1]) {
535 sr_err("Invalid probe group specified.");
536 return SR_ERR;
537 }
538 }
539
f4816ac6 540 ret = SR_OK;
035a1078 541 switch (id) {
1953564a 542 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 543 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 544 break;
1953564a 545 case SR_CONF_TRIGGER_SLOPE:
f6a0ac9f 546 tmp_u64 = g_variant_get_uint64(data);
254dd102
BV
547 if (tmp_u64 != 0 && tmp_u64 != 1)
548 return SR_ERR;
549 g_free(devc->trigger_slope);
550 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
551 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 552 break;
1953564a 553 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
554 t_dbl = g_variant_get_double(data);
555 if (t_dbl < 0.0 || t_dbl > 1.0)
556 return SR_ERR;
557 devc->horiz_triggerpos = t_dbl;
558 /* We have the trigger offset as a percentage of the frame, but
559 * need to express this in seconds. */
bafd4890 560 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
254dd102 561 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
e0b7d23c 562 break;
1953564a 563 case SR_CONF_TIMEBASE:
f6a0ac9f 564 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
565 for (i = 0; i < devc->num_timebases; i++) {
566 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102
BV
567 devc->timebase = (float)p / q;
568 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
f6a0ac9f
BV
569 break;
570 }
571 }
bafd4890 572 if (i == devc->num_timebases)
254dd102 573 ret = SR_ERR_ARG;
e0b7d23c 574 break;
1953564a 575 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 576 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
577 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
578 if (!strcmp(trigger_sources[i], tmp_str)) {
579 g_free(devc->trigger_source);
580 devc->trigger_source = g_strdup(trigger_sources[i]);
581 if (!strcmp(devc->trigger_source, "AC Line"))
582 tmp_str = "ACL";
583 else if (!strcmp(devc->trigger_source, "CH1"))
584 tmp_str = "CHAN1";
585 else if (!strcmp(devc->trigger_source, "CH2"))
586 tmp_str = "CHAN2";
821fbcad
ML
587 else if (!strcmp(devc->trigger_source, "CH3"))
588 tmp_str = "CHAN3";
589 else if (!strcmp(devc->trigger_source, "CH4"))
590 tmp_str = "CHAN4";
254dd102
BV
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);
0709197d 731 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
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;
29d957ce 782
e73ffd42
BV
783 if (sdi->status != SR_ST_ACTIVE)
784 return SR_ERR_DEV_CLOSED;
e0b7d23c 785
ae1bc1cc 786 scpi = sdi->conn;
29d957ce
UH
787 devc = sdi->priv;
788
254dd102
BV
789 for (l = sdi->probes; l; l = l->next) {
790 probe = l->data;
6bb192bc
ML
791 sr_dbg("handling probe %s", probe->name);
792 if (probe->type == SR_PROBE_ANALOG) {
793 if (probe->enabled)
794 devc->enabled_analog_probes = g_slist_append(
795 devc->enabled_analog_probes, probe);
796 if (probe->enabled != devc->analog_channels[probe->index]) {
797 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
798 if (set_cfg(sdi, ":CHAN%d:DISP %s", probe->index + 1,
799 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
800 return SR_ERR;
801 }
802 } else if (probe->type == SR_PROBE_LOGIC) {
803 if (probe->enabled)
804 devc->enabled_digital_probes = g_slist_append(
805 devc->enabled_digital_probes, probe);
806 if (probe->enabled != devc->digital_channels[probe->index]) {
807 /* Enabled channel is currently disabled, or vice versa. */
6396b0a7
ML
808 if (set_cfg(sdi, ":DIG%d:TURN %s", probe->index,
809 probe->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc
ML
810 return SR_ERR;
811 }
254dd102
BV
812 }
813 }
1fed20cb 814
6bb192bc 815 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
254dd102 816 return SR_ERR;
e0b7d23c 817
1fed20cb 818 if (devc->data_source == DATA_SOURCE_LIVE) {
6396b0a7 819 if (set_cfg(sdi, ":RUN") != SR_OK)
1fed20cb
ML
820 return SR_ERR;
821 } else if (devc->data_source == DATA_SOURCE_MEMORY) {
822 if (devc->model->series != RIGOL_DS2000) {
823 sr_err("Data source 'Memory' not supported for this device");
824 return SR_ERR;
825 }
826 } else if (devc->data_source == DATA_SOURCE_SEGMENTED) {
827 sr_err("Data source 'Segmented' not yet supported");
828 return SR_ERR;
829 }
830
ae1bc1cc 831 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
832
833 /* Send header packet to the session bus. */
29a27196 834 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 835
821fbcad
ML
836 if (devc->enabled_analog_probes)
837 devc->channel_entry = devc->enabled_analog_probes;
838 else
839 devc->channel_entry = devc->enabled_digital_probes;
840
babab622 841 if (devc->model->protocol == PROTOCOL_LEGACY) {
9e4b7d98
ML
842 devc->analog_frame_size = (devc->model->series == RIGOL_VS5000 ?
843 VS5000_ANALOG_LIVE_WAVEFORM_SIZE :
844 DS1000_ANALOG_LIVE_WAVEFORM_SIZE);
bafd4890 845 /* Fetch the first frame. */
677f85d0
ML
846 if (rigol_ds_channel_start(sdi) != SR_OK)
847 return SR_ERR;
6bb192bc 848 } else {
bafd4890 849 if (devc->enabled_analog_probes) {
babab622
ML
850 if (devc->data_source == DATA_SOURCE_MEMORY)
851 {
852 if (g_slist_length(devc->enabled_analog_probes) == 1)
853 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_1C;
854 else
855 devc->analog_frame_size = DS2000_ANALOG_MEM_WAVEFORM_SIZE_2C;
856 /* Apparently for the DS2000 the memory
857 * depth can only be set in Running state -
858 * this matches the behaviour of the UI. */
6396b0a7 859 if (set_cfg(sdi, ":RUN") != SR_OK)
babab622 860 return SR_ERR;
6396b0a7 861 if (set_cfg(sdi, "ACQ:MDEP %d", devc->analog_frame_size) != SR_OK)
babab622 862 return SR_ERR;
6396b0a7 863 if (set_cfg(sdi, ":STOP") != SR_OK)
babab622 864 return SR_ERR;
0d9f5a12
ML
865 } else {
866 if (devc->model->series == AGILENT_DSO1000)
867 devc->analog_frame_size = DSO1000_ANALOG_LIVE_WAVEFORM_SIZE;
868 else
869 devc->analog_frame_size = DS2000_ANALOG_LIVE_WAVEFORM_SIZE;
870 }
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};