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