]> sigrok.org Git - libsigrok.git/blame - hardware/rigol-ds/api.c
build: Portability fixes.
[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 274 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
05238d28
ML
275 sr_info("Couldn't get IDN response, retrying.");
276 sr_scpi_close(scpi);
277 sr_scpi_open(scpi);
278 if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
279 sr_info("Couldn't get IDN response.");
280 return NULL;
281 }
ca55277c 282 }
e0b7d23c 283
ca55277c 284 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
569d4dbd
ML
285 if (!strcasecmp(hw_info->manufacturer,
286 supported_models[i].series->vendor->full_name) &&
10afee13 287 !strcmp(hw_info->model, supported_models[i].name)) {
bafd4890 288 model = &supported_models[i];
ca55277c 289 break;
fb6e5ba8 290 }
ca55277c 291 }
fb6e5ba8 292
bafd4890 293 if (!model || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
569d4dbd
ML
294 model->series->vendor->name,
295 model->name,
ae1bc1cc
ML
296 hw_info->firmware_version))) {
297 sr_scpi_hw_info_free(hw_info);
9d3ae01b 298 return NULL;
ca55277c 299 }
fb6e5ba8 300
ae1bc1cc 301 sdi->conn = scpi;
fb6e5ba8 302
cc9fd2d2 303 sdi->driver = di;
ae1bc1cc 304 sdi->inst_type = SR_INST_SCPI;
512bb890 305
cc9fd2d2 306 if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
9d3ae01b 307 return NULL;
ae1bc1cc 308
cc9fd2d2 309 devc->limit_frames = 0;
bafd4890 310 devc->model = model;
569d4dbd 311 devc->format = model->series->format;
8dd0b290 312
569d4dbd
ML
313 /* DS1000 models with firmware before 0.2.4 used the old data format. */
314 if (model->series == SERIES(DS1000)) {
8dd0b290
BV
315 version = g_strsplit(hw_info->firmware_version, ".", 0);
316 do {
317 if (!version[0] || !version[1] || !version[2])
318 break;
319 if (version[0][0] == 0 || version[1][0] == 0 || version[2][0] == 0)
320 break;
321 for (i = 0; i < 3; i++) {
322 if (sr_atol(version[i], &n[i]) != SR_OK)
323 break;
324 }
325 if (i != 3)
326 break;
327 if (n[0] != 0 || n[1] > 2)
328 break;
329 if (n[1] == 2 && n[2] > 3)
330 break;
569d4dbd
ML
331 sr_dbg("Found DS1000 firmware < 0.2.4, using raw data format.");
332 devc->format = FORMAT_RAW;
8dd0b290
BV
333 } while(0);
334 g_strfreev(version);
335 }
336
337 sr_scpi_hw_info_free(hw_info);
512bb890 338
821fbcad
ML
339 for (i = 0; i < model->analog_channels; i++) {
340 if (!(channel_name = g_strdup_printf("CH%d", i + 1)))
9d3ae01b 341 return NULL;
3f239f08 342 ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE, channel_name);
ba7dd8bb 343 sdi->channels = g_slist_append(sdi->channels, ch);
3d3a601e 344 devc->analog_groups[i].name = channel_name;
ba7dd8bb 345 devc->analog_groups[i].channels = g_slist_append(NULL, ch);
660e398f 346 sdi->channel_groups = g_slist_append(sdi->channel_groups,
3d3a601e 347 &devc->analog_groups[i]);
ca55277c 348 }
512bb890 349
bafd4890 350 if (devc->model->has_digital) {
ca55277c
ML
351 for (i = 0; i < 16; i++) {
352 if (!(channel_name = g_strdup_printf("D%d", i)))
9d3ae01b 353 return NULL;
3f239f08 354 ch = sr_channel_new(i, SR_CHANNEL_LOGIC, TRUE, channel_name);
ca55277c 355 g_free(channel_name);
ba7dd8bb 356 if (!ch)
9d3ae01b 357 return NULL;
ba7dd8bb 358 sdi->channels = g_slist_append(sdi->channels, ch);
a68bf88e 359 devc->digital_group.channels = g_slist_append(
ba7dd8bb 360 devc->digital_group.channels, ch);
512bb890 361 }
b3916147 362 devc->digital_group.name = "LA";
660e398f 363 sdi->channel_groups = g_slist_append(sdi->channel_groups,
b3916147 364 &devc->digital_group);
ca55277c 365 }
bafd4890
ML
366
367 for (i = 0; i < NUM_TIMEBASE; i++) {
368 if (!memcmp(&devc->model->min_timebase, &timebases[i], sizeof(uint64_t[2])))
369 devc->timebases = &timebases[i];
569d4dbd 370 if (!memcmp(&devc->model->series->max_timebase, &timebases[i], sizeof(uint64_t[2])))
bafd4890
ML
371 devc->num_timebases = &timebases[i] - devc->timebases + 1;
372 }
373
0709197d 374 for (i = 0; i < NUM_VDIV; i++)
569d4dbd 375 if (!memcmp(&devc->model->series->min_vdiv, &vdivs[i], sizeof(uint64_t[2])))
6ff1394e 376 devc->vdivs = &vdivs[i];
bafd4890 377
babab622 378 if (!(devc->buffer = g_try_malloc(ACQ_BUFFER_SIZE)))
9d3ae01b 379 return NULL;
babab622 380 if (!(devc->data = g_try_malloc(ACQ_BUFFER_SIZE * sizeof(float))))
9d3ae01b 381 return NULL;
babab622
ML
382
383 devc->data_source = DATA_SOURCE_LIVE;
384
cc9fd2d2
BV
385 sdi->priv = devc;
386
9d3ae01b 387 return sdi;
ca55277c 388}
512bb890 389
6078d2c9 390static GSList *scan(GSList *options)
ca55277c 391{
9d3ae01b 392 return sr_scpi_scan(di->priv, options, probe_device);
f4816ac6
ML
393}
394
6078d2c9 395static GSList *dev_list(void)
f4816ac6 396{
0e94d524 397 return ((struct drv_context *)(di->priv))->instances;
f4816ac6
ML
398}
399
6078d2c9 400static int dev_open(struct sr_dev_inst *sdi)
f4816ac6 401{
ae1bc1cc 402 struct sr_scpi_dev_inst *scpi = sdi->conn;
9bd4c956 403
ae1bc1cc 404 if (sr_scpi_open(scpi) < 0)
e0b7d23c 405 return SR_ERR;
e0b7d23c 406
3086efdd 407 if (rigol_ds_get_dev_cfg(sdi) != SR_OK)
254dd102 408 return SR_ERR;
f4816ac6 409
46a743c1 410 sdi->status = SR_ST_ACTIVE;
cc9fd2d2 411
f4816ac6
ML
412 return SR_OK;
413}
414
6078d2c9 415static int dev_close(struct sr_dev_inst *sdi)
f4816ac6 416{
ae1bc1cc 417 struct sr_scpi_dev_inst *scpi;
22c19688 418 struct dev_context *devc;
ae1bc1cc 419
83dbd9f0
AJ
420 if (sdi->status != SR_ST_ACTIVE)
421 return SR_ERR_DEV_CLOSED;
464d4936 422
ae1bc1cc 423 scpi = sdi->conn;
22c19688
ML
424 devc = sdi->priv;
425
6e94eb41 426 if (devc->model->series->protocol == PROTOCOL_V2)
38354d9d 427 rigol_ds_config_set(sdi, ":KEY:LOCK DISABLE");
e0b7d23c 428
ae1bc1cc
ML
429 if (scpi) {
430 if (sr_scpi_close(scpi) < 0)
431 return SR_ERR;
cc9fd2d2
BV
432 sdi->status = SR_ST_INACTIVE;
433 }
f4816ac6
ML
434
435 return SR_OK;
436}
437
6078d2c9 438static int cleanup(void)
f4816ac6 439{
3b412e3a 440 return dev_clear();
f4816ac6
ML
441}
442
5415e602
ML
443static int analog_frame_size(const struct sr_dev_inst *sdi)
444{
445 struct dev_context *devc = sdi->priv;
ba7dd8bb
UH
446 struct sr_channel *ch;
447 int analog_channels = 0;
5415e602
ML
448 GSList *l;
449
ba7dd8bb
UH
450 for (l = sdi->channels; l; l = l->next) {
451 ch = l->data;
3f239f08 452 if (ch->type == SR_CHANNEL_ANALOG && ch->enabled)
ba7dd8bb 453 analog_channels++;
569d4dbd
ML
454 }
455
ba7dd8bb 456 if (analog_channels == 0)
824eb2ac
ML
457 return 0;
458
569d4dbd
ML
459 switch (devc->data_source) {
460 case DATA_SOURCE_LIVE:
461 return devc->model->series->live_samples;
462 case DATA_SOURCE_MEMORY:
ba7dd8bb 463 return devc->model->series->buffer_samples / analog_channels;
470140fc 464 default:
569d4dbd 465 return 0;
5415e602
ML
466 }
467}
468
d22250a9
ML
469static int digital_frame_size(const struct sr_dev_inst *sdi)
470{
471 struct dev_context *devc = sdi->priv;
472
569d4dbd
ML
473 switch (devc->data_source) {
474 case DATA_SOURCE_LIVE:
475 return devc->model->series->live_samples * 2;
476 case DATA_SOURCE_MEMORY:
477 return devc->model->series->buffer_samples * 2;
d22250a9
ML
478 default:
479 return 0;
480 }
481}
482
8f996b89 483static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 484 const struct sr_channel_group *cg)
d62d7ad1 485{
e43fdd8d 486 struct dev_context *devc;
ba7dd8bb 487 struct sr_channel *ch;
2b0e4a46 488 const char *tmp_str;
c2b394d5 489 uint64_t samplerate;
2b0e4a46
AJ
490 int analog_channel = -1;
491 float smallest_diff = 0.0000000001;
492 int idx = -1;
493 unsigned i;
d62d7ad1 494
e43fdd8d
BV
495 if (!sdi || !(devc = sdi->priv))
496 return SR_ERR_ARG;
497
660e398f 498 /* If a channel group is specified, it must be a valid one. */
53b4680f 499 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 500 sr_err("Invalid channel group specified.");
969edf63 501 return SR_ERR;
be60a9e4
BV
502 }
503
53b4680f 504 if (cg) {
ba7dd8bb
UH
505 ch = g_slist_nth_data(cg->channels, 0);
506 if (!ch)
2b0e4a46 507 return SR_ERR;
3f239f08 508 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb 509 if (ch->name[2] < '1' || ch->name[2] > '4')
2b0e4a46 510 return SR_ERR;
ba7dd8bb 511 analog_channel = ch->name[2] - '1';
2b0e4a46
AJ
512 }
513 }
514
d62d7ad1
BV
515 switch (id) {
516 case SR_CONF_NUM_TIMEBASE:
569d4dbd 517 *data = g_variant_new_int32(devc->model->series->num_horizontal_divs);
d62d7ad1
BV
518 break;
519 case SR_CONF_NUM_VDIV:
72ecba02 520 *data = g_variant_new_int32(NUM_VDIV);
babab622
ML
521 case SR_CONF_DATA_SOURCE:
522 if (devc->data_source == DATA_SOURCE_LIVE)
523 *data = g_variant_new_string("Live");
524 else if (devc->data_source == DATA_SOURCE_MEMORY)
525 *data = g_variant_new_string("Memory");
526 else
527 *data = g_variant_new_string("Segmented");
528 break;
4914dd4b
ML
529 case SR_CONF_SAMPLERATE:
530 if (devc->data_source == DATA_SOURCE_LIVE) {
c2b394d5 531 samplerate = analog_frame_size(sdi) /
569d4dbd 532 (devc->timebase * devc->model->series->num_horizontal_divs);
4914dd4b 533 *data = g_variant_new_uint64(samplerate);
c2b394d5 534 } else {
4914dd4b 535 return SR_ERR_NA;
c2b394d5 536 }
4914dd4b 537 break;
2b0e4a46
AJ
538 case SR_CONF_TRIGGER_SOURCE:
539 if (!strcmp(devc->trigger_source, "ACL"))
540 tmp_str = "AC Line";
541 else if (!strcmp(devc->trigger_source, "CHAN1"))
542 tmp_str = "CH1";
543 else if (!strcmp(devc->trigger_source, "CHAN2"))
544 tmp_str = "CH2";
545 else if (!strcmp(devc->trigger_source, "CHAN3"))
546 tmp_str = "CH3";
547 else if (!strcmp(devc->trigger_source, "CHAN4"))
548 tmp_str = "CH4";
549 else
550 tmp_str = devc->trigger_source;
551 *data = g_variant_new_string(tmp_str);
552 break;
5d336f11
AJ
553 case SR_CONF_TRIGGER_SLOPE:
554 if (!strcmp(devc->trigger_slope, "POS"))
555 tmp_str = "r";
556 else if (!strcmp(devc->trigger_slope, "NEG"))
557 tmp_str = "f";
558 else
559 return SR_ERR_NA;
560 *data = g_variant_new_string(tmp_str);
561 break;
2b0e4a46
AJ
562 case SR_CONF_TIMEBASE:
563 for (i = 0; i < devc->num_timebases; i++) {
564 float tb = (float)devc->timebases[i][0] / devc->timebases[i][1];
565 float diff = fabs(devc->timebase - tb);
566 if (diff < smallest_diff) {
567 smallest_diff = diff;
568 idx = i;
569 }
570 }
571 if (idx < 0)
572 return SR_ERR_NA;
573 *data = g_variant_new("(tt)", devc->timebases[idx][0],
574 devc->timebases[idx][1]);
575 break;
576 case SR_CONF_VDIV:
577 if (analog_channel < 0)
578 return SR_ERR_NA;
579 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
580 float vdiv = (float)vdivs[i][0] / vdivs[i][1];
581 float diff = fabs(devc->vdiv[analog_channel] - vdiv);
582 if (diff < smallest_diff) {
583 smallest_diff = diff;
584 idx = i;
585 }
586 }
587 if (idx < 0)
588 return SR_ERR_NA;
589 *data = g_variant_new("(tt)", vdivs[idx][0], vdivs[idx][1]);
590 break;
591 case SR_CONF_COUPLING:
592 if (analog_channel < 0)
593 return SR_ERR_NA;
594 *data = g_variant_new_string(devc->coupling[analog_channel]);
595 break;
d62d7ad1 596 default:
bd6fbf62 597 return SR_ERR_NA;
d62d7ad1
BV
598 }
599
600 return SR_OK;
601}
602
8f996b89 603static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi,
53b4680f 604 const struct sr_channel_group *cg)
f4816ac6 605{
29d957ce 606 struct dev_context *devc;
ca9b9f48 607 uint64_t p, q;
254dd102 608 double t_dbl;
f48e0249 609 unsigned int i, j;
254dd102
BV
610 int ret;
611 const char *tmp_str;
889ef4a0 612 char buffer[16];
f4816ac6 613
e43fdd8d
BV
614 if (!(devc = sdi->priv))
615 return SR_ERR_ARG;
29d957ce 616
e73ffd42
BV
617 if (sdi->status != SR_ST_ACTIVE)
618 return SR_ERR_DEV_CLOSED;
f4816ac6 619
660e398f 620 /* If a channel group is specified, it must be a valid one. */
53b4680f 621 if (cg && !g_slist_find(sdi->channel_groups, cg)) {
660e398f 622 sr_err("Invalid channel group specified.");
969edf63 623 return SR_ERR;
be60a9e4
BV
624 }
625
f4816ac6 626 ret = SR_OK;
035a1078 627 switch (id) {
1953564a 628 case SR_CONF_LIMIT_FRAMES:
f6a0ac9f 629 devc->limit_frames = g_variant_get_uint64(data);
e0b7d23c 630 break;
1953564a 631 case SR_CONF_TRIGGER_SLOPE:
ca9b9f48
DE
632 tmp_str = g_variant_get_string(data, NULL);
633
634 if (!tmp_str || !(tmp_str[0] == 'f' || tmp_str[0] == 'r'))
635 return SR_ERR_ARG;
636
254dd102 637 g_free(devc->trigger_slope);
ca9b9f48 638 devc->trigger_slope = g_strdup((tmp_str[0] == 'r') ? "POS" : "NEG");
38354d9d 639 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
e0b7d23c 640 break;
1953564a 641 case SR_CONF_HORIZ_TRIGGERPOS:
254dd102
BV
642 t_dbl = g_variant_get_double(data);
643 if (t_dbl < 0.0 || t_dbl > 1.0)
644 return SR_ERR;
645 devc->horiz_triggerpos = t_dbl;
646 /* We have the trigger offset as a percentage of the frame, but
647 * need to express this in seconds. */
bafd4890 648 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * devc->num_timebases;
889ef4a0 649 g_ascii_formatd(buffer, sizeof(buffer), "%.6f", t_dbl);
38354d9d 650 ret = rigol_ds_config_set(sdi, ":TIM:OFFS %s", buffer);
e0b7d23c 651 break;
1953564a 652 case SR_CONF_TIMEBASE:
f6a0ac9f 653 g_variant_get(data, "(tt)", &p, &q);
bafd4890
ML
654 for (i = 0; i < devc->num_timebases; i++) {
655 if (devc->timebases[i][0] == p && devc->timebases[i][1] == q) {
254dd102 656 devc->timebase = (float)p / q;
889ef4a0
AJ
657 g_ascii_formatd(buffer, sizeof(buffer), "%.9f",
658 devc->timebase);
38354d9d 659 ret = rigol_ds_config_set(sdi, ":TIM:SCAL %s", buffer);
f6a0ac9f
BV
660 break;
661 }
662 }
bafd4890 663 if (i == devc->num_timebases)
254dd102 664 ret = SR_ERR_ARG;
e0b7d23c 665 break;
1953564a 666 case SR_CONF_TRIGGER_SOURCE:
f6a0ac9f 667 tmp_str = g_variant_get_string(data, NULL);
254dd102
BV
668 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
669 if (!strcmp(trigger_sources[i], tmp_str)) {
670 g_free(devc->trigger_source);
671 devc->trigger_source = g_strdup(trigger_sources[i]);
672 if (!strcmp(devc->trigger_source, "AC Line"))
673 tmp_str = "ACL";
674 else if (!strcmp(devc->trigger_source, "CH1"))
675 tmp_str = "CHAN1";
676 else if (!strcmp(devc->trigger_source, "CH2"))
677 tmp_str = "CHAN2";
821fbcad
ML
678 else if (!strcmp(devc->trigger_source, "CH3"))
679 tmp_str = "CHAN3";
680 else if (!strcmp(devc->trigger_source, "CH4"))
681 tmp_str = "CHAN4";
254dd102
BV
682 else
683 tmp_str = (char *)devc->trigger_source;
38354d9d 684 ret = rigol_ds_config_set(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
254dd102
BV
685 break;
686 }
4e108ace 687 }
254dd102
BV
688 if (i == ARRAY_SIZE(trigger_sources))
689 ret = SR_ERR_ARG;
e0b7d23c 690 break;
1953564a 691 case SR_CONF_VDIV:
53b4680f 692 if (!cg) {
660e398f
UH
693 sr_err("No channel group specified.");
694 return SR_ERR_CHANNEL_GROUP;
be60a9e4 695 }
f6a0ac9f 696 g_variant_get(data, "(tt)", &p, &q);
f48e0249 697 for (i = 0; i < 2; i++) {
53b4680f 698 if (cg == &devc->analog_groups[i]) {
78bcc55a 699 for (j = 0; j < ARRAY_SIZE(vdivs); j++) {
f48e0249
ML
700 if (vdivs[j][0] != p || vdivs[j][1] != q)
701 continue;
702 devc->vdiv[i] = (float)p / q;
889ef4a0
AJ
703 g_ascii_formatd(buffer, sizeof(buffer), "%.3f",
704 devc->vdiv[i]);
38354d9d 705 return rigol_ds_config_set(sdi, ":CHAN%d:SCAL %s", i + 1,
889ef4a0 706 buffer);
f48e0249
ML
707 }
708 return SR_ERR_ARG;
709 }
e0b7d23c 710 }
f48e0249 711 return SR_ERR_NA;
1953564a 712 case SR_CONF_COUPLING:
53b4680f 713 if (!cg) {
660e398f
UH
714 sr_err("No channel group specified.");
715 return SR_ERR_CHANNEL_GROUP;
78bcc55a 716 }
f6a0ac9f 717 tmp_str = g_variant_get_string(data, NULL);
f48e0249 718 for (i = 0; i < 2; i++) {
53b4680f 719 if (cg == &devc->analog_groups[i]) {
78bcc55a
BV
720 for (j = 0; j < ARRAY_SIZE(coupling); j++) {
721 if (!strcmp(tmp_str, coupling[j])) {
f48e0249
ML
722 g_free(devc->coupling[i]);
723 devc->coupling[i] = g_strdup(coupling[j]);
38354d9d 724 return rigol_ds_config_set(sdi, ":CHAN%d:COUP %s", i + 1,
f48e0249
ML
725 devc->coupling[i]);
726 }
727 }
728 return SR_ERR_ARG;
e0b7d23c
ML
729 }
730 }
f48e0249 731 return SR_ERR_NA;
babab622
ML
732 case SR_CONF_DATA_SOURCE:
733 tmp_str = g_variant_get_string(data, NULL);
734 if (!strcmp(tmp_str, "Live"))
735 devc->data_source = DATA_SOURCE_LIVE;
569d4dbd
ML
736 else if (devc->model->series->protocol >= PROTOCOL_V2
737 && !strcmp(tmp_str, "Memory"))
babab622 738 devc->data_source = DATA_SOURCE_MEMORY;
569d4dbd 739 else if (devc->model->series->protocol >= PROTOCOL_V3
babab622
ML
740 && !strcmp(tmp_str, "Segmented"))
741 devc->data_source = DATA_SOURCE_SEGMENTED;
742 else
743 return SR_ERR;
744 break;
f4816ac6 745 default:
bd6fbf62 746 ret = SR_ERR_NA;
29d957ce 747 break;
f4816ac6
ML
748 }
749
750 return ret;
751}
752
8f996b89 753static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi,
53b4680f 754 const struct sr_channel_group *cg)
a1c743fc 755{
861c447b
BV
756 GVariant *tuple, *rational[2];
757 GVariantBuilder gvb;
758 unsigned int i;
7cc1a550
ML
759 struct dev_context *devc = NULL;
760
761 if (sdi)
762 devc = sdi->priv;
8f996b89 763
e43fdd8d 764 if (key == SR_CONF_SCAN_OPTIONS) {
ca55277c
ML
765 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
766 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
e43fdd8d 767 return SR_OK;
53b4680f 768 } else if (key == SR_CONF_DEVICE_OPTIONS && cg == NULL) {
e43fdd8d
BV
769 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
770 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
771 return SR_OK;
772 }
773
774 /* Every other option requires a valid device instance. */
775 if (!sdi || !(devc = sdi->priv))
776 return SR_ERR_ARG;
777
660e398f 778 /* If a channel group is specified, it must be a valid one. */
53b4680f
UH
779 if (cg) {
780 if (cg != &devc->analog_groups[0]
781 && cg != &devc->analog_groups[1]) {
660e398f 782 sr_err("Invalid channel group specified.");
be60a9e4
BV
783 return SR_ERR;
784 }
785 }
786
e43fdd8d 787 switch (key) {
9a6517d1 788 case SR_CONF_DEVICE_OPTIONS:
53b4680f 789 if (!cg) {
660e398f
UH
790 sr_err("No channel group specified.");
791 return SR_ERR_CHANNEL_GROUP;
be60a9e4 792 }
53b4680f 793 if (cg == &devc->digital_group) {
f48e0249
ML
794 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
795 NULL, 0, sizeof(int32_t));
796 return SR_OK;
797 } else {
798 for (i = 0; i < 2; i++) {
53b4680f 799 if (cg == &devc->analog_groups[i]) {
f48e0249
ML
800 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
801 analog_hwcaps, ARRAY_SIZE(analog_hwcaps), sizeof(int32_t));
802 return SR_OK;
803 }
804 }
805 return SR_ERR_NA;
806 }
5f77dffc 807 break;
2a7b113d 808 case SR_CONF_COUPLING:
53b4680f 809 if (!cg) {
660e398f
UH
810 sr_err("No channel group specified.");
811 return SR_ERR_CHANNEL_GROUP;
f48e0249 812 }
58f43369
BV
813 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
814 break;
e4f2b2ad 815 case SR_CONF_VDIV:
7cc1a550
ML
816 if (!devc)
817 /* Can't know this until we have the exact model. */
818 return SR_ERR_ARG;
53b4680f 819 if (!cg) {
660e398f
UH
820 sr_err("No channel group specified.");
821 return SR_ERR_CHANNEL_GROUP;
861c447b 822 }
58f43369 823 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
0709197d 824 for (i = 0; i < NUM_VDIV; i++) {
bafd4890
ML
825 rational[0] = g_variant_new_uint64(devc->vdivs[i][0]);
826 rational[1] = g_variant_new_uint64(devc->vdivs[i][1]);
58f43369
BV
827 tuple = g_variant_new_tuple(rational, 2);
828 g_variant_builder_add_value(&gvb, tuple);
829 }
830 *data = g_variant_builder_end(&gvb);
831 break;
41f5bd09 832 case SR_CONF_TIMEBASE:
7cc1a550
ML
833 if (!devc)
834 /* Can't know this until we have the exact model. */
835 return SR_ERR_ARG;
a31b2ccb
AJ
836 if (devc->num_timebases <= 0)
837 return SR_ERR_NA;
861c447b 838 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
bafd4890
ML
839 for (i = 0; i < devc->num_timebases; i++) {
840 rational[0] = g_variant_new_uint64(devc->timebases[i][0]);
841 rational[1] = g_variant_new_uint64(devc->timebases[i][1]);
861c447b
BV
842 tuple = g_variant_new_tuple(rational, 2);
843 g_variant_builder_add_value(&gvb, tuple);
844 }
845 *data = g_variant_builder_end(&gvb);
41f5bd09 846 break;
328bafab 847 case SR_CONF_TRIGGER_SOURCE:
7cc1a550
ML
848 if (!devc)
849 /* Can't know this until we have the exact model. */
850 return SR_ERR_ARG;
f6a0ac9f 851 *data = g_variant_new_strv(trigger_sources,
bafd4890 852 devc->model->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
328bafab 853 break;
5d336f11
AJ
854 case SR_CONF_TRIGGER_SLOPE:
855 *data = g_variant_new_strv(trigger_slopes, ARRAY_SIZE(trigger_slopes));
856 break;
babab622
ML
857 case SR_CONF_DATA_SOURCE:
858 if (!devc)
859 /* Can't know this until we have the exact model. */
860 return SR_ERR_ARG;
569d4dbd
ML
861 switch (devc->model->series->protocol) {
862 case PROTOCOL_V1:
863 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 2);
864 break;
865 case PROTOCOL_V2:
babab622 866 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1);
569d4dbd
ML
867 break;
868 default:
869 *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources));
870 break;
871 }
babab622 872 break;
a1c743fc 873 default:
bd6fbf62 874 return SR_ERR_NA;
a1c743fc
BV
875 }
876
877 return SR_OK;
878}
879
254dd102 880static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
f4816ac6 881{
ae1bc1cc 882 struct sr_scpi_dev_inst *scpi;
29d957ce 883 struct dev_context *devc;
ba7dd8bb 884 struct sr_channel *ch;
f76c24f6 885 struct sr_datafeed_packet packet;
254dd102 886 GSList *l;
29d957ce 887
e73ffd42
BV
888 if (sdi->status != SR_ST_ACTIVE)
889 return SR_ERR_DEV_CLOSED;
e0b7d23c 890
ae1bc1cc 891 scpi = sdi->conn;
29d957ce
UH
892 devc = sdi->priv;
893
51b294cd
ML
894 devc->num_frames = 0;
895
ba7dd8bb
UH
896 for (l = sdi->channels; l; l = l->next) {
897 ch = l->data;
898 sr_dbg("handling channel %s", ch->name);
3f239f08 899 if (ch->type == SR_CHANNEL_ANALOG) {
ba7dd8bb
UH
900 if (ch->enabled)
901 devc->enabled_analog_channels = g_slist_append(
902 devc->enabled_analog_channels, ch);
903 if (ch->enabled != devc->analog_channels[ch->index]) {
6bb192bc 904 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
905 if (rigol_ds_config_set(sdi, ":CHAN%d:DISP %s", ch->index + 1,
906 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 907 return SR_ERR;
ba7dd8bb 908 devc->analog_channels[ch->index] = ch->enabled;
6bb192bc 909 }
3f239f08 910 } else if (ch->type == SR_CHANNEL_LOGIC) {
ba7dd8bb
UH
911 if (ch->enabled) {
912 devc->enabled_digital_channels = g_slist_append(
913 devc->enabled_digital_channels, ch);
04e8e01e
ML
914 /* Turn on LA module if currently off. */
915 if (!devc->la_enabled) {
38354d9d 916 if (rigol_ds_config_set(sdi, ":LA:DISP ON") != SR_OK)
04e8e01e
ML
917 return SR_ERR;
918 devc->la_enabled = TRUE;
919 }
920 }
ba7dd8bb 921 if (ch->enabled != devc->digital_channels[ch->index]) {
6bb192bc 922 /* Enabled channel is currently disabled, or vice versa. */
ba7dd8bb
UH
923 if (rigol_ds_config_set(sdi, ":DIG%d:TURN %s", ch->index,
924 ch->enabled ? "ON" : "OFF") != SR_OK)
6bb192bc 925 return SR_ERR;
ba7dd8bb 926 devc->digital_channels[ch->index] = ch->enabled;
6bb192bc 927 }
254dd102
BV
928 }
929 }
1fed20cb 930
ba7dd8bb 931 if (!devc->enabled_analog_channels && !devc->enabled_digital_channels)
254dd102 932 return SR_ERR;
e0b7d23c 933
ba7dd8bb
UH
934 /* Turn off LA module if on and no digital channels selected. */
935 if (devc->la_enabled && !devc->enabled_digital_channels)
38354d9d 936 if (rigol_ds_config_set(sdi, ":LA:DISP OFF") != SR_OK)
04e8e01e
ML
937 return SR_ERR;
938
e086b750
ML
939 /* Set memory mode. */
940 if (devc->data_source == DATA_SOURCE_SEGMENTED) {
941 sr_err("Data source 'Segmented' not yet supported");
942 return SR_ERR;
943 }
944
945 devc->analog_frame_size = analog_frame_size(sdi);
946 devc->digital_frame_size = digital_frame_size(sdi);
947
569d4dbd
ML
948 switch (devc->model->series->protocol) {
949 case PROTOCOL_V2:
99af83b7 950 if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK)
e086b750 951 return SR_ERR;
569d4dbd
ML
952 break;
953 case PROTOCOL_V3:
e086b750
ML
954 /* Apparently for the DS2000 the memory
955 * depth can only be set in Running state -
956 * this matches the behaviour of the UI. */
38354d9d 957 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
1fed20cb 958 return SR_ERR;
e086b750
ML
959 if (rigol_ds_config_set(sdi, ":ACQ:MDEP %d",
960 devc->analog_frame_size) != SR_OK)
961 return SR_ERR;
962 if (rigol_ds_config_set(sdi, ":STOP") != SR_OK)
1fed20cb 963 return SR_ERR;
569d4dbd
ML
964 break;
965 default:
966 break;
1fed20cb
ML
967 }
968
e086b750
ML
969 if (devc->data_source == DATA_SOURCE_LIVE)
970 if (rigol_ds_config_set(sdi, ":RUN") != SR_OK)
971 return SR_ERR;
972
102f1239
BV
973 sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
974 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 1017 scpi = sdi->conn;
102f1239 1018 sr_scpi_source_remove(sdi->session, 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};