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