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