]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/rigol-ds1xx2/api.c
Python bindings: Fix reported libsigrok version.
[libsigrok.git] / hardware / rigol-ds1xx2 / api.c
... / ...
CommitLineData
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2012 Martin Ling <martin-git@earth.li>
5 * Copyright (C) 2013 Bert Vermeulen <bert@biot.com>
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#include <fcntl.h>
22#include <unistd.h>
23#include <stdlib.h>
24#include <string.h>
25#include <glib.h>
26#include "libsigrok.h"
27#include "libsigrok-internal.h"
28#include "protocol.h"
29
30#define NUM_TIMEBASE 12
31#define NUM_VDIV 8
32
33static const int32_t hwcaps[] = {
34 SR_CONF_OSCILLOSCOPE,
35 SR_CONF_TIMEBASE,
36 SR_CONF_TRIGGER_SOURCE,
37 SR_CONF_TRIGGER_SLOPE,
38 SR_CONF_HORIZ_TRIGGERPOS,
39 SR_CONF_VDIV,
40 SR_CONF_COUPLING,
41 SR_CONF_NUM_TIMEBASE,
42 SR_CONF_NUM_VDIV,
43};
44
45static const uint64_t timebases[][2] = {
46 /* nanoseconds */
47 { 2, 1000000000 },
48 { 5, 1000000000 },
49 { 10, 1000000000 },
50 { 20, 1000000000 },
51 { 50, 1000000000 },
52 { 100, 1000000000 },
53 { 500, 1000000000 },
54 /* microseconds */
55 { 1, 1000000 },
56 { 2, 1000000 },
57 { 5, 1000000 },
58 { 10, 1000000 },
59 { 20, 1000000 },
60 { 50, 1000000 },
61 { 100, 1000000 },
62 { 200, 1000000 },
63 { 500, 1000000 },
64 /* milliseconds */
65 { 1, 1000 },
66 { 2, 1000 },
67 { 5, 1000 },
68 { 10, 1000 },
69 { 20, 1000 },
70 { 50, 1000 },
71 { 100, 1000 },
72 { 200, 1000 },
73 { 500, 1000 },
74 /* seconds */
75 { 1, 1 },
76 { 2, 1 },
77 { 5, 1 },
78 { 10, 1 },
79 { 20, 1 },
80 { 50, 1 },
81};
82
83static const uint64_t vdivs[][2] = {
84 /* millivolts */
85 { 2, 1000 },
86 { 5, 1000 },
87 { 10, 1000 },
88 { 20, 1000 },
89 { 50, 1000 },
90 { 100, 1000 },
91 { 200, 1000 },
92 { 500, 1000 },
93 /* volts */
94 { 1, 1 },
95 { 2, 1 },
96 { 5, 1 },
97 { 10, 1 },
98};
99
100static const char *trigger_sources[] = {
101 "CH1",
102 "CH2",
103 "EXT",
104 "AC Line",
105 "D0",
106 "D1",
107 "D2",
108 "D3",
109 "D4",
110 "D5",
111 "D6",
112 "D7",
113 "D8",
114 "D9",
115 "D10",
116 "D11",
117 "D12",
118 "D13",
119 "D14",
120 "D15",
121};
122
123static const char *coupling[] = {
124 "AC",
125 "DC",
126 "GND",
127};
128
129static const char *supported_models[] = {
130 "DS1052E",
131 "DS1102E",
132 "DS1052D",
133 "DS1102D",
134};
135
136SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
137static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
138
139/* Properly close and free all devices. */
140static int clear_instances(void)
141{
142 struct sr_dev_inst *sdi;
143 struct drv_context *drvc;
144 struct dev_context *devc;
145 GSList *l;
146
147 if (!(drvc = di->priv))
148 return SR_OK;
149
150 for (l = drvc->instances; l; l = l->next) {
151 if (!(sdi = l->data))
152 continue;
153 if (!(devc = sdi->priv))
154 continue;
155
156 g_free(devc->device);
157 g_free(devc->coupling[0]);
158 g_free(devc->coupling[1]);
159 g_free(devc->trigger_source);
160 g_free(devc->trigger_slope);
161 close(devc->fd);
162
163 sr_dev_inst_free(sdi);
164 }
165
166 g_slist_free(drvc->instances);
167 drvc->instances = NULL;
168
169 return SR_OK;
170}
171
172static int set_cfg(const struct sr_dev_inst *sdi, const char *format, ...)
173{
174 struct dev_context *devc;
175 va_list args;
176 char buf[256];
177
178 devc = sdi->priv;
179
180 va_start(args, format);
181 vsnprintf(buf, 255, format, args);
182 va_end(args);
183 if (rigol_ds1xx2_send(devc, buf) != SR_OK)
184 return SR_ERR;
185
186 /* When setting a bunch of parameters in a row, the DS1052E scrambles
187 * some of them unless there is at least 100ms delay in between. */
188 sr_spew("delay %dms", 100);
189 g_usleep(100);
190
191 return SR_OK;
192}
193
194static int hw_init(struct sr_context *sr_ctx)
195{
196 return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
197}
198
199static GSList *hw_scan(GSList *options)
200{
201 struct drv_context *drvc;
202 struct sr_dev_inst *sdi;
203 struct dev_context *devc;
204 struct sr_probe *probe;
205 GSList *devices;
206 GDir *dir;
207 const gchar *dev_name;
208 const gchar *dev_dir = "/dev/";
209 const gchar *prefix = "usbtmc";
210 gchar *device;
211 const gchar *idn_query = "*IDN?";
212 unsigned int i;
213 int len, num_tokens, fd;
214 const gchar *delimiter = ",";
215 gchar **tokens;
216 const char *manufacturer, *model, *version;
217 gboolean matched = FALSE;
218 gboolean has_digital = FALSE;
219 char buf[256];
220 gchar *channel_name;
221
222 (void)options;
223
224 drvc = di->priv;
225 drvc->instances = NULL;
226
227 devices = NULL;
228
229 dir = g_dir_open("/sys/class/usb/", 0, NULL);
230
231 if (dir == NULL)
232 return NULL;
233
234 while ((dev_name = g_dir_read_name(dir)) != NULL) {
235 if (strncmp(dev_name, prefix, strlen(prefix)))
236 continue;
237
238 device = g_strconcat(dev_dir, dev_name, NULL);
239
240 fd = open(device, O_RDWR);
241 len = write(fd, idn_query, strlen(idn_query));
242 len = read(fd, buf, sizeof(buf));
243 close(fd);
244 if (len == 0) {
245 g_free(device);
246 return NULL;
247 }
248
249 buf[len] = 0;
250 tokens = g_strsplit(buf, delimiter, 0);
251 close(fd);
252 sr_dbg("response: %s %d [%s]", device, len, buf);
253
254 for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
255
256 if (num_tokens < 4) {
257 g_strfreev(tokens);
258 g_free(device);
259 return NULL;
260 }
261
262 manufacturer = tokens[0];
263 model = tokens[1];
264 version = tokens[3];
265
266 if (strcmp(manufacturer, "Rigol Technologies")) {
267 g_strfreev(tokens);
268 g_free(device);
269 return NULL;
270 }
271
272 for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
273 if (!strcmp(model, supported_models[i])) {
274 matched = 1;
275 has_digital = g_str_has_suffix(model, "D");
276 break;
277 }
278 }
279
280 if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
281 manufacturer, model, version))) {
282 g_strfreev(tokens);
283 g_free(device);
284 return NULL;
285 }
286
287 g_strfreev(tokens);
288
289 if (!(devc = g_try_malloc0(sizeof(struct dev_context)))) {
290 sr_err("Device context malloc failed.");
291 g_free(device);
292 return NULL;
293 }
294 devc->limit_frames = 0;
295 devc->device = device;
296 devc->has_digital = has_digital;
297 sdi->priv = devc;
298 sdi->driver = di;
299
300 for (i = 0; i < 2; i++) {
301 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
302 i == 0 ? "CH1" : "CH2")))
303 return NULL;
304 sdi->probes = g_slist_append(sdi->probes, probe);
305 }
306
307 if (devc->has_digital) {
308 for (i = 0; i < 16; i++) {
309 if (!(channel_name = g_strdup_printf("D%d", i)))
310 return NULL;
311 probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
312 g_free(channel_name);
313 if (!probe)
314 return NULL;
315 sdi->probes = g_slist_append(sdi->probes, probe);
316 }
317 }
318
319 drvc->instances = g_slist_append(drvc->instances, sdi);
320 devices = g_slist_append(devices, sdi);
321 }
322
323 g_dir_close(dir);
324
325 return devices;
326}
327
328static GSList *hw_dev_list(void)
329{
330 return ((struct drv_context *)(di->priv))->instances;
331}
332
333static int hw_dev_open(struct sr_dev_inst *sdi)
334{
335 struct dev_context *devc;
336 int fd;
337
338 devc = sdi->priv;
339
340 if ((fd = open(devc->device, O_RDWR)) == -1)
341 return SR_ERR;
342 devc->fd = fd;
343
344 if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
345 /* TODO: force configuration? */
346 return SR_ERR;
347
348 return SR_OK;
349}
350
351static int hw_dev_close(struct sr_dev_inst *sdi)
352{
353 struct dev_context *devc;
354
355 devc = sdi->priv;
356
357 close(devc->fd);
358
359 return SR_OK;
360}
361
362static int hw_cleanup(void)
363{
364 clear_instances();
365
366 return SR_OK;
367}
368
369static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
370{
371
372 (void)sdi;
373
374 switch (id) {
375 case SR_CONF_NUM_TIMEBASE:
376 *data = g_variant_new_int32(NUM_TIMEBASE);
377 break;
378 case SR_CONF_NUM_VDIV:
379 *data = g_variant_new_int32(NUM_VDIV);
380 break;
381 default:
382 return SR_ERR_ARG;
383 }
384
385 return SR_OK;
386}
387
388static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
389{
390 struct dev_context *devc;
391 uint64_t tmp_u64, p, q;
392 double t_dbl;
393 unsigned int i;
394 int ret;
395 const char *tmp_str;
396
397 devc = sdi->priv;
398
399 if (sdi->status != SR_ST_ACTIVE) {
400 sr_err("Device inactive, can't set config options.");
401 return SR_ERR;
402 }
403
404 ret = SR_OK;
405 switch (id) {
406 case SR_CONF_LIMIT_FRAMES:
407 devc->limit_frames = g_variant_get_uint64(data);
408 break;
409 case SR_CONF_TRIGGER_SLOPE:
410 tmp_u64 = g_variant_get_uint64(data);
411 if (tmp_u64 != 0 && tmp_u64 != 1)
412 return SR_ERR;
413 g_free(devc->trigger_slope);
414 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
415 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
416 break;
417 case SR_CONF_HORIZ_TRIGGERPOS:
418 t_dbl = g_variant_get_double(data);
419 if (t_dbl < 0.0 || t_dbl > 1.0)
420 return SR_ERR;
421 devc->horiz_triggerpos = t_dbl;
422 /* We have the trigger offset as a percentage of the frame, but
423 * need to express this in seconds. */
424 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
425 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
426 break;
427 case SR_CONF_TIMEBASE:
428 g_variant_get(data, "(tt)", &p, &q);
429 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
430 if (timebases[i][0] == p && timebases[i][1] == q) {
431 devc->timebase = (float)p / q;
432 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
433 break;
434 }
435 }
436 if (i == ARRAY_SIZE(timebases))
437 ret = SR_ERR_ARG;
438 break;
439 case SR_CONF_TRIGGER_SOURCE:
440 tmp_str = g_variant_get_string(data, NULL);
441 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
442 if (!strcmp(trigger_sources[i], tmp_str)) {
443 g_free(devc->trigger_source);
444 devc->trigger_source = g_strdup(trigger_sources[i]);
445 if (!strcmp(devc->trigger_source, "AC Line"))
446 tmp_str = "ACL";
447 else if (!strcmp(devc->trigger_source, "CH1"))
448 tmp_str = "CHAN1";
449 else if (!strcmp(devc->trigger_source, "CH2"))
450 tmp_str = "CHAN2";
451 else
452 tmp_str = (char *)devc->trigger_source;
453 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
454 break;
455 }
456 }
457 if (i == ARRAY_SIZE(trigger_sources))
458 ret = SR_ERR_ARG;
459 break;
460 case SR_CONF_VDIV:
461 g_variant_get(data, "(tt)", &p, &q);
462 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
463 if (vdivs[i][0] != p || vdivs[i][1] != q)
464 continue;
465 devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
466 set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
467 ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
468 break;
469 }
470 if (i == ARRAY_SIZE(vdivs))
471 ret = SR_ERR_ARG;
472 break;
473 case SR_CONF_COUPLING:
474 /* TODO: Not supporting coupling per channel yet. */
475 tmp_str = g_variant_get_string(data, NULL);
476 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
477 if (!strcmp(tmp_str, coupling[i])) {
478 g_free(devc->coupling[0]);
479 g_free(devc->coupling[1]);
480 devc->coupling[0] = g_strdup(coupling[i]);
481 devc->coupling[1] = g_strdup(coupling[i]);
482 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
483 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
484 break;
485 }
486 }
487 if (i == ARRAY_SIZE(coupling))
488 ret = SR_ERR_ARG;
489 break;
490 default:
491 sr_err("Unknown hardware capability: %d.", id);
492 ret = SR_ERR_ARG;
493 break;
494 }
495
496 return ret;
497}
498
499static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
500{
501 GVariant *tuple, *rational[2];
502 GVariantBuilder gvb;
503 unsigned int i;
504 struct dev_context *devc;
505
506 switch (key) {
507 case SR_CONF_DEVICE_OPTIONS:
508 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
509 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
510 break;
511 case SR_CONF_COUPLING:
512 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
513 break;
514 case SR_CONF_VDIV:
515 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
516 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
517 rational[0] = g_variant_new_uint64(vdivs[i][0]);
518 rational[1] = g_variant_new_uint64(vdivs[i][1]);
519 tuple = g_variant_new_tuple(rational, 2);
520 g_variant_builder_add_value(&gvb, tuple);
521 }
522 *data = g_variant_builder_end(&gvb);
523 break;
524 case SR_CONF_TIMEBASE:
525 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
526 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
527 rational[0] = g_variant_new_uint64(timebases[i][0]);
528 rational[1] = g_variant_new_uint64(timebases[i][1]);
529 tuple = g_variant_new_tuple(rational, 2);
530 g_variant_builder_add_value(&gvb, tuple);
531 }
532 *data = g_variant_builder_end(&gvb);
533 break;
534 case SR_CONF_TRIGGER_SOURCE:
535 if (!sdi || !sdi->priv)
536 /* Can't know this until we have the exact model. */
537 return SR_ERR_ARG;
538 devc = sdi->priv;
539 *data = g_variant_new_strv(trigger_sources,
540 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
541 break;
542 default:
543 return SR_ERR_ARG;
544 }
545
546 return SR_OK;
547}
548
549static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
550{
551 struct dev_context *devc;
552 struct sr_probe *probe;
553 GSList *l;
554 char cmd[256];
555
556 (void)cb_data;
557
558 devc = sdi->priv;
559
560 for (l = sdi->probes; l; l = l->next) {
561 probe = l->data;
562 sr_dbg("handling probe %s", probe->name);
563 if (probe->type == SR_PROBE_ANALOG) {
564 if (probe->enabled)
565 devc->enabled_analog_probes = g_slist_append(
566 devc->enabled_analog_probes, probe);
567 if (probe->enabled != devc->analog_channels[probe->index]) {
568 /* Enabled channel is currently disabled, or vice versa. */
569 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
570 probe->enabled ? "ON" : "OFF");
571 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
572 return SR_ERR;
573 }
574 } else if (probe->type == SR_PROBE_LOGIC) {
575 if (probe->enabled)
576 devc->enabled_digital_probes = g_slist_append(
577 devc->enabled_digital_probes, probe);
578 if (probe->enabled != devc->digital_channels[probe->index]) {
579 /* Enabled channel is currently disabled, or vice versa. */
580 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
581 probe->enabled ? "ON" : "OFF");
582 if (rigol_ds1xx2_send(devc, cmd) != SR_OK)
583 return SR_ERR;
584 }
585 }
586 }
587 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
588 return SR_ERR;
589
590 sr_source_add(devc->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
591
592 /* Send header packet to the session bus. */
593 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
594
595 /* Fetch the first frame. */
596 if (devc->enabled_analog_probes) {
597 devc->channel_frame = devc->enabled_analog_probes->data;
598 if (rigol_ds1xx2_send(devc, ":WAV:DATA? CHAN%d",
599 devc->channel_frame->index + 1) != SR_OK)
600 return SR_ERR;
601 } else {
602 devc->channel_frame = devc->enabled_digital_probes->data;
603 if (rigol_ds1xx2_send(devc, ":WAV:DATA? DIG") != SR_OK)
604 return SR_ERR;
605 }
606
607 devc->num_frame_bytes = 0;
608
609 return SR_OK;
610}
611
612static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
613{
614 struct dev_context *devc;
615
616 (void)cb_data;
617
618 devc = sdi->priv;
619
620 if (sdi->status != SR_ST_ACTIVE) {
621 sr_err("Device inactive, can't stop acquisition.");
622 return SR_ERR;
623 }
624
625 g_slist_free(devc->enabled_analog_probes);
626 g_slist_free(devc->enabled_digital_probes);
627 devc->enabled_analog_probes = NULL;
628 devc->enabled_digital_probes = NULL;
629 sr_source_remove(devc->fd);
630
631 return SR_OK;
632}
633
634SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
635 .name = "rigol-ds1xx2",
636 .longname = "Rigol DS1xx2",
637 .api_version = 1,
638 .init = hw_init,
639 .cleanup = hw_cleanup,
640 .scan = hw_scan,
641 .dev_list = hw_dev_list,
642 .dev_clear = clear_instances,
643 .config_get = config_get,
644 .config_set = config_set,
645 .config_list = config_list,
646 .dev_open = hw_dev_open,
647 .dev_close = hw_dev_close,
648 .dev_acquisition_start = dev_acquisition_start,
649 .dev_acquisition_stop = dev_acquisition_stop,
650 .priv = NULL,
651};