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