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