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