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