]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds1xx2/api.c
bffc6ab951d0958b05f8edd9936e2ba8ef49379c
[libsigrok.git] / hardware / rigol-ds1xx2 / api.c
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
33 static const int32_t hwopts[] = {
34         SR_CONF_CONN,
35 };
36
37 static 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
49 static 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
87 static 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
104 static 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
127 static const char *coupling[] = {
128         "AC",
129         "DC",
130         "GND",
131 };
132
133 static const char *supported_models[] = {
134         "DS1052E",
135         "DS1102E",
136         "DS1052D",
137         "DS1102D",
138 };
139
140 SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info;
141 static struct sr_dev_driver *di = &rigol_ds1xx2_driver_info;
142
143 /* Properly close and free all devices. */
144 static 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
176 static 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
195 static int hw_init(struct sr_context *sr_ctx)
196 {
197         return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
198 }
199
200 static 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
300 static 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
348 static GSList *hw_dev_list(void)
349 {
350         return ((struct drv_context *)(di->priv))->instances;
351 }
352
353 static 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
367 static 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
380 static int hw_cleanup(void)
381 {
382         clear_instances();
383
384         return SR_OK;
385 }
386
387 static 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
406 static 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
516 static 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
570 static 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
635 static 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
659 SR_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 };