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