]> sigrok.org Git - libsigrok.git/blob - hardware/rigol-ds1xx2/api.c
rigol-ds1xx2: Accept SR_CONF_CONN.
[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                 if (!(devc = sdi->priv))
158                         continue;
159
160                 g_free(devc->device);
161                 g_free(devc->coupling[0]);
162                 g_free(devc->coupling[1]);
163                 g_free(devc->trigger_source);
164                 g_free(devc->trigger_slope);
165                 close(devc->fd);
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         struct dev_context *devc;
179         va_list args;
180         char buf[256];
181
182         devc = sdi->priv;
183
184         va_start(args, format);
185         vsnprintf(buf, 255, format, args);
186         va_end(args);
187         if (rigol_ds1xx2_send(devc, buf) != SR_OK)
188                 return SR_ERR;
189
190         /* When setting a bunch of parameters in a row, the DS1052E scrambles
191          * some of them unless there is at least 100ms delay in between. */
192         sr_spew("delay %dms", 100);
193         g_usleep(100000);
194
195         return SR_OK;
196 }
197
198 static int hw_init(struct sr_context *sr_ctx)
199 {
200         return std_hw_init(sr_ctx, di, DRIVER_LOG_DOMAIN);
201 }
202
203 static int probe_device(struct drv_context *drvc, const char *device)
204 {
205         const gchar *idn_query = "*IDN?";
206         unsigned int i;
207         int len, num_tokens, fd;
208         const gchar *delimiter = ",";
209         gchar **tokens;
210         const char *manufacturer, *model, *version;
211         gboolean matched = FALSE;
212         struct sr_dev_inst *sdi;
213         struct dev_context *devc;
214         gboolean has_digital = FALSE;
215         char buf[256];
216         gchar *channel_name;
217         struct sr_probe *probe;
218
219         fd = open(device, O_RDWR);
220         len = write(fd, idn_query, strlen(idn_query));
221         len = read(fd, buf, sizeof(buf));
222         close(fd);
223         if (len == 0)
224                 return SR_ERR_NA;
225
226         buf[len] = 0;
227         tokens = g_strsplit(buf, delimiter, 0);
228         close(fd);
229         sr_dbg("response: %s %d [%s]", device, len, buf);
230
231         for (num_tokens = 0; tokens[num_tokens] != NULL; num_tokens++);
232
233         if (num_tokens < 4) {
234                 g_strfreev(tokens);
235                 return SR_ERR_NA;
236         }
237
238         manufacturer = tokens[0];
239         model = tokens[1];
240         version = tokens[3];
241
242         if (strcmp(manufacturer, "Rigol Technologies")) {
243                 g_strfreev(tokens);
244                 return SR_ERR_NA;
245         }
246
247         for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
248                 if (!strcmp(model, supported_models[i])) {
249                         matched = 1;
250                         has_digital = g_str_has_suffix(model, "D");
251                         break;
252                 }
253         }
254
255         if (!matched || !(sdi = sr_dev_inst_new(0, SR_ST_ACTIVE,
256                 manufacturer, model, version))) {
257                 g_strfreev(tokens);
258                 return SR_ERR_NA;
259         }
260
261         g_strfreev(tokens);
262
263         if (!(devc = g_try_malloc0(sizeof(struct dev_context))))
264                 return SR_ERR_MALLOC;
265
266         devc->limit_frames = 0;
267         if (!(devc->device = g_strdup(device)))
268                 return SR_ERR_MALLOC;
269         devc->has_digital = has_digital;
270         sdi->priv = devc;
271         sdi->driver = di;
272         drvc->instances = g_slist_append(drvc->instances, sdi);
273
274         for (i = 0; i < 2; i++) {
275                 if (!(probe = sr_probe_new(i, SR_PROBE_ANALOG, TRUE,
276                                 i == 0 ? "CH1" : "CH2")))
277                         return SR_ERR_MALLOC;
278                 sdi->probes = g_slist_append(sdi->probes, probe);
279         }
280
281         if (devc->has_digital) {
282                 for (i = 0; i < 16; i++) {
283                         if (!(channel_name = g_strdup_printf("D%d", i)))
284                                 return SR_ERR_MALLOC;
285                         probe = sr_probe_new(i, SR_PROBE_LOGIC, TRUE, channel_name);
286                         g_free(channel_name);
287                         if (!probe)
288                                 return SR_ERR_MALLOC;
289                         sdi->probes = g_slist_append(sdi->probes, probe);
290                 }
291         }
292
293         return SR_OK;
294 }
295
296 static GSList *hw_scan(GSList *options)
297 {
298         struct drv_context *drvc;
299         GSList *l, *devices;
300         struct sr_config *src;
301         GDir *dir;
302         const gchar *dev_name;
303         const gchar *dev_dir = "/dev/";
304         const gchar *prefix = "usbtmc";
305         gchar *device = NULL;
306         int ret;
307
308         drvc = di->priv;
309         drvc->instances = NULL;
310
311         for (l = options; l; l = l->next) {
312                 src = l->data;
313                 if (src->key == SR_CONF_CONN) {
314                         device = g_variant_get_string(src->data, NULL);
315                         break;
316                 }
317         }
318
319         if (device) {
320                 ret = probe_device(drvc, device);
321                 if (ret == SR_ERR_MALLOC) {
322                         clear_instances();
323                         return NULL;
324                 }
325         } else {
326                 if (!(dir = g_dir_open("/sys/class/usb/", 0, NULL)))
327                         return NULL;
328                 while ((dev_name = g_dir_read_name(dir))) {
329                         if (strncmp(dev_name, prefix, strlen(prefix)))
330                                 continue;
331                         device = g_strconcat(dev_dir, dev_name, NULL);
332                         ret = probe_device(drvc, device);
333                         g_free(device);
334                         if (ret == SR_ERR_MALLOC) {
335                                 g_dir_close(dir);
336                                 clear_instances();
337                                 return NULL;
338                         }
339                 }
340
341                 g_dir_close(dir);
342         }
343
344         devices = g_slist_copy(drvc->instances);
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         struct dev_context *devc;
356         int fd;
357
358         devc = sdi->priv;
359
360         if ((fd = open(devc->device, O_RDWR)) == -1)
361                 return SR_ERR;
362         devc->fd = fd;
363
364         if (rigol_ds1xx2_get_dev_cfg(sdi) != SR_OK)
365                 /* TODO: force configuration? */
366                 return SR_ERR;
367
368         return SR_OK;
369 }
370
371 static int hw_dev_close(struct sr_dev_inst *sdi)
372 {
373         struct dev_context *devc;
374
375         devc = sdi->priv;
376
377         close(devc->fd);
378
379         return SR_OK;
380 }
381
382 static int hw_cleanup(void)
383 {
384         clear_instances();
385
386         return SR_OK;
387 }
388
389 static int config_get(int id, GVariant **data, const struct sr_dev_inst *sdi)
390 {
391
392         (void)sdi;
393
394         switch (id) {
395         case SR_CONF_NUM_TIMEBASE:
396                 *data = g_variant_new_int32(NUM_TIMEBASE);
397                 break;
398         case SR_CONF_NUM_VDIV:
399                 *data = g_variant_new_int32(NUM_VDIV);
400                 break;
401         default:
402                 return SR_ERR_NA;
403         }
404
405         return SR_OK;
406 }
407
408 static int config_set(int id, GVariant *data, const struct sr_dev_inst *sdi)
409 {
410         struct dev_context *devc;
411         uint64_t tmp_u64, p, q;
412         double t_dbl;
413         unsigned int i;
414         int ret;
415         const char *tmp_str;
416
417         devc = sdi->priv;
418
419         if (sdi->status != SR_ST_ACTIVE) {
420                 sr_err("Device inactive, can't set config options.");
421                 return SR_ERR;
422         }
423
424         ret = SR_OK;
425         switch (id) {
426         case SR_CONF_LIMIT_FRAMES:
427                 devc->limit_frames = g_variant_get_uint64(data);
428                 break;
429         case SR_CONF_TRIGGER_SLOPE:
430                 tmp_u64 = g_variant_get_uint64(data);
431                 if (tmp_u64 != 0 && tmp_u64 != 1)
432                         return SR_ERR;
433                 g_free(devc->trigger_slope);
434                 devc->trigger_slope = g_strdup(tmp_u64 ? "POS" : "NEG");
435                 ret = set_cfg(sdi, ":TRIG:EDGE:SLOP %s", devc->trigger_slope);
436                 break;
437         case SR_CONF_HORIZ_TRIGGERPOS:
438                 t_dbl = g_variant_get_double(data);
439                 if (t_dbl < 0.0 || t_dbl > 1.0)
440                         return SR_ERR;
441                 devc->horiz_triggerpos = t_dbl;
442                 /* We have the trigger offset as a percentage of the frame, but
443                  * need to express this in seconds. */
444                 t_dbl = -(devc->horiz_triggerpos - 0.5) * devc->timebase * NUM_TIMEBASE;
445                 ret = set_cfg(sdi, ":TIM:OFFS %.6f", t_dbl);
446                 break;
447         case SR_CONF_TIMEBASE:
448                 g_variant_get(data, "(tt)", &p, &q);
449                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
450                         if (timebases[i][0] == p && timebases[i][1] == q) {
451                                 devc->timebase = (float)p / q;
452                                 ret = set_cfg(sdi, ":TIM:SCAL %.9f", devc->timebase);
453                                 break;
454                         }
455                 }
456                 if (i == ARRAY_SIZE(timebases))
457                         ret = SR_ERR_ARG;
458                 break;
459         case SR_CONF_TRIGGER_SOURCE:
460                 tmp_str = g_variant_get_string(data, NULL);
461                 for (i = 0; i < ARRAY_SIZE(trigger_sources); i++) {
462                         if (!strcmp(trigger_sources[i], tmp_str)) {
463                                 g_free(devc->trigger_source);
464                                 devc->trigger_source = g_strdup(trigger_sources[i]);
465                                 if (!strcmp(devc->trigger_source, "AC Line"))
466                                         tmp_str = "ACL";
467                                 else if (!strcmp(devc->trigger_source, "CH1"))
468                                         tmp_str = "CHAN1";
469                                 else if (!strcmp(devc->trigger_source, "CH2"))
470                                         tmp_str = "CHAN2";
471                                 else
472                                         tmp_str = (char *)devc->trigger_source;
473                                 ret = set_cfg(sdi, ":TRIG:EDGE:SOUR %s", tmp_str);
474                                 break;
475                         }
476                 }
477                 if (i == ARRAY_SIZE(trigger_sources))
478                         ret = SR_ERR_ARG;
479                 break;
480         case SR_CONF_VDIV:
481                 g_variant_get(data, "(tt)", &p, &q);
482                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
483                         if (vdivs[i][0] != p || vdivs[i][1] != q)
484                                 continue;
485                         devc->vdiv[0] = devc->vdiv[1] = (float)p / q;
486                         set_cfg(sdi, ":CHAN1:SCAL %.3f", devc->vdiv[0]);
487                         ret = set_cfg(sdi, ":CHAN2:SCAL %.3f", devc->vdiv[1]);
488                         break;
489                 }
490                 if (i == ARRAY_SIZE(vdivs))
491                         ret = SR_ERR_ARG;
492                 break;
493         case SR_CONF_COUPLING:
494                 /* TODO: Not supporting coupling per channel yet. */
495                 tmp_str = g_variant_get_string(data, NULL);
496                 for (i = 0; i < ARRAY_SIZE(coupling); i++) {
497                         if (!strcmp(tmp_str, coupling[i])) {
498                                 g_free(devc->coupling[0]);
499                                 g_free(devc->coupling[1]);
500                                 devc->coupling[0] = g_strdup(coupling[i]);
501                                 devc->coupling[1] = g_strdup(coupling[i]);
502                                 set_cfg(sdi, ":CHAN1:COUP %s", devc->coupling[0]);
503                                 ret = set_cfg(sdi, ":CHAN2:COUP %s", devc->coupling[1]);
504                                 break;
505                         }
506                 }
507                 if (i == ARRAY_SIZE(coupling))
508                         ret = SR_ERR_ARG;
509                 break;
510         default:
511                 ret = SR_ERR_NA;
512                 break;
513         }
514
515         return ret;
516 }
517
518 static int config_list(int key, GVariant **data, const struct sr_dev_inst *sdi)
519 {
520         GVariant *tuple, *rational[2];
521         GVariantBuilder gvb;
522         unsigned int i;
523         struct dev_context *devc;
524
525         switch (key) {
526         case SR_CONF_SCAN_OPTIONS:
527                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
528                                 hwopts, ARRAY_SIZE(hwopts), sizeof(int32_t));
529                 break;
530         case SR_CONF_DEVICE_OPTIONS:
531                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_INT32,
532                                 hwcaps, ARRAY_SIZE(hwcaps), sizeof(int32_t));
533                 break;
534         case SR_CONF_COUPLING:
535                 *data = g_variant_new_strv(coupling, ARRAY_SIZE(coupling));
536                 break;
537         case SR_CONF_VDIV:
538                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
539                 for (i = 0; i < ARRAY_SIZE(vdivs); i++) {
540                         rational[0] = g_variant_new_uint64(vdivs[i][0]);
541                         rational[1] = g_variant_new_uint64(vdivs[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_TIMEBASE:
548                 g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
549                 for (i = 0; i < ARRAY_SIZE(timebases); i++) {
550                         rational[0] = g_variant_new_uint64(timebases[i][0]);
551                         rational[1] = g_variant_new_uint64(timebases[i][1]);
552                         tuple = g_variant_new_tuple(rational, 2);
553                         g_variant_builder_add_value(&gvb, tuple);
554                 }
555                 *data = g_variant_builder_end(&gvb);
556                 break;
557         case SR_CONF_TRIGGER_SOURCE:
558                 if (!sdi || !sdi->priv)
559                         /* Can't know this until we have the exact model. */
560                         return SR_ERR_ARG;
561                 devc = sdi->priv;
562                 *data = g_variant_new_strv(trigger_sources,
563                                 devc->has_digital ? ARRAY_SIZE(trigger_sources) : 4);
564                 break;
565         default:
566                 return SR_ERR_NA;
567         }
568
569         return SR_OK;
570 }
571
572 static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
573 {
574         struct dev_context *devc;
575         struct sr_probe *probe;
576         GSList *l;
577         char cmd[256];
578
579         (void)cb_data;
580
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(devc, 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(devc, 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(devc->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(devc, ":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(devc, ":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
639         (void)cb_data;
640
641         devc = sdi->priv;
642
643         if (sdi->status != SR_ST_ACTIVE) {
644                 sr_err("Device inactive, can't stop acquisition.");
645                 return SR_ERR;
646         }
647
648         g_slist_free(devc->enabled_analog_probes);
649         g_slist_free(devc->enabled_digital_probes);
650         devc->enabled_analog_probes = NULL;
651         devc->enabled_digital_probes = NULL;
652         sr_source_remove(devc->fd);
653
654         return SR_OK;
655 }
656
657 SR_PRIV struct sr_dev_driver rigol_ds1xx2_driver_info = {
658         .name = "rigol-ds1xx2",
659         .longname = "Rigol DS1xx2",
660         .api_version = 1,
661         .init = hw_init,
662         .cleanup = hw_cleanup,
663         .scan = hw_scan,
664         .dev_list = hw_dev_list,
665         .dev_clear = clear_instances,
666         .config_get = config_get,
667         .config_set = config_set,
668         .config_list = config_list,
669         .dev_open = hw_dev_open,
670         .dev_close = hw_dev_close,
671         .dev_acquisition_start = dev_acquisition_start,
672         .dev_acquisition_stop = dev_acquisition_stop,
673         .priv = NULL,
674 };