]> sigrok.org Git - libsigrok.git/blob - src/hardware/lecroy-xstream/api.c
lecroy-xstream: Fix capabilities listing in config_list()
[libsigrok.git] / src / hardware / lecroy-xstream / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2017 Sven Schnelle <svens@stackframe.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include "scpi.h"
23 #include "protocol.h"
24
25 static struct sr_dev_driver lecroy_xstream_driver_info;
26
27 static const char *manufacturers[] = {
28         "LECROY",
29 };
30
31 static const uint32_t scanopts[] = {
32         SR_CONF_CONN,
33 };
34
35 static const uint32_t drvopts[] = {
36         SR_CONF_OSCILLOSCOPE,
37 };
38
39 static const uint32_t devopts[] = {
40         SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET,
41         SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
42         SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43         SR_CONF_NUM_HDIV | SR_CONF_GET,
44         SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
45         SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
46         SR_CONF_SAMPLERATE | SR_CONF_GET,
47 };
48
49 static const uint32_t analog_devopts[] = {
50         SR_CONF_NUM_VDIV | SR_CONF_GET,
51         SR_CONF_COUPLING | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
52         SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
53 };
54
55 static int check_manufacturer(const char *manufacturer)
56 {
57         unsigned int i;
58
59         for (i = 0; i < ARRAY_SIZE(manufacturers); i++)
60                 if (!strcmp(manufacturer, manufacturers[i]))
61                         return SR_OK;
62
63         return SR_ERR;
64 }
65
66 static struct sr_dev_inst *probe_serial_device(struct sr_scpi_dev_inst *scpi)
67 {
68         struct sr_dev_inst *sdi;
69         struct dev_context *devc;
70         struct sr_scpi_hw_info *hw_info;
71
72         sdi = NULL;
73         devc = NULL;
74         hw_info = NULL;
75
76         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
77                 sr_info("Couldn't get IDN response.");
78                 goto fail;
79         }
80
81         if (check_manufacturer(hw_info->manufacturer) != SR_OK)
82                 goto fail;
83
84         sdi = g_malloc0(sizeof(struct sr_dev_inst));
85         sdi->vendor = g_strdup(hw_info->manufacturer);
86         sdi->model = g_strdup(hw_info->model);
87         sdi->version = g_strdup(hw_info->firmware_version);
88         sdi->serial_num = g_strdup(hw_info->serial_number);
89         sdi->driver = &lecroy_xstream_driver_info;
90         sdi->inst_type = SR_INST_SCPI;
91         sdi->conn = scpi;
92
93         sr_scpi_hw_info_free(hw_info);
94         hw_info = NULL;
95
96         devc = g_malloc0(sizeof(struct dev_context));
97
98         sdi->priv = devc;
99
100         if (lecroy_xstream_init_device(sdi) != SR_OK)
101                 goto fail;
102
103         return sdi;
104
105 fail:
106         sr_scpi_hw_info_free(hw_info);
107         if (sdi)
108                 sr_dev_inst_free(sdi);
109         g_free(devc);
110
111         return NULL;
112 }
113
114 static GSList *scan(struct sr_dev_driver *di, GSList *options)
115 {
116         return sr_scpi_scan(di->context, options, probe_serial_device);
117 }
118
119 static void clear_helper(void *priv)
120 {
121         struct dev_context *devc;
122
123         devc = priv;
124
125         lecroy_xstream_state_free(devc->model_state);
126
127         g_free(devc->analog_groups);
128
129         g_free(devc);
130 }
131
132 static int dev_clear(const struct sr_dev_driver *di)
133 {
134         return std_dev_clear(di, clear_helper);
135 }
136
137 static int dev_open(struct sr_dev_inst *sdi)
138 {
139         if (sdi->status != SR_ST_ACTIVE && sr_scpi_open(sdi->conn) != SR_OK)
140                 return SR_ERR;
141
142         if (lecroy_xstream_state_get(sdi) != SR_OK)
143                 return SR_ERR;
144
145         sdi->status = SR_ST_ACTIVE;
146
147         return SR_OK;
148 }
149
150 static int dev_close(struct sr_dev_inst *sdi)
151 {
152         if (sdi->status == SR_ST_INACTIVE)
153                 return SR_OK;
154
155         sr_scpi_close(sdi->conn);
156
157         sdi->status = SR_ST_INACTIVE;
158
159         return SR_OK;
160 }
161
162 static int config_get(uint32_t key, GVariant **data,
163         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
164 {
165         int ret;
166         unsigned int i;
167         struct dev_context *devc;
168         const struct scope_config *model;
169         struct scope_state *state;
170
171         if (!sdi)
172                 return SR_ERR_ARG;
173
174         devc = sdi->priv;
175
176         ret = SR_ERR_NA;
177         model = devc->model_config;
178         state = devc->model_state;
179         *data = NULL;
180
181         switch (key) {
182         case SR_CONF_NUM_HDIV:
183                 *data = g_variant_new_int32(model->num_xdivs);
184                 ret = SR_OK;
185                 break;
186         case SR_CONF_TIMEBASE:
187                 *data = g_variant_new("(tt)",
188                                 model->timebases[state->timebase].p,
189                                 model->timebases[state->timebase].q);
190                 ret = SR_OK;
191                 break;
192         case SR_CONF_NUM_VDIV:
193                 for (i = 0; i < model->analog_channels; i++) {
194                         if (cg != devc->analog_groups[i])
195                                 continue;
196                         *data = g_variant_new_int32(model->num_ydivs);
197                         ret = SR_OK;
198                 }
199                 break;
200         case SR_CONF_VDIV:
201                 for (i = 0; i < model->analog_channels; i++) {
202                         if (cg != devc->analog_groups[i])
203                                 continue;
204                         *data = g_variant_new("(tt)",
205                                 model->vdivs[state->analog_channels[i].vdiv].p,
206                                 model->vdivs[state->analog_channels[i].vdiv].q);
207                         ret = SR_OK;
208                 }
209                 break;
210         case SR_CONF_TRIGGER_SOURCE:
211                 *data = g_variant_new_string((*model->trigger_sources)[state->trigger_source]);
212                 ret = SR_OK;
213                 break;
214         case SR_CONF_TRIGGER_SLOPE:
215                 *data = g_variant_new_string((*model->trigger_slopes)[state->trigger_slope]);
216                 ret = SR_OK;
217                 break;
218         case SR_CONF_HORIZ_TRIGGERPOS:
219                 *data = g_variant_new_double(state->horiz_triggerpos);
220                 ret = SR_OK;
221                 break;
222         case SR_CONF_COUPLING:
223                 for (i = 0; i < model->analog_channels; i++) {
224                         if (cg != devc->analog_groups[i])
225                                 continue;
226                         *data = g_variant_new_string((*model->coupling_options)[state->analog_channels[i].coupling]);
227                         ret = SR_OK;
228                 }
229                 break;
230         case SR_CONF_SAMPLERATE:
231                 *data = g_variant_new_uint64(state->sample_rate);
232                 ret = SR_OK;
233                 break;
234         case SR_CONF_ENABLED:
235                 *data = g_variant_new_boolean(FALSE);
236                 ret = SR_OK;
237                 break;
238         default:
239                 ret = SR_ERR_NA;
240         }
241
242         return ret;
243 }
244
245 static GVariant *build_tuples(const struct sr_rational *array, unsigned int n)
246 {
247         unsigned int i;
248         GVariant *rational[2];
249         GVariantBuilder gvb;
250
251         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
252
253         for (i = 0; i < n; i++) {
254                 rational[0] = g_variant_new_uint64(array[i].p);
255                 rational[1] = g_variant_new_uint64(array[i].q);
256
257                 /* FIXME: Valgrind reports a memory leak here. */
258                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
259         }
260
261         return g_variant_builder_end(&gvb);
262 }
263
264 static int config_set(uint32_t key, GVariant *data,
265         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
266 {
267         int ret;
268         unsigned int i, j;
269         char command[MAX_COMMAND_SIZE];
270         struct dev_context *devc;
271         const struct scope_config *model;
272         struct scope_state *state;
273         const char *tmp;
274         int64_t p;
275         uint64_t q;
276         double tmp_d;
277         gboolean update_sample_rate;
278
279         if (!sdi)
280                 return SR_ERR_ARG;
281
282         devc = sdi->priv;
283
284         model = devc->model_config;
285         state = devc->model_state;
286         update_sample_rate = FALSE;
287
288         ret = SR_ERR_NA;
289
290         switch (key) {
291         case SR_CONF_LIMIT_FRAMES:
292                 devc->frame_limit = g_variant_get_uint64(data);
293                 ret = SR_OK;
294                 break;
295         case SR_CONF_TRIGGER_SOURCE:
296                 tmp = g_variant_get_string(data, NULL);
297                 for (i = 0; (*model->trigger_sources)[i]; i++) {
298                         if (g_strcmp0(tmp, (*model->trigger_sources)[i]) != 0)
299                                 continue;
300                         state->trigger_source = i;
301                         g_snprintf(command, sizeof(command),
302                                         "SET TRIGGER SOURCE %s",
303                                         (*model->trigger_sources)[i]);
304
305                         ret = sr_scpi_send(sdi->conn, command);
306                         break;
307                 }
308                 break;
309         case SR_CONF_VDIV:
310                 g_variant_get(data, "(tt)", &p, &q);
311
312                 for (i = 0; i < model->num_vdivs; i++) {
313                         if (p != model->vdivs[i].p || q != model->vdivs[i].q)
314                                 continue;
315                         for (j = 1; j <= model->analog_channels; j++) {
316                                 if (cg != devc->analog_groups[j - 1])
317                                         continue;
318                                 state->analog_channels[j - 1].vdiv = i;
319                                 g_snprintf(command, sizeof(command),
320                                                 "C%d:VDIV %E", j, (float)p/q);
321
322                                 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
323                                     sr_scpi_get_opc(sdi->conn) != SR_OK)
324                                         return SR_ERR;
325
326                                 break;
327                         }
328
329                         ret = SR_OK;
330                         break;
331                 }
332                 break;
333         case SR_CONF_TIMEBASE:
334                 g_variant_get(data, "(tt)", &p, &q);
335
336                 for (i = 0; i < model->num_timebases; i++) {
337                         if (p != model->timebases[i].p ||
338                             q != model->timebases[i].q)
339                                 continue;
340                         state->timebase = i;
341                         g_snprintf(command, sizeof(command),
342                                         "TIME_DIV %E", (float)p/q);
343
344                         ret = sr_scpi_send(sdi->conn, command);
345                         update_sample_rate = TRUE;
346                         break;
347                 }
348                 break;
349         case SR_CONF_HORIZ_TRIGGERPOS:
350                 tmp_d = g_variant_get_double(data);
351
352                 if (tmp_d < 0.0 || tmp_d > 1.0)
353                         return SR_ERR;
354
355                 state->horiz_triggerpos = tmp_d;
356                 tmp_d = -(tmp_d - 0.5) *
357                         ((double)model->timebases[state->timebase].p /
358                          model->timebases[state->timebase].q)
359                          * model->num_xdivs;
360
361                 g_snprintf(command, sizeof(command), "TRIG POS %e S", tmp_d);
362
363                 ret = sr_scpi_send(sdi->conn, command);
364                 break;
365         case SR_CONF_TRIGGER_SLOPE:
366                 tmp = g_variant_get_string(data, NULL);
367                 for (i = 0; (*model->trigger_slopes)[i]; i++) {
368                         if (g_strcmp0(tmp, (*model->trigger_slopes)[i]) != 0)
369                                 continue;
370                         state->trigger_slope = i;
371                         g_snprintf(command, sizeof(command),
372                                         "SET TRIGGER SLOPE %s",
373                                         (*model->trigger_slopes)[i]);
374
375                         ret = sr_scpi_send(sdi->conn, command);
376                         break;
377                 }
378                 break;
379         case SR_CONF_COUPLING:
380                 tmp = g_variant_get_string(data, NULL);
381
382                 for (i = 0; (*model->coupling_options)[i]; i++) {
383                         if (strcmp(tmp, (*model->coupling_options)[i]) != 0)
384                                 continue;
385                         for (j = 1; j <= model->analog_channels; j++) {
386                                 if (cg != devc->analog_groups[j - 1])
387                                         continue;
388                                 state->analog_channels[j - 1].coupling = i;
389
390                                 g_snprintf(command, sizeof(command),
391                                                 "C%d:COUPLING %s", j, tmp);
392
393                                 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
394                                     sr_scpi_get_opc(sdi->conn) != SR_OK)
395                                         return SR_ERR;
396                                 break;
397                         }
398
399                         ret = SR_OK;
400                         break;
401                 }
402                 break;
403         default:
404                 ret = SR_ERR_NA;
405                 break;
406         }
407
408         if (ret == SR_OK)
409                 ret = sr_scpi_get_opc(sdi->conn);
410
411         if (ret == SR_OK && update_sample_rate)
412                 ret = lecroy_xstream_update_sample_rate(sdi);
413
414         return ret;
415 }
416
417 static int config_list(uint32_t key, GVariant **data,
418         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
419 {
420         struct dev_context *devc = NULL;
421         const struct scope_config *model = NULL;
422
423         (void)cg;
424
425         /* SR_CONF_SCAN_OPTIONS is always valid, regardless of sdi or channel group. */
426         if (key == SR_CONF_SCAN_OPTIONS) {
427                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
428                                 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
429                 return SR_OK;
430         }
431
432         /* If sdi is NULL, nothing except SR_CONF_DEVICE_OPTIONS can be provided. */
433         if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
434                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
435                                 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
436                 return SR_OK;
437         }
438
439         /* Every other option requires a valid device instance. */
440         if (!sdi)
441                 return SR_ERR_ARG;
442
443         devc = sdi->priv;
444         model = devc->model_config;
445
446         switch (key) {
447         case SR_CONF_DEVICE_OPTIONS:
448                 if (!cg) {
449                         /* If cg is NULL, only the SR_CONF_DEVICE_OPTIONS that are not
450                          * specific to a channel group must be returned. */
451                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
452                                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
453                         return SR_OK;
454                 }
455                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
456                         analog_devopts, ARRAY_SIZE(analog_devopts),
457                         sizeof(uint32_t));
458                 break;
459         case SR_CONF_COUPLING:
460                 *data = g_variant_new_strv(*model->coupling_options,
461                            g_strv_length((char **)*model->coupling_options));
462                 break;
463         case SR_CONF_TRIGGER_SOURCE:
464                 if (!model)
465                         return SR_ERR_ARG;
466                 *data = g_variant_new_strv(*model->trigger_sources,
467                            g_strv_length((char **)*model->trigger_sources));
468                 break;
469         case SR_CONF_TRIGGER_SLOPE:
470                 if (!model)
471                         return SR_ERR_ARG;
472                 *data = g_variant_new_strv(*model->trigger_slopes,
473                            g_strv_length((char **)*model->trigger_slopes));
474                 break;
475         case SR_CONF_TIMEBASE:
476                 if (!model)
477                         return SR_ERR_ARG;
478                 *data = build_tuples(model->timebases, model->num_timebases);
479                 break;
480         case SR_CONF_VDIV:
481                 if (!model)
482                         return SR_ERR_ARG;
483                 *data = build_tuples(model->vdivs, model->num_vdivs);
484                 break;
485         default:
486                 return SR_ERR_NA;
487         }
488         return SR_OK;
489 }
490
491 SR_PRIV int lecroy_xstream_request_data(const struct sr_dev_inst *sdi)
492 {
493         char command[MAX_COMMAND_SIZE];
494         struct sr_channel *ch;
495         struct dev_context *devc;
496
497         devc = sdi->priv;
498
499         ch = devc->current_channel->data;
500
501         if (ch->type != SR_CHANNEL_ANALOG)
502                 return SR_ERR;
503
504         g_snprintf(command, sizeof(command),
505                 "COMM_FORMAT DEF9,WORD,BIN;C%d:WAVEFORM?", ch->index + 1);
506         return sr_scpi_send(sdi->conn, command);
507 }
508
509 static int setup_channels(const struct sr_dev_inst *sdi)
510 {
511         GSList *l;
512         gboolean setup_changed;
513         char command[MAX_COMMAND_SIZE];
514         struct scope_state *state;
515         struct sr_channel *ch;
516         struct dev_context *devc;
517         struct sr_scpi_dev_inst *scpi;
518
519         devc = sdi->priv;
520         scpi = sdi->conn;
521         state = devc->model_state;
522         setup_changed = FALSE;
523
524         for (l = sdi->channels; l; l = l->next) {
525                 ch = l->data;
526                 switch (ch->type) {
527                 case SR_CHANNEL_ANALOG:
528                         if (ch->enabled == state->analog_channels[ch->index].state)
529                                 break;
530                         g_snprintf(command, sizeof(command), "C%d:TRACE %s",
531                                    ch->index + 1, ch->enabled ? "ON" : "OFF");
532
533                         if (sr_scpi_send(scpi, command) != SR_OK)
534                                 return SR_ERR;
535                         state->analog_channels[ch->index].state = ch->enabled;
536                         setup_changed = TRUE;
537                         break;
538                 default:
539                         return SR_ERR;
540                 }
541         }
542
543         if (setup_changed && lecroy_xstream_update_sample_rate(sdi) != SR_OK)
544                 return SR_ERR;
545
546         return SR_OK;
547 }
548
549 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
550 {
551         GSList *l;
552         struct sr_channel *ch;
553         struct dev_context *devc;
554         int ret;
555         struct sr_scpi_dev_inst *scpi;
556
557         if (sdi->status != SR_ST_ACTIVE)
558                 return SR_ERR_DEV_CLOSED;
559
560         devc = sdi->priv;
561         scpi = sdi->conn;
562         /* Preset empty results. */
563         g_slist_free(devc->enabled_channels);
564         devc->enabled_channels = NULL;
565
566         /*
567          * Contruct the list of enabled channels. Determine the highest
568          * number of digital pods involved in the acquisition.
569          */
570
571         for (l = sdi->channels; l; l = l->next) {
572                 ch = l->data;
573                 if (!ch->enabled)
574                         continue;
575                 /* Only add a single digital channel per group (pod). */
576                 devc->enabled_channels = g_slist_append(
577                         devc->enabled_channels, ch);
578         }
579
580         if (!devc->enabled_channels)
581                 return SR_ERR;
582
583         /*
584          * Configure the analog channels and the
585          * corresponding digital pods.
586          */
587         if (setup_channels(sdi) != SR_OK) {
588                 sr_err("Failed to setup channel configuration!");
589                 ret = SR_ERR;
590                 goto free_enabled;
591         }
592
593         /*
594          * Start acquisition on the first enabled channel. The
595          * receive routine will continue driving the acquisition.
596          */
597         sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
598                         lecroy_xstream_receive_data, (void *)sdi);
599
600         std_session_send_df_header(sdi);
601
602         devc->current_channel = devc->enabled_channels;
603
604         return lecroy_xstream_request_data(sdi);
605
606 free_enabled:
607         g_slist_free(devc->enabled_channels);
608         devc->enabled_channels = NULL;
609
610         return ret;
611 }
612
613 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
614 {
615         struct dev_context *devc;
616         struct sr_scpi_dev_inst *scpi;
617
618         std_session_send_df_end(sdi);
619
620         if (sdi->status != SR_ST_ACTIVE)
621                 return SR_ERR_DEV_CLOSED;
622
623         devc = sdi->priv;
624
625         devc->num_frames = 0;
626         g_slist_free(devc->enabled_channels);
627         devc->enabled_channels = NULL;
628         scpi = sdi->conn;
629         sr_scpi_source_remove(sdi->session, scpi);
630
631         return SR_OK;
632 }
633
634 static struct sr_dev_driver lecroy_xstream_driver_info = {
635         .name = "lecroy-xstream",
636         .longname = "LeCroy X-Stream",
637         .api_version = 1,
638         .init = std_init,
639         .cleanup = std_cleanup,
640         .scan = scan,
641         .dev_list = std_dev_list,
642         .dev_clear = dev_clear,
643         .config_get = config_get,
644         .config_set = config_set,
645         .config_list = config_list,
646         .dev_open = dev_open,
647         .dev_close = dev_close,
648         .dev_acquisition_start = dev_acquisition_start,
649         .dev_acquisition_stop = dev_acquisition_stop,
650         .context = NULL,
651 };
652 SR_REGISTER_DEV_DRIVER(lecroy_xstream_driver_info);