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