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