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