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