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