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