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