]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
rigol-ds: Add the TRIGGER_SLOPE entry to config_get() and config_list()
[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>
2b0e4a46 26#include <math.h>
f4816ac6
ML
27#include <glib.h>
28#include "libsigrok.h"
29#include "libsigrok-internal.h"
30#include "protocol.h"
31
ca55277c
ML
32static const int32_t hwopts[] = {
33 SR_CONF_CONN,
0dc7b43e 34 SR_CONF_SERIALCOMM
ca55277c
ML
35};
36
f6a0ac9f 37static const int32_t hwcaps[] = {
1953564a 38 SR_CONF_OSCILLOSCOPE,
1953564a
BV
39 SR_CONF_TIMEBASE,
40 SR_CONF_TRIGGER_SOURCE,
41 SR_CONF_TRIGGER_SLOPE,
42 SR_CONF_HORIZ_TRIGGERPOS,
d62d7ad1 43 SR_CONF_NUM_TIMEBASE,
c1bcb8cc 44 SR_CONF_LIMIT_FRAMES,
4914dd4b 45 SR_CONF_SAMPLERATE,
f48e0249
ML
46};
47
48static const int32_t analog_hwcaps[] = {
d62d7ad1 49 SR_CONF_NUM_VDIV,
f48e0249 50 SR_CONF_VDIV,
78bcc55a 51 SR_CONF_COUPLING,
babab622 52 SR_CONF_DATA_SOURCE,
e0b7d23c
ML
53};
54
f6a0ac9f 55static const uint64_t timebases[][2] = {
e0b7d23c 56 /* nanoseconds */
8e06edf5 57 { 1, 1000000000 },
e0b7d23c
ML
58 { 2, 1000000000 },
59 { 5, 1000000000 },
60 { 10, 1000000000 },
61 { 20, 1000000000 },
62 { 50, 1000000000 },
63 { 100, 1000000000 },
64 { 500, 1000000000 },
65 /* microseconds */
66 { 1, 1000000 },
67 { 2, 1000000 },
68 { 5, 1000000 },
69 { 10, 1000000 },
70 { 20, 1000000 },
71 { 50, 1000000 },
72 { 100, 1000000 },
73 { 200, 1000000 },
74 { 500, 1000000 },
75 /* milliseconds */
76 { 1, 1000 },
77 { 2, 1000 },
78 { 5, 1000 },
79 { 10, 1000 },
80 { 20, 1000 },
81 { 50, 1000 },
82 { 100, 1000 },
83 { 200, 1000 },
84 { 500, 1000 },
85 /* seconds */
86 { 1, 1 },
87 { 2, 1 },
88 { 5, 1 },
89 { 10, 1 },
90 { 20, 1 },
91 { 50, 1 },
bafd4890
ML
92 { 100, 1 },
93 { 200, 1 },
94 { 500, 1 },
8e06edf5 95 { 1000, 1 },
e0b7d23c
ML
96};
97
f6a0ac9f 98static const uint64_t vdivs[][2] = {
bafd4890
ML
99 /* microvolts */
100 { 500, 1000000 },
e0b7d23c 101 /* millivolts */
bafd4890 102 { 1, 1000 },
e0b7d23c
ML
103 { 2, 1000 },
104 { 5, 1000 },
105 { 10, 1000 },
106 { 20, 1000 },
107 { 50, 1000 },
108 { 100, 1000 },
109 { 200, 1000 },
110 { 500, 1000 },
111 /* volts */
112 { 1, 1 },
113 { 2, 1 },
114 { 5, 1 },
115 { 10, 1 },
e0b7d23c
ML
116};
117
bafd4890
ML
118#define NUM_TIMEBASE ARRAY_SIZE(timebases)
119#define NUM_VDIV ARRAY_SIZE(vdivs)
120
e0b7d23c
ML
121static const char *trigger_sources[] = {
122 "CH1",
123 "CH2",
821fbcad
ML
124 "CH3",
125 "CH4",
e0b7d23c
ML
126 "EXT",
127 "AC Line",
6bb192bc
ML
128 "D0",
129 "D1",
130 "D2",
131 "D3",
132 "D4",
133 "D5",
134 "D6",
135 "D7",
136 "D8",
137 "D9",
138 "D10",
139 "D11",
140 "D12",
141 "D13",
142 "D14",
143 "D15",
e0b7d23c
ML
144};
145
5d336f11
AJ
146static const char *trigger_slopes[] = {
147 "r",
148 "f",
149};
150
e0b7d23c
ML
151static const char *coupling[] = {
152 "AC",
153 "DC",
154 "GND",
e0b7d23c
ML
155};
156
babab622
ML
157/* Do not change the order of entries */
158static const char *data_sources[] = {
159 "Live",
160 "Memory",
161 "Segmented",
162};
163
569d4dbd
ML
164enum vendor {
165 RIGOL,
166 AGILENT,
167};
168
169enum series {
170 VS5000,
171 DS1000,
172 DS2000,
173 DS2000A,
174 DSO1000,
175};
10afee13 176
569d4dbd
ML
177/* short name, full name */
178static const struct rigol_ds_vendor supported_vendors[] = {
179 [RIGOL] = {"Rigol", "Rigol Technologies"},
180 [AGILENT] = {"Agilent", "Rigol Technologies"},
181};
182
183#define VENDOR(x) &supported_vendors[x]
184/* vendor, series, protocol, max timebase, min vdiv, number of horizontal divs,
185 * live waveform samples, memory buffer samples */
186static const struct rigol_ds_series supported_series[] = {
187 [VS5000] = {VENDOR(RIGOL), "VS5000", PROTOCOL_V1, FORMAT_RAW,
188 {50, 1}, {2, 1000}, 14, 2048, 0},
189 [DS1000] = {VENDOR(RIGOL), "DS1000", PROTOCOL_V2, FORMAT_IEEE488_2,
190 {50, 1}, {2, 1000}, 12, 600, 1048576},
191 [DS2000] = {VENDOR(RIGOL), "DS2000", PROTOCOL_V3, FORMAT_IEEE488_2,
192 {500, 1}, {2, 1000}, 14, 1400, 14000},
193 [DS2000A] = {VENDOR(RIGOL), "DS2000A", PROTOCOL_V3, FORMAT_IEEE488_2,
194 {1000, 1}, {500, 1000000}, 14, 1400, 14000},
195 [DSO1000] = {VENDOR(AGILENT), "DSO1000", PROTOCOL_V3, FORMAT_IEEE488_2,
196 {50, 1}, {2, 1000}, 12, 600, 20480},
197};
10afee13 198
569d4dbd
ML
199#define SERIES(x) &supported_series[x]
200/* series, model, min timebase, analog channels, digital */
bafd4890 201static const struct rigol_ds_model supported_models[] = {
569d4dbd
ML
202 {SERIES(VS5000), "VS5022", {20, 1000000000}, 2, false},
203 {SERIES(VS5000), "VS5042", {10, 1000000000}, 2, false},
204 {SERIES(VS5000), "VS5062", {5, 1000000000}, 2, false},
205 {SERIES(VS5000), "VS5102", {2, 1000000000}, 2, false},
206 {SERIES(VS5000), "VS5202", {2, 1000000000}, 2, false},
207 {SERIES(VS5000), "VS5022D", {20, 1000000000}, 2, true},
208 {SERIES(VS5000), "VS5042D", {10, 1000000000}, 2, true},
209 {SERIES(VS5000), "VS5062D", {5, 1000000000}, 2, true},
210 {SERIES(VS5000), "VS5102D", {2, 1000000000}, 2, true},
211 {SERIES(VS5000), "VS5202D", {2, 1000000000}, 2, true},
212 {SERIES(DS1000), "DS1052E", {5, 1000000000}, 2, false},
213 {SERIES(DS1000), "DS1102E", {2, 1000000000}, 2, false},
214 {SERIES(DS1000), "DS1152E", {2, 1000000000}, 2, false},
215 {SERIES(DS1000), "DS1052D", {5, 1000000000}, 2, true},
216 {SERIES(DS1000), "DS1102D", {2, 1000000000}, 2, true},
217 {SERIES(DS1000), "DS1152D", {2, 1000000000}, 2, true},
218 {SERIES(DS2000), "DS2072", {5, 1000000000}, 2, false},
219 {SERIES(DS2000), "DS2102", {5, 1000000000}, 2, false},
220 {SERIES(DS2000), "DS2202", {2, 1000000000}, 2, false},
221 {SERIES(DS2000), "DS2302", {1, 1000000000}, 2, false},
222 {SERIES(DS2000A), "DS2072A", {5, 1000000000}, 2, false},
223 {SERIES(DS2000A), "DS2102A", {5, 1000000000}, 2, false},
224 {SERIES(DS2000A), "DS2202A", {2, 1000000000}, 2, false},
225 {SERIES(DS2000A), "DS2302A", {1, 1000000000}, 2, false},
226 {SERIES(DSO1000), "DSO1002A", {5, 1000000000}, 2, false},
227 {SERIES(DSO1000), "DSO1004A", {5, 1000000000}, 4, false},
228 {SERIES(DSO1000), "DSO1012A", {2, 1000000000}, 2, false},
229 {SERIES(DSO1000), "DSO1014A", {2, 1000000000}, 4, false},
230 {SERIES(DSO1000), "DSO1022A", {2, 1000000000}, 2, false},
231 {SERIES(DSO1000), "DSO1024A", {2, 1000000000}, 4, false},
512bb890
BV
232};
233
3086efdd
ML
234SR_PRIV struct sr_dev_driver rigol_ds_driver_info;
235static struct sr_dev_driver *di = &rigol_ds_driver_info;
f4816ac6 236
fa85f376 237static void clear_helper(void *priv)
f4816ac6 238{
f4816ac6 239 struct dev_context *devc;
f4816ac6 240
ba358ffd 241 devc = priv;
babab622
ML
242 g_free(devc->data);
243 g_free(devc->buffer);
fa85f376
UH
244 g_free(devc->coupling[0]);
245 g_free(devc->coupling[1]);
246 g_free(devc->trigger_source);
247 g_free(devc->trigger_slope);
a68bf88e
UH
248 g_slist_free(devc->analog_groups[0].channels);
249 g_slist_free(devc->analog_groups[1].channels);
250 g_slist_free(devc->digital_group.channels);
fa85f376 251}
f4816ac6 252
3b412e3a 253static int dev_clear(void)
fa85f376
UH
254{
255 return std_dev_clear(di, clear_helper);
f4816ac6
ML
256}
257
6078d2c9 258static int init(struct sr_context *sr_ctx)
f4816ac6 259{
f6beaac5 260 return std_init(sr_ctx, di, LOG_PREFIX);
f4816ac6
ML
261}
262
9d3ae01b 263static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
f4816ac6 264{
cc9fd2d2
BV
265 struct dev_context *devc;
266 struct sr_dev_inst *sdi;
ae1bc1cc 267 struct sr_scpi_hw_info *hw_info;
ba7dd8bb 268 struct sr_channel *ch;
8dd0b290 269 long n[3];
f6a0ac9f 270 unsigned int i;
bafd4890 271 const struct rigol_ds_model *model = NULL;
569d4dbd 272 gchar *channel_name, **version;
fb6e5ba8 273
ae1bc1cc
ML
274 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
275 sr_info("Couldn't get IDN response.");
276 sr_scpi_close(scpi);
277 sr_scpi_free(scpi);
9d3ae01b 278 return NULL;
ca55277c 279 }
e0b7d23c 280
ca55277c 281 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
569d4dbd
ML
282 if (!strcasecmp(hw_info->manufacturer,
283 supported_models[i].series->vendor->full_name) &&
10afee13 284 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 285 model = &supported_models[i];
ca55277c 286 break;
fb6e5ba8 287 }
ca55277c 288 }
fb6e5ba8 289
bafd4890 290 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
569d4dbd
ML
291 model->series->vendor->name,
292 model->name,
ae1bc1cc
ML
293 hw_info->firmware_version))) {
294 sr_scpi_hw_info_free(hw_info);
b4936bae 295 sr_scpi_close(scpi);
ae1bc1cc 296 sr_scpi_free(scpi);
9d3ae01b 297 return NULL;
ca55277c 298 }
fb6e5ba8 299
b4936bae 300 sr_scpi_close(scpi);
ae1bc1cc
ML
301
302 sdi->conn = scpi;
fb6e5ba8 303
cc9fd2d2 304 sdi->driver = di;
ae1bc1cc 305 sdi->inst_type = SR_INST_SCPI;
512bb890 306
cc9fd2d2 307 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
9d3ae01b 308 return NULL;
ae1bc1cc 309
cc9fd2d2 310 devc->limit_frames = 0;
bafd4890 311 devc->model = model;
569d4dbd 312 devc->format = model->series->format;
8dd0b290 313
569d4dbd
ML
314 /* DS1000 models with firmware before 0.2.4 used the old data format. */
315 if (model->series == SERIES(DS1000)) {
8dd0b290
BV
316 version = g_strsplit(hw_info->firmware_version, ".", 0);
317 do {
318 if (!version[0] || !version[1] || !version[2])
319 break;
320 if (version[0][0] == 0 || version[1][0] == 0 || version[2][0] == 0)
321 break;
322 for (i = 0; i < 3; i++) {
323 if (sr_atol(version[i], &n[i]) != SR_OK)
324 break;
325 }
326 if (i != 3)
327 break;
328 if (n[0] != 0 || n[1] > 2)
329 break;
330 if (n[1] == 2 && n[2] > 3)
331 break;
569d4dbd
ML
332 sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
333 devc->format = FORMAT_RAW;
8dd0b290
BV
334 } while(0);
335 g_strfreev(version);
336 }
337
338 sr_scpi_hw_info_free(hw_info);
512bb890 339
821fbcad
ML
340 for (i = 0; i < model->analog_channels; i++) {
341 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
9d3ae01b 342 return NULL;
3f239f08 343 ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, channel_name);
ba7dd8bb 344 sdi->channels = g_slist_append(sdi->channels, ch);
3d3a601e 345 devc->analog_groups[i].name = channel_name;
ba7dd8bb 346 devc->analog_groups[i].channels = g_slist_append(NULL, ch);
660e398f 347 sdi->channel_groups = g_slist_append(sdi->channel_groups,
3d3a601e 348 &devc->analog_groups[i]);
ca55277c 349 }
512bb890 350
bafd4890 351 if (devc->model->has_digital) {
ca55277c
ML
352 for (i = 0; i < 16; i++) {
353 if (!(channel_name = g_strdup_printf("D%d", i)))
9d3ae01b 354 return NULL;
3f239f08 355 ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name);
ca55277c 356 g_free(channel_name);
ba7dd8bb 357 if (!ch)
9d3ae01b 358 return NULL;
ba7dd8bb 359 sdi->channels = g_slist_append(sdi->channels, ch);
a68bf88e 360 devc->digital_group.channels = g_slist_append(
ba7dd8bb 361 devc->digital_group.channels, ch);
512bb890 362 }
b3916147 363 devc->digital_group.name = "LA";
660e398f 364 sdi->channel_groups = g_slist_append(sdi->channel_groups,
b3916147 365 &devc->digital_group);
ca55277c 366 }
bafd4890
ML
367
368 for (i = 0; i < NUM_TIMEBASE; i++) {
369 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
370 devc->timebases = &timebases[i];
569d4dbd 371 if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2])))
bafd4890
ML
372 devc->num_timebases = &timebases[i] - devc->timebases + 1;
373 }
374
0709197d 375 for (i = 0; i < NUM_VDIV; i++)
569d4dbd 376 if (!memcmp(&devc->model->series->min_vdiv, &vdivs[i], sizeof(uint64_t[2])))
6ff1394e 377 devc->vdivs = &vdivs[i];
bafd4890 378
babab622 379 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
9d3ae01b 380 return NULL;
babab622 381 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
9d3ae01b 382 return NULL;
babab622
ML
383
384 devc->data_source = DATA_SOURCE_LIVE;
385
cc9fd2d2
BV
386 sdi->priv = devc;
387
9d3ae01b 388 return sdi;
ca55277c 389}
512bb890 390
6078d2c9 391static GSList *scan(GSList *options)
ca55277c 392{
9d3ae01b 393 return sr_scpi_scan(di->priv, options, probe_device);
f4816ac6
ML
394}
395
6078d2c9 396static GSList *dev_list(void)
f4816ac6 397{
0e94d524 398 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
399}
400
6078d2c9 401static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 402{
ae1bc1cc 403 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 404
ae1bc1cc 405 if (sr_scpi_open(scpi) < 0)
e0b7d23c 406 return SR_ERR;
e0b7d23c 407
3086efdd 408 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 409 return SR_ERR;
f4816ac6 410
46a743c1 411 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 412
f4816ac6
ML
413 return SR_OK;
414}
415
6078d2c9 416static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 417{
ae1bc1cc 418 struct sr_scpi_dev_inst *scpi;
22c19688 419 struct dev_context *devc;
ae1bc1cc 420
83dbd9f0
AJ
421 if (sdi->status != SR_ST_ACTIVE)
422 return SR_ERR_DEV_CLOSED;
464d4936 423
ae1bc1cc 424 scpi = sdi->conn;
22c19688
ML
425 devc = sdi->priv;
426
6e94eb41 427 if (devc->model->series->protocol == PROTOCOL_V2)
38354d9d 428 rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE");
e0b7d23c 429
ae1bc1cc
ML
430 if (scpi) {
431 if (sr_scpi_close(scpi) < 0)
432 return SR_ERR;
cc9fd2d2
BV
433 sdi->status = SR_ST_INACTIVE;
434 }
f4816ac6
ML
435
436 return SR_OK;
437}
438
6078d2c9 439static int cleanup(void)
f4816ac6 440{
3b412e3a 441 return dev_clear();
f4816ac6
ML
442}
443
5415e602
ML
444static int analog_frame_size(const struct sr_dev_inst *sdi)
445{
446 struct dev_context *devc = sdi->priv;
ba7dd8bb
UH
447 struct sr_channel *ch;
448 int analog_channels = 0;
5415e602
ML
449 GSList *l;
450
ba7dd8bb
UH
451 for (l = sdi->channels; l; l = l->next) {
452 ch = l->data;
3f239f08 453 if (ch->type == SR_CHANNEL_ANALOG && ch->enabled)
ba7dd8bb 454 analog_channels++;
569d4dbd
ML
455 }
456
ba7dd8bb 457 if (analog_channels == 0)
824eb2ac
ML
458 return 0;
459
569d4dbd
ML
460 switch (devc->data_source) {
461 case DATA_SOURCE_LIVE:
462 return devc->model->series->live_samples;
463 case DATA_SOURCE_MEMORY:
ba7dd8bb 464 return devc->model->series->buffer_samples / analog_channels;
470140fc 465 default:
569d4dbd 466 return 0;
5415e602
ML
467 }
468}
469
d22250a9
ML
470static int digital_frame_size(const struct sr_dev_inst *sdi)
471{
472 struct dev_context *devc = sdi->priv;
473
569d4dbd
ML
474 switch (devc->data_source) {
475 case DATA_SOURCE_LIVE:
476 return devc->model->series->live_samples * 2;
477 case DATA_SOURCE_MEMORY:
478 return devc->model->series->buffer_samples * 2;
d22250a9
ML
479 default:
480 return 0;
481 }
482}
483
8f996b89 484static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 485 const struct sr_channel_group *cg)
d62d7ad1 486{
e43fdd8d 487 struct dev_context *devc;
ba7dd8bb 488 struct sr_channel *ch;
2b0e4a46 489 const char *tmp_str;
c2b394d5 490 uint64_t samplerate;
2b0e4a46
AJ
491 int analog_channel = -1;
492 float smallest_diff = 0.0000000001;
493 int idx = -1;
494 unsigned i;
d62d7ad1 495
e43fdd8d
BV
496 if (!sdi || !(devc = sdi->priv))
497 return SR_ERR_ARG;
498
660e398f 499 /* If a channel group is specified, it must be a valid one. */
53b4680f 500 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 501 sr_err("Invalid channel group specified.");
969edf63 502 return SR_ERR;
be60a9e4
BV
503 }
504
53b4680f 505 if (cg) {
ba7dd8bb
UH
506 ch = g_slist_nth_data(cg->channels, 0);
507 if (!ch)
2b0e4a46 508 return SR_ERR;
3f239f08 509 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 510 if (ch->name[2] < '1' || ch->name[2] > '4')
2b0e4a46 511 return SR_ERR;
ba7dd8bb 512 analog_channel = ch->name[2] - '1';
2b0e4a46
AJ
513 }
514 }
515
d62d7ad1
BV
516 switch (id) {
517 case SR_CONF_NUM_TIMEBASE:
569d4dbd 518 *data = g_variant_new_int32(devc->model->series->num_horizontal_divs);
d62d7ad1
BV
519 break;
520 case SR_CONF_NUM_VDIV:
72ecba02 521 *data = g_variant_new_int32(NUM_VDIV);
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) /
569d4dbd 533 (devc->timebase * devc->model->series->num_horizontal_divs);
4914dd4b 534 *data = g_variant_new_uint64(samplerate);
c2b394d5 535 } else {
4914dd4b 536 return SR_ERR_NA;
c2b394d5 537 }
4914dd4b 538 break;
2b0e4a46
AJ
539 case SR_CONF_TRIGGER_SOURCE:
540 if (!strcmp(devc->trigger_source, "ACL"))
541 tmp_str = "AC Line";
542 else if (!strcmp(devc->trigger_source, "CHAN1"))
543 tmp_str = "CH1";
544 else if (!strcmp(devc->trigger_source, "CHAN2"))
545 tmp_str = "CH2";
546 else if (!strcmp(devc->trigger_source, "CHAN3"))
547 tmp_str = "CH3";
548 else if (!strcmp(devc->trigger_source, "CHAN4"))
549 tmp_str = "CH4";
550 else
551 tmp_str = devc->trigger_source;
552 *data = g_variant_new_string(tmp_str);
553 break;
5d336f11
AJ
554 case SR_CONF_TRIGGER_SLOPE:
555 if (!strcmp(devc->trigger_slope, "POS"))
556 tmp_str = "r";
557 else if (!strcmp(devc->trigger_slope, "NEG"))
558 tmp_str = "f";
559 else
560 return SR_ERR_NA;
561 *data = g_variant_new_string(tmp_str);
562 break;
2b0e4a46
AJ
563 case SR_CONF_TIMEBASE:
564 for (i = 0; i < devc->num_timebases; i++) {
565 float tb = (float)devc->timebases[i][0] / devc->timebases[i][1];
566 float diff = fabs(devc->timebase - tb);
567 if (diff < smallest_diff) {
568 smallest_diff = diff;
569 idx = i;
570 }
571 }
572 if (idx < 0)
573 return SR_ERR_NA;
574 *data = g_variant_new("(tt)", devc->timebases[idx][0],
575 devc->timebases[idx][1]);
576 break;
577 case SR_CONF_VDIV:
578 if (analog_channel < 0)
579 return SR_ERR_NA;
580 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
581 float vdiv = (float)vdivs[i][0] / vdivs[i][1];
582 float diff = fabs(devc->vdiv[analog_channel] - vdiv);
583 if (diff < smallest_diff) {
584 smallest_diff = diff;
585 idx = i;
586 }
587 }
588 if (idx < 0)
589 return SR_ERR_NA;
590 *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]);
591 break;
592 case SR_CONF_COUPLING:
593 if (analog_channel < 0)
594 return SR_ERR_NA;
595 *data = g_variant_new_string(devc->coupling[analog_channel]);
596 break;
d62d7ad1 597 default:
bd6fbf62 598 return SR_ERR_NA;
d62d7ad1
BV
599 }
600
601 return SR_OK;
602}
603
8f996b89 604static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 605 const struct sr_channel_group *cg)
f4816ac6 606{
29d957ce 607 struct dev_context *devc;
ca9b9f48 608 uint64_t p, q;
254dd102 609 double t_dbl;
f48e0249 610 unsigned int i, j;
254dd102
BV
611 int ret;
612 const char *tmp_str;
889ef4a0 613 char buffer[16];
f4816ac6 614
e43fdd8d
BV
615 if (!(devc = sdi->priv))
616 return SR_ERR_ARG;
29d957ce 617
e73ffd42
BV
618 if (sdi->status != SR_ST_ACTIVE)
619 return SR_ERR_DEV_CLOSED;
f4816ac6 620
660e398f 621 /* If a channel group is specified, it must be a valid one. */
53b4680f 622 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 623 sr_err("Invalid channel group specified.");
969edf63 624 return SR_ERR;
be60a9e4
BV
625 }
626
f4816ac6 627 ret = SR_OK;
035a1078 628 switch (id) {
1953564a 629 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 630 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 631 break;
1953564a 632 case SR_CONF_TRIGGER_SLOPE:
ca9b9f48
DE
633 tmp_str = g_variant_get_string(data, NULL);
634
635 if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r'))
636 return SR_ERR_ARG;
637
254dd102 638 g_free(devc->trigger_slope);
ca9b9f48 639 devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG");
38354d9d 640 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 641 break;
1953564a 642 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
643 t_dbl = g_variant_get_double(data);
644 if (t_dbl < 0.0 || t_dbl > 1.0)
645 return SR_ERR;
646 devc->horiz_triggerpos = t_dbl;
647 /* We have the trigger offset as a percentage of the frame, but
648 * need to express this in seconds. */
bafd4890 649 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
889ef4a0 650 g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl);
38354d9d 651 ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer);
e0b7d23c 652 break;
1953564a 653 case SR_CONF_TIMEBASE:
f6a0ac9f 654 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
655 for (i = 0; i < devc->num_timebases; i++) {
656 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102 657 devc->timebase = (float)p / q;
889ef4a0
AJ
658 g_ascii_formatd(buffer, sizeof(buffer), "%.9f",
659 devc->timebase);
38354d9d 660 ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer);
f6a0ac9f
BV
661 break;
662 }
663 }
bafd4890 664 if (i == devc->num_timebases)
254dd102 665 ret = SR_ERR_ARG;
e0b7d23c 666 break;
1953564a 667 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 668 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
669 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
670 if (!strcmp(trigger_sources[i], tmp_str)) {
671 g_free(devc->trigger_source);
672 devc->trigger_source = g_strdup(trigger_sources[i]);
673 if (!strcmp(devc->trigger_source, "AC Line"))
674 tmp_str = "ACL";
675 else if (!strcmp(devc->trigger_source, "CH1"))
676 tmp_str = "CHAN1";
677 else if (!strcmp(devc->trigger_source, "CH2"))
678 tmp_str = "CHAN2";
821fbcad
ML
679 else if (!strcmp(devc->trigger_source, "CH3"))
680 tmp_str = "CHAN3";
681 else if (!strcmp(devc->trigger_source, "CH4"))
682 tmp_str = "CHAN4";
254dd102
BV
683 else
684 tmp_str = (char *)devc->trigger_source;
38354d9d 685 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
254dd102
BV
686 break;
687 }
4e108ace 688 }
254dd102
BV
689 if (i == ARRAY_SIZE(trigger_sources))
690 ret = SR_ERR_ARG;
e0b7d23c 691 break;
1953564a 692 case SR_CONF_VDIV:
53b4680f 693 if (!cg) {
660e398f
UH
694 sr_err("No channel group specified.");
695 return SR_ERR_CHANNEL_GROUP;
be60a9e4 696 }
f6a0ac9f 697 g_variant_get(data, "(tt)", &p, &q);
f48e0249 698 for (i = 0; i < 2; i++) {
53b4680f 699 if (cg == &devc->analog_groups[i]) {
78bcc55a 700 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
701 if (vdivs[j][0] != p || vdivs[j][1] != q)
702 continue;
703 devc->vdiv[i] = (float)p / q;
889ef4a0
AJ
704 g_ascii_formatd(buffer, sizeof(buffer), "%.3f",
705 devc->vdiv[i]);
38354d9d 706 return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1,
889ef4a0 707 buffer);
f48e0249
ML
708 }
709 return SR_ERR_ARG;
710 }
e0b7d23c 711 }
f48e0249 712 return SR_ERR_NA;
1953564a 713 case SR_CONF_COUPLING:
53b4680f 714 if (!cg) {
660e398f
UH
715 sr_err("No channel group specified.");
716 return SR_ERR_CHANNEL_GROUP;
78bcc55a 717 }
f6a0ac9f 718 tmp_str = g_variant_get_string(data, NULL);
f48e0249 719 for (i = 0; i < 2; i++) {
53b4680f 720 if (cg == &devc->analog_groups[i]) {
78bcc55a
BV
721 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
722 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
723 g_free(devc->coupling[i]);
724 devc->coupling[i] = g_strdup(coupling[j]);
38354d9d 725 return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1,
f48e0249
ML
726 devc->coupling[i]);
727 }
728 }
729 return SR_ERR_ARG;
e0b7d23c
ML
730 }
731 }
f48e0249 732 return SR_ERR_NA;
babab622
ML
733 case SR_CONF_DATA_SOURCE:
734 tmp_str = g_variant_get_string(data, NULL);
735 if (!strcmp(tmp_str, "Live"))
736 devc->data_source = DATA_SOURCE_LIVE;
569d4dbd
ML
737 else if (devc->model->series->protocol >= PROTOCOL_V2
738 && !strcmp(tmp_str, "Memory"))
babab622 739 devc->data_source = DATA_SOURCE_MEMORY;
569d4dbd 740 else if (devc->model->series->protocol >= PROTOCOL_V3
babab622
ML
741 && !strcmp(tmp_str, "Segmented"))
742 devc->data_source = DATA_SOURCE_SEGMENTED;
743 else
744 return SR_ERR;
745 break;
f4816ac6 746 default:
bd6fbf62 747 ret = SR_ERR_NA;
29d957ce 748 break;
f4816ac6
ML
749 }
750
751 return ret;
752}
753
8f996b89 754static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 755 const struct sr_channel_group *cg)
a1c743fc 756{
861c447b
BV
757 GVariant *tuple, *rational[2];
758 GVariantBuilder gvb;
759 unsigned int i;
7cc1a550
ML
760 struct dev_context *devc = NULL;
761
762 if (sdi)
763 devc = sdi->priv;
8f996b89 764
e43fdd8d 765 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
766 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
767 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d 768 return SR_OK;
53b4680f 769 } else if (key == SR_CONF_DEVICE_OPTIONS && cg == NULL) {
e43fdd8d
BV
770 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
771 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
772 return SR_OK;
773 }
774
775 /* Every other option requires a valid device instance. */
776 if (!sdi || !(devc = sdi->priv))
777 return SR_ERR_ARG;
778
660e398f 779 /* If a channel group is specified, it must be a valid one. */
53b4680f
UH
780 if (cg) {
781 if (cg != &devc->analog_groups[0]
782 && cg != &devc->analog_groups[1]) {
660e398f 783 sr_err("Invalid channel group specified.");
be60a9e4
BV
784 return SR_ERR;
785 }
786 }
787
e43fdd8d 788 switch (key) {
9a6517d1 789 case SR_CONF_DEVICE_OPTIONS:
53b4680f 790 if (!cg) {
660e398f
UH
791 sr_err("No channel group specified.");
792 return SR_ERR_CHANNEL_GROUP;
be60a9e4 793 }
53b4680f 794 if (cg == &devc->digital_group) {
f48e0249
ML
795 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
796 NULL, 0, sizeof(int32_t));
797 return SR_OK;
798 } else {
799 for (i = 0; i < 2; i++) {
53b4680f 800 if (cg == &devc->analog_groups[i]) {
f48e0249
ML
801 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
802 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
803 return SR_OK;
804 }
805 }
806 return SR_ERR_NA;
807 }
5f77dffc 808 break;
2a7b113d 809 case SR_CONF_COUPLING:
53b4680f 810 if (!cg) {
660e398f
UH
811 sr_err("No channel group specified.");
812 return SR_ERR_CHANNEL_GROUP;
f48e0249 813 }
58f43369
BV
814 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
815 break;
e4f2b2ad 816 case SR_CONF_VDIV:
7cc1a550
ML
817 if (!devc)
818 /* Can't know this until we have the exact model. */
819 return SR_ERR_ARG;
53b4680f 820 if (!cg) {
660e398f
UH
821 sr_err("No channel group specified.");
822 return SR_ERR_CHANNEL_GROUP;
861c447b 823 }
58f43369 824 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
0709197d 825 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
826 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
827 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
828 tuple = g_variant_new_tuple(rational, 2);
829 g_variant_builder_add_value(&gvb, tuple);
830 }
831 *data = g_variant_builder_end(&gvb);
832 break;
41f5bd09 833 case SR_CONF_TIMEBASE:
7cc1a550
ML
834 if (!devc)
835 /* Can't know this until we have the exact model. */
836 return SR_ERR_ARG;
a31b2ccb
AJ
837 if (devc->num_timebases <= 0)
838 return SR_ERR_NA;
861c447b 839 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
840 for (i = 0; i < devc->num_timebases; i++) {
841 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
842 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
843 tuple = g_variant_new_tuple(rational, 2);
844 g_variant_builder_add_value(&gvb, tuple);
845 }
846 *data = g_variant_builder_end(&gvb);
41f5bd09 847 break;
328bafab 848 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
849 if (!devc)
850 /* Can't know this until we have the exact model. */
851 return SR_ERR_ARG;
f6a0ac9f 852 *data = g_variant_new_strv(trigger_sources,
bafd4890 853 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 854 break;
5d336f11
AJ
855 case SR_CONF_TRIGGER_SLOPE:
856 *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
857 break;
babab622
ML
858 case SR_CONF_DATA_SOURCE:
859 if (!devc)
860 /* Can't know this until we have the exact model. */
861 return SR_ERR_ARG;
569d4dbd
ML
862 switch (devc->model->series->protocol) {
863 case PROTOCOL_V1:
864 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
865 break;
866 case PROTOCOL_V2:
babab622 867 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
569d4dbd
ML
868 break;
869 default:
870 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
871 break;
872 }
babab622 873 break;
a1c743fc 874 default:
bd6fbf62 875 return SR_ERR_NA;
a1c743fc
BV
876 }
877
878 return SR_OK;
879}
880
254dd102 881static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 882{
ae1bc1cc 883 struct sr_scpi_dev_inst *scpi;
29d957ce 884 struct dev_context *devc;
ba7dd8bb 885 struct sr_channel *ch;
f76c24f6 886 struct sr_datafeed_packet packet;
254dd102 887 GSList *l;
29d957ce 888
e73ffd42
BV
889 if (sdi->status != SR_ST_ACTIVE)
890 return SR_ERR_DEV_CLOSED;
e0b7d23c 891
ae1bc1cc 892 scpi = sdi->conn;
29d957ce
UH
893 devc = sdi->priv;
894
51b294cd
ML
895 devc->num_frames = 0;
896
ba7dd8bb
UH
897 for (l = sdi->channels; l; l = l->next) {
898 ch = l->data;
899 sr_dbg("handling channel %s", ch->name);
3f239f08 900 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb
UH
901 if (ch->enabled)
902 devc->enabled_analog_channels = g_slist_append(
903 devc->enabled_analog_channels, ch);
904 if (ch->enabled != devc->analog_channels[ch->index]) {
6bb192bc 905 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
906 if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1,
907 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 908 return SR_ERR;
ba7dd8bb 909 devc->analog_channels[ch->index] = ch->enabled;
6bb192bc 910 }
3f239f08 911 } else if (ch->type == SR_CHANNEL_LOGIC) {
ba7dd8bb
UH
912 if (ch->enabled) {
913 devc->enabled_digital_channels = g_slist_append(
914 devc->enabled_digital_channels, ch);
04e8e01e
ML
915 /* Turn on LA module if currently off. */
916 if (!devc->la_enabled) {
38354d9d 917 if (rigol_ds_config_set(sdi, ":LA:DISP ON") != SR_OK)
04e8e01e
ML
918 return SR_ERR;
919 devc->la_enabled = TRUE;
920 }
921 }
ba7dd8bb 922 if (ch->enabled != devc->digital_channels[ch->index]) {
6bb192bc 923 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
924 if (rigol_ds_config_set(sdi, ":DIG%d:TURN %s", ch->index,
925 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 926 return SR_ERR;
ba7dd8bb 927 devc->digital_channels[ch->index] = ch->enabled;
6bb192bc 928 }
254dd102
BV
929 }
930 }
1fed20cb 931
ba7dd8bb 932 if (!devc->enabled_analog_channels && !devc->enabled_digital_channels)
254dd102 933 return SR_ERR;
e0b7d23c 934
ba7dd8bb
UH
935 /* Turn off LA module if on and no digital channels selected. */
936 if (devc->la_enabled && !devc->enabled_digital_channels)
38354d9d 937 if (rigol_ds_config_set(sdi, ":LA:DISP OFF") != SR_OK)
04e8e01e
ML
938 return SR_ERR;
939
e086b750
ML
940 /* Set memory mode. */
941 if (devc->data_source == DATA_SOURCE_SEGMENTED) {
942 sr_err("Data source 'Segmented' not yet supported");
943 return SR_ERR;
944 }
945
946 devc->analog_frame_size = analog_frame_size(sdi);
947 devc->digital_frame_size = digital_frame_size(sdi);
948
569d4dbd
ML
949 switch (devc->model->series->protocol) {
950 case PROTOCOL_V2:
e086b750
ML
951 if (rigol_ds_config_set(sdi, ":ACQ:MDEP LONG") != SR_OK)
952 return SR_ERR;
569d4dbd
ML
953 break;
954 case PROTOCOL_V3:
e086b750
ML
955 /* Apparently for the DS2000 the memory
956 * depth can only be set in Running state -
957 * this matches the behaviour of the UI. */
38354d9d 958 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1fed20cb 959 return SR_ERR;
e086b750
ML
960 if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d",
961 devc->analog_frame_size) != SR_OK)
962 return SR_ERR;
963 if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
1fed20cb 964 return SR_ERR;
569d4dbd
ML
965 break;
966 default:
967 break;
1fed20cb
ML
968 }
969
e086b750
ML
970 if (devc->data_source == DATA_SOURCE_LIVE)
971 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
972 return SR_ERR;
973
ae1bc1cc 974 sr_scpi_source_add(scpi, G_IO_IN, 50, rigol_ds_receive, (void *)sdi);
e0b7d23c
ML
975
976 /* Send header packet to the session bus. */
29a27196 977 std_session_send_df_header(cb_data, LOG_PREFIX);
e0b7d23c 978
ba7dd8bb
UH
979 if (devc->enabled_analog_channels)
980 devc->channel_entry = devc->enabled_analog_channels;
821fbcad 981 else
ba7dd8bb 982 devc->channel_entry = devc->enabled_digital_channels;
821fbcad 983
e086b750
ML
984 if (rigol_ds_capture_start(sdi) != SR_OK)
985 return SR_ERR;
f4816ac6 986
f76c24f6
ML
987 /* Start of first frame. */
988 packet.type = SR_DF_FRAME_BEGIN;
989 sr_session_send(cb_data, &packet);
990
f4816ac6
ML
991 return SR_OK;
992}
993
254dd102 994static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 995{
29d957ce 996 struct dev_context *devc;
ae1bc1cc 997 struct sr_scpi_dev_inst *scpi;
b751cf7a 998 struct sr_datafeed_packet packet;
29d957ce 999
f4816ac6
ML
1000 (void)cb_data;
1001
29d957ce
UH
1002 devc = sdi->priv;
1003
f4816ac6
ML
1004 if (sdi->status != SR_ST_ACTIVE) {
1005 sr_err("Device inactive, can't stop acquisition.");
1006 return SR_ERR;
1007 }
1008
b751cf7a
ML
1009 /* End of last frame. */
1010 packet.type = SR_DF_END;
1011 sr_session_send(sdi, &packet);
1012
ba7dd8bb
UH
1013 g_slist_free(devc->enabled_analog_channels);
1014 g_slist_free(devc->enabled_digital_channels);
1015 devc->enabled_analog_channels = NULL;
1016 devc->enabled_digital_channels = NULL;
ae1bc1cc
ML
1017 scpi = sdi->conn;
1018 sr_scpi_source_remove(scpi);
f4816ac6
ML
1019
1020 return SR_OK;
1021}
1022
3086efdd
ML
1023SR_PRIV struct sr_dev_driver rigol_ds_driver_info = {
1024 .name = "rigol-ds",
1025 .longname = "Rigol DS",
f4816ac6 1026 .api_version = 1,
6078d2c9
UH
1027 .init = init,
1028 .cleanup = cleanup,
1029 .scan = scan,
1030 .dev_list = dev_list,
3b412e3a 1031 .dev_clear = dev_clear,
d62d7ad1 1032 .config_get = config_get,
035a1078 1033 .config_set = config_set,
a1c743fc 1034 .config_list = config_list,
6078d2c9
UH
1035 .dev_open = dev_open,
1036 .dev_close = dev_close,
254dd102
BV
1037 .dev_acquisition_start = dev_acquisition_start,
1038 .dev_acquisition_stop = dev_acquisition_stop,
f4816ac6
ML
1039 .priv = NULL,
1040};