]> sigrok.org Git - libsigrok.git/blame_incremental - hardware/rigol-ds1xx2/api.c
fx2lafw: Minor cleanup
[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 sr_err("Device inactive, can't set config options.");
419 return SR_ERR;
420 }
421
422 ret = SR_OK;
423 switch (id) {
424 case SR_CONF_LIMIT_FRAMES:
425 devc->limit_frames = g_variant_get_uint64(data);
426 break;
427 case SR_CONF_TRIGGER_SLOPE:
428 tmp_u64 = g_variant_get_uint64(data);
429 if (tmp_u64 != 0 && tmp_u64 != 1)
430 return SR_ERR;
431 g_free(devc->trigger_slope);
432 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
433 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
434 break;
435 case SR_CONF_HORIZ_TRIGGERPOS:
436 t_dbl = g_variant_get_double(data);
437 if (t_dbl < 0.0 || t_dbl > 1.0)
438 return SR_ERR;
439 devc->horiz_triggerpos = t_dbl;
440 /* We have the trigger offset as a percentage of the frame, but
441 * need to express this in seconds. */
442 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
443 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
444 break;
445 case SR_CONF_TIMEBASE:
446 g_variant_get(data, "(tt)", &p, &q);
447 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
448 if (timebases[i][0] == p && timebases[i][1] == q) {
449 devc->timebase = (float)p / q;
450 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
451 break;
452 }
453 }
454 if (i == ARRAY_SIZE(timebases))
455 ret = SR_ERR_ARG;
456 break;
457 case SR_CONF_TRIGGER_SOURCE:
458 tmp_str = g_variant_get_string(data, NULL);
459 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
460 if (!strcmp(trigger_sources[i], tmp_str)) {
461 g_free(devc->trigger_source);
462 devc->trigger_source = g_strdup(trigger_sources[i]);
463 if (!strcmp(devc->trigger_source, "AC Line"))
464 tmp_str = "ACL";
465 else if (!strcmp(devc->trigger_source, "CH1"))
466 tmp_str = "CHAN1";
467 else if (!strcmp(devc->trigger_source, "CH2"))
468 tmp_str = "CHAN2";
469 else
470 tmp_str = (char *)devc->trigger_source;
471 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
472 break;
473 }
474 }
475 if (i == ARRAY_SIZE(trigger_sources))
476 ret = SR_ERR_ARG;
477 break;
478 case SR_CONF_VDIV:
479 g_variant_get(data, "(tt)", &p, &q);
480 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
481 if (vdivs[i][0] != p || vdivs[i][1] != q)
482 continue;
483 devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
484 set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
485 ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
486 break;
487 }
488 if (i == ARRAY_SIZE(vdivs))
489 ret = SR_ERR_ARG;
490 break;
491 case SR_CONF_COUPLING:
492 /* TODO: Not supporting coupling per channel yet. */
493 tmp_str = g_variant_get_string(data, NULL);
494 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
495 if (!strcmp(tmp_str, coupling[i])) {
496 g_free(devc->coupling[0]);
497 g_free(devc->coupling[1]);
498 devc->coupling[0] = g_strdup(coupling[i]);
499 devc->coupling[1] = g_strdup(coupling[i]);
500 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
501 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
502 break;
503 }
504 }
505 if (i == ARRAY_SIZE(coupling))
506 ret = SR_ERR_ARG;
507 break;
508 default:
509 ret = SR_ERR_NA;
510 break;
511 }
512
513 return ret;
514}
515
516static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
517{
518 GVariant *tuple, *rational[2];
519 GVariantBuilder gvb;
520 unsigned int i;
521 struct dev_context *devc;
522
523 switch (key) {
524 case SR_CONF_SCAN_OPTIONS:
525 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
526 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
527 break;
528 case SR_CONF_DEVICE_OPTIONS:
529 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
530 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
531 break;
532 case SR_CONF_COUPLING:
533 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
534 break;
535 case SR_CONF_VDIV:
536 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
537 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
538 rational[0] = g_variant_new_uint64(vdivs[i][0]);
539 rational[1] = g_variant_new_uint64(vdivs[i][1]);
540 tuple = g_variant_new_tuple(rational, 2);
541 g_variant_builder_add_value(&gvb, tuple);
542 }
543 *data = g_variant_builder_end(&gvb);
544 break;
545 case SR_CONF_TIMEBASE:
546 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
547 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
548 rational[0] = g_variant_new_uint64(timebases[i][0]);
549 rational[1] = g_variant_new_uint64(timebases[i][1]);
550 tuple = g_variant_new_tuple(rational, 2);
551 g_variant_builder_add_value(&gvb, tuple);
552 }
553 *data = g_variant_builder_end(&gvb);
554 break;
555 case SR_CONF_TRIGGER_SOURCE:
556 if (!sdi || !sdi->priv)
557 /* Can't know this until we have the exact model. */
558 return SR_ERR_ARG;
559 devc = sdi->priv;
560 *data = g_variant_new_strv(trigger_sources,
561 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
562 break;
563 default:
564 return SR_ERR_NA;
565 }
566
567 return SR_OK;
568}
569
570static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
571{
572 struct sr_serial_dev_inst *serial;
573 struct dev_context *devc;
574 struct sr_probe *probe;
575 GSList *l;
576 char cmd[256];
577
578 (void)cb_data;
579
580 serial = sdi->conn;
581 devc = sdi->priv;
582
583 for (l = sdi->probes; l; l = l->next) {
584 probe = l->data;
585 sr_dbg("handling probe %s", probe->name);
586 if (probe->type == SR_PROBE_ANALOG) {
587 if (probe->enabled)
588 devc->enabled_analog_probes = g_slist_append(
589 devc->enabled_analog_probes, probe);
590 if (probe->enabled != devc->analog_channels[probe->index]) {
591 /* Enabled channel is currently disabled, or vice versa. */
592 sprintf(cmd, ":CHAN%d:DISP %s", probe->index + 1,
593 probe->enabled ? "ON" : "OFF");
594 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
595 return SR_ERR;
596 }
597 } else if (probe->type == SR_PROBE_LOGIC) {
598 if (probe->enabled)
599 devc->enabled_digital_probes = g_slist_append(
600 devc->enabled_digital_probes, probe);
601 if (probe->enabled != devc->digital_channels[probe->index]) {
602 /* Enabled channel is currently disabled, or vice versa. */
603 sprintf(cmd, ":DIG%d:TURN %s", probe->index,
604 probe->enabled ? "ON" : "OFF");
605 if (rigol_ds1xx2_send(sdi, cmd) != SR_OK)
606 return SR_ERR;
607 }
608 }
609 }
610 if (!devc->enabled_analog_probes && !devc->enabled_digital_probes)
611 return SR_ERR;
612
613 sr_source_add(serial->fd, G_IO_IN, 50, rigol_ds1xx2_receive, (void *)sdi);
614
615 /* Send header packet to the session bus. */
616 std_session_send_df_header(cb_data, DRIVER_LOG_DOMAIN);
617
618 /* Fetch the first frame. */
619 if (devc->enabled_analog_probes) {
620 devc->channel_frame = devc->enabled_analog_probes->data;
621 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? CHAN%d",
622 devc->channel_frame->index + 1) != SR_OK)
623 return SR_ERR;
624 } else {
625 devc->channel_frame = devc->enabled_digital_probes->data;
626 if (rigol_ds1xx2_send(sdi, ":WAV:DATA? DIG") != SR_OK)
627 return SR_ERR;
628 }
629
630 devc->num_frame_bytes = 0;
631
632 return SR_OK;
633}
634
635static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
636{
637 struct dev_context *devc;
638 struct sr_serial_dev_inst *serial;
639
640 (void)cb_data;
641
642 devc = sdi->priv;
643
644 if (sdi->status != SR_ST_ACTIVE) {
645 sr_err("Device inactive, can't stop acquisition.");
646 return SR_ERR;
647 }
648
649 g_slist_free(devc->enabled_analog_probes);
650 g_slist_free(devc->enabled_digital_probes);
651 devc->enabled_analog_probes = NULL;
652 devc->enabled_digital_probes = NULL;
653 serial = sdi->conn;
654 sr_source_remove(serial->fd);
655
656 return SR_OK;
657}
658
659SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
660 .name = "rigol-ds1xx2",
661 .longname = "Rigol DS1xx2",
662 .api_version = 1,
663 .init = hw_init,
664 .cleanup = hw_cleanup,
665 .scan = hw_scan,
666 .dev_list = hw_dev_list,
667 .dev_clear = clear_instances,
668 .config_get = config_get,
669 .config_set = config_set,
670 .config_list = config_list,
671 .dev_open = hw_dev_open,
672 .dev_close = hw_dev_close,
673 .dev_acquisition_start = dev_acquisition_start,
674 .dev_acquisition_stop = dev_acquisition_stop,
675 .priv = NULL,
676};