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