]> sigrok.org Git - libsigrok.git/blob - src/hardware/lecroy-xstream/api.c
sr_dev_open(): Set status to SR_ST_ACTIVE upon success.
[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_SAMPLERATE | SR_CONF_GET,
42         SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
43         SR_CONF_NUM_HDIV | SR_CONF_GET,
44         SR_CONF_HORIZ_TRIGGERPOS | SR_CONF_GET | SR_CONF_SET,
45         SR_CONF_TRIGGER_SOURCE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
46         SR_CONF_TRIGGER_SLOPE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
47 };
48
49 static const uint32_t analog_devopts[] = {
50         SR_CONF_NUM_VDIV | SR_CONF_GET,
51         SR_CONF_VDIV | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
52         SR_CONF_COUPLING | 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         sr_dev_inst_free(sdi);
108         g_free(devc);
109
110         return NULL;
111 }
112
113 static GSList *scan(struct sr_dev_driver *di, GSList *options)
114 {
115         return sr_scpi_scan(di->context, options, probe_serial_device);
116 }
117
118 static void clear_helper(void *priv)
119 {
120         struct dev_context *devc;
121
122         devc = priv;
123
124         lecroy_xstream_state_free(devc->model_state);
125
126         g_free(devc->analog_groups);
127
128         g_free(devc);
129 }
130
131 static int dev_clear(const struct sr_dev_driver *di)
132 {
133         return std_dev_clear(di, clear_helper);
134 }
135
136 static int dev_open(struct sr_dev_inst *sdi)
137 {
138         if (sr_scpi_open(sdi->conn) != SR_OK)
139                 return SR_ERR;
140
141         if (lecroy_xstream_state_get(sdi) != SR_OK)
142                 return SR_ERR;
143
144         return SR_OK;
145 }
146
147 static int dev_close(struct sr_dev_inst *sdi)
148 {
149         sr_scpi_close(sdi->conn);
150
151         sdi->status = SR_ST_INACTIVE;
152
153         return SR_OK;
154 }
155
156 static int config_get(uint32_t key, GVariant **data,
157         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
158 {
159         int ret;
160         unsigned int i;
161         struct dev_context *devc;
162         const struct scope_config *model;
163         struct scope_state *state;
164
165         if (!sdi)
166                 return SR_ERR_ARG;
167
168         devc = sdi->priv;
169
170         ret = SR_ERR_NA;
171         model = devc->model_config;
172         state = devc->model_state;
173         *data = NULL;
174
175         switch (key) {
176         case SR_CONF_NUM_HDIV:
177                 *data = g_variant_new_int32(model->num_xdivs);
178                 ret = SR_OK;
179                 break;
180         case SR_CONF_TIMEBASE:
181                 *data = g_variant_new("(tt)",
182                                 model->timebases[state->timebase].p,
183                                 model->timebases[state->timebase].q);
184                 ret = SR_OK;
185                 break;
186         case SR_CONF_NUM_VDIV:
187                 for (i = 0; i < model->analog_channels; i++) {
188                         if (cg != devc->analog_groups[i])
189                                 continue;
190                         *data = g_variant_new_int32(model->num_ydivs);
191                         ret = SR_OK;
192                 }
193                 break;
194         case SR_CONF_VDIV:
195                 for (i = 0; i < model->analog_channels; i++) {
196                         if (cg != devc->analog_groups[i])
197                                 continue;
198                         *data = g_variant_new("(tt)",
199                                 model->vdivs[state->analog_channels[i].vdiv].p,
200                                 model->vdivs[state->analog_channels[i].vdiv].q);
201                         ret = SR_OK;
202                 }
203                 break;
204         case SR_CONF_TRIGGER_SOURCE:
205                 *data = g_variant_new_string((*model->trigger_sources)[state->trigger_source]);
206                 ret = SR_OK;
207                 break;
208         case SR_CONF_TRIGGER_SLOPE:
209                 *data = g_variant_new_string((*model->trigger_slopes)[state->trigger_slope]);
210                 ret = SR_OK;
211                 break;
212         case SR_CONF_HORIZ_TRIGGERPOS:
213                 *data = g_variant_new_double(state->horiz_triggerpos);
214                 ret = SR_OK;
215                 break;
216         case SR_CONF_COUPLING:
217                 for (i = 0; i < model->analog_channels; i++) {
218                         if (cg != devc->analog_groups[i])
219                                 continue;
220                         *data = g_variant_new_string((*model->coupling_options)[state->analog_channels[i].coupling]);
221                         ret = SR_OK;
222                 }
223                 break;
224         case SR_CONF_SAMPLERATE:
225                 *data = g_variant_new_uint64(state->sample_rate);
226                 ret = SR_OK;
227                 break;
228         case SR_CONF_ENABLED:
229                 *data = g_variant_new_boolean(FALSE);
230                 ret = SR_OK;
231                 break;
232         default:
233                 ret = SR_ERR_NA;
234         }
235
236         return ret;
237 }
238
239 static GVariant *build_tuples(const struct sr_rational *array, unsigned int n)
240 {
241         unsigned int i;
242         GVariant *rational[2];
243         GVariantBuilder gvb;
244
245         g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
246
247         for (i = 0; i < n; i++) {
248                 rational[0] = g_variant_new_uint64(array[i].p);
249                 rational[1] = g_variant_new_uint64(array[i].q);
250
251                 /* FIXME: Valgrind reports a memory leak here. */
252                 g_variant_builder_add_value(&gvb, g_variant_new_tuple(rational, 2));
253         }
254
255         return g_variant_builder_end(&gvb);
256 }
257
258 static int config_set(uint32_t key, GVariant *data,
259         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
260 {
261         int ret;
262         unsigned int i, j;
263         char command[MAX_COMMAND_SIZE];
264         struct dev_context *devc;
265         const struct scope_config *model;
266         struct scope_state *state;
267         const char *tmp;
268         int64_t p;
269         uint64_t q;
270         double tmp_d;
271         gboolean update_sample_rate;
272
273         if (!sdi)
274                 return SR_ERR_ARG;
275
276         devc = sdi->priv;
277
278         model = devc->model_config;
279         state = devc->model_state;
280         update_sample_rate = FALSE;
281
282         ret = SR_ERR_NA;
283
284         switch (key) {
285         case SR_CONF_LIMIT_FRAMES:
286                 devc->frame_limit = g_variant_get_uint64(data);
287                 ret = SR_OK;
288                 break;
289         case SR_CONF_TRIGGER_SOURCE:
290                 tmp = g_variant_get_string(data, NULL);
291                 for (i = 0; (*model->trigger_sources)[i]; i++) {
292                         if (g_strcmp0(tmp, (*model->trigger_sources)[i]) != 0)
293                                 continue;
294                         state->trigger_source = i;
295                         g_snprintf(command, sizeof(command),
296                                         "SET TRIGGER SOURCE %s",
297                                         (*model->trigger_sources)[i]);
298
299                         ret = sr_scpi_send(sdi->conn, command);
300                         break;
301                 }
302                 break;
303         case SR_CONF_VDIV:
304                 g_variant_get(data, "(tt)", &p, &q);
305
306                 for (i = 0; i < model->num_vdivs; i++) {
307                         if (p != model->vdivs[i].p || q != model->vdivs[i].q)
308                                 continue;
309                         for (j = 1; j <= model->analog_channels; j++) {
310                                 if (cg != devc->analog_groups[j - 1])
311                                         continue;
312                                 state->analog_channels[j - 1].vdiv = i;
313                                 g_snprintf(command, sizeof(command),
314                                                 "C%d:VDIV %E", j, (float)p/q);
315
316                                 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
317                                     sr_scpi_get_opc(sdi->conn) != SR_OK)
318                                         return SR_ERR;
319
320                                 break;
321                         }
322
323                         ret = SR_OK;
324                         break;
325                 }
326                 break;
327         case SR_CONF_TIMEBASE:
328                 g_variant_get(data, "(tt)", &p, &q);
329
330                 for (i = 0; i < model->num_timebases; i++) {
331                         if (p != model->timebases[i].p ||
332                             q != model->timebases[i].q)
333                                 continue;
334                         state->timebase = i;
335                         g_snprintf(command, sizeof(command),
336                                         "TIME_DIV %E", (float)p/q);
337
338                         ret = sr_scpi_send(sdi->conn, command);
339                         update_sample_rate = TRUE;
340                         break;
341                 }
342                 break;
343         case SR_CONF_HORIZ_TRIGGERPOS:
344                 tmp_d = g_variant_get_double(data);
345
346                 if (tmp_d < 0.0 || tmp_d > 1.0)
347                         return SR_ERR;
348
349                 state->horiz_triggerpos = tmp_d;
350                 tmp_d = -(tmp_d - 0.5) *
351                         ((double)model->timebases[state->timebase].p /
352                          model->timebases[state->timebase].q)
353                          * model->num_xdivs;
354
355                 g_snprintf(command, sizeof(command), "TRIG POS %e S", tmp_d);
356
357                 ret = sr_scpi_send(sdi->conn, command);
358                 break;
359         case SR_CONF_TRIGGER_SLOPE:
360                 tmp = g_variant_get_string(data, NULL);
361                 for (i = 0; (*model->trigger_slopes)[i]; i++) {
362                         if (g_strcmp0(tmp, (*model->trigger_slopes)[i]) != 0)
363                                 continue;
364                         state->trigger_slope = i;
365                         g_snprintf(command, sizeof(command),
366                                         "SET TRIGGER SLOPE %s",
367                                         (*model->trigger_slopes)[i]);
368
369                         ret = sr_scpi_send(sdi->conn, command);
370                         break;
371                 }
372                 break;
373         case SR_CONF_COUPLING:
374                 tmp = g_variant_get_string(data, NULL);
375
376                 for (i = 0; (*model->coupling_options)[i]; i++) {
377                         if (strcmp(tmp, (*model->coupling_options)[i]) != 0)
378                                 continue;
379                         for (j = 1; j <= model->analog_channels; j++) {
380                                 if (cg != devc->analog_groups[j - 1])
381                                         continue;
382                                 state->analog_channels[j - 1].coupling = i;
383
384                                 g_snprintf(command, sizeof(command),
385                                                 "C%d:COUPLING %s", j, tmp);
386
387                                 if (sr_scpi_send(sdi->conn, command) != SR_OK ||
388                                     sr_scpi_get_opc(sdi->conn) != SR_OK)
389                                         return SR_ERR;
390                                 break;
391                         }
392
393                         ret = SR_OK;
394                         break;
395                 }
396                 break;
397         default:
398                 ret = SR_ERR_NA;
399                 break;
400         }
401
402         if (ret == SR_OK)
403                 ret = sr_scpi_get_opc(sdi->conn);
404
405         if (ret == SR_OK && update_sample_rate)
406                 ret = lecroy_xstream_update_sample_rate(sdi);
407
408         return ret;
409 }
410
411 static int config_list(uint32_t key, GVariant **data,
412         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
413 {
414         struct dev_context *devc = NULL;
415         const struct scope_config *model = NULL;
416
417         (void)cg;
418
419         /* SR_CONF_SCAN_OPTIONS is always valid, regardless of sdi or channel group. */
420         if (key == SR_CONF_SCAN_OPTIONS) {
421                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
422                                 scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t));
423                 return SR_OK;
424         }
425
426         /* If sdi is NULL, nothing except SR_CONF_DEVICE_OPTIONS can be provided. */
427         if (key == SR_CONF_DEVICE_OPTIONS && !sdi) {
428                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
429                                 drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t));
430                 return SR_OK;
431         }
432
433         /* Every other option requires a valid device instance. */
434         if (!sdi)
435                 return SR_ERR_ARG;
436
437         devc = sdi->priv;
438         model = devc->model_config;
439
440         switch (key) {
441         case SR_CONF_DEVICE_OPTIONS:
442                 if (!cg) {
443                         /* If cg is NULL, only the SR_CONF_DEVICE_OPTIONS that are not
444                          * specific to a channel group must be returned. */
445                         *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
446                                         devopts, ARRAY_SIZE(devopts), sizeof(uint32_t));
447                         return SR_OK;
448                 }
449                 *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32,
450                         analog_devopts, ARRAY_SIZE(analog_devopts),
451                         sizeof(uint32_t));
452                 break;
453         case SR_CONF_COUPLING:
454                 *data = g_variant_new_strv(*model->coupling_options,
455                            g_strv_length((char **)*model->coupling_options));
456                 break;
457         case SR_CONF_TRIGGER_SOURCE:
458                 if (!model)
459                         return SR_ERR_ARG;
460                 *data = g_variant_new_strv(*model->trigger_sources,
461                            g_strv_length((char **)*model->trigger_sources));
462                 break;
463         case SR_CONF_TRIGGER_SLOPE:
464                 if (!model)
465                         return SR_ERR_ARG;
466                 *data = g_variant_new_strv(*model->trigger_slopes,
467                            g_strv_length((char **)*model->trigger_slopes));
468                 break;
469         case SR_CONF_TIMEBASE:
470                 if (!model)
471                         return SR_ERR_ARG;
472                 *data = build_tuples(model->timebases, model->num_timebases);
473                 break;
474         case SR_CONF_VDIV:
475                 if (!model)
476                         return SR_ERR_ARG;
477                 *data = build_tuples(model->vdivs, model->num_vdivs);
478                 break;
479         default:
480                 return SR_ERR_NA;
481         }
482         return SR_OK;
483 }
484
485 SR_PRIV int lecroy_xstream_request_data(const struct sr_dev_inst *sdi)
486 {
487         char command[MAX_COMMAND_SIZE];
488         struct sr_channel *ch;
489         struct dev_context *devc;
490
491         devc = sdi->priv;
492
493         ch = devc->current_channel->data;
494
495         if (ch->type != SR_CHANNEL_ANALOG)
496                 return SR_ERR;
497
498         g_snprintf(command, sizeof(command),
499                 "COMM_FORMAT DEF9,WORD,BIN;C%d:WAVEFORM?", ch->index + 1);
500         return sr_scpi_send(sdi->conn, command);
501 }
502
503 static int setup_channels(const struct sr_dev_inst *sdi)
504 {
505         GSList *l;
506         gboolean setup_changed;
507         char command[MAX_COMMAND_SIZE];
508         struct scope_state *state;
509         struct sr_channel *ch;
510         struct dev_context *devc;
511         struct sr_scpi_dev_inst *scpi;
512
513         devc = sdi->priv;
514         scpi = sdi->conn;
515         state = devc->model_state;
516         setup_changed = FALSE;
517
518         for (l = sdi->channels; l; l = l->next) {
519                 ch = l->data;
520                 switch (ch->type) {
521                 case SR_CHANNEL_ANALOG:
522                         if (ch->enabled == state->analog_channels[ch->index].state)
523                                 break;
524                         g_snprintf(command, sizeof(command), "C%d:TRACE %s",
525                                    ch->index + 1, ch->enabled ? "ON" : "OFF");
526
527                         if (sr_scpi_send(scpi, command) != SR_OK)
528                                 return SR_ERR;
529                         state->analog_channels[ch->index].state = ch->enabled;
530                         setup_changed = TRUE;
531                         break;
532                 default:
533                         return SR_ERR;
534                 }
535         }
536
537         if (setup_changed && lecroy_xstream_update_sample_rate(sdi) != SR_OK)
538                 return SR_ERR;
539
540         return SR_OK;
541 }
542
543 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
544 {
545         GSList *l;
546         struct sr_channel *ch;
547         struct dev_context *devc;
548         int ret;
549         struct sr_scpi_dev_inst *scpi;
550
551         devc = sdi->priv;
552         scpi = sdi->conn;
553         /* Preset empty results. */
554         g_slist_free(devc->enabled_channels);
555         devc->enabled_channels = NULL;
556
557         /*
558          * Contruct the list of enabled channels. Determine the highest
559          * number of digital pods involved in the acquisition.
560          */
561
562         for (l = sdi->channels; l; l = l->next) {
563                 ch = l->data;
564                 if (!ch->enabled)
565                         continue;
566                 /* Only add a single digital channel per group (pod). */
567                 devc->enabled_channels = g_slist_append(
568                         devc->enabled_channels, ch);
569         }
570
571         if (!devc->enabled_channels)
572                 return SR_ERR;
573
574         /*
575          * Configure the analog channels and the
576          * corresponding digital pods.
577          */
578         if (setup_channels(sdi) != SR_OK) {
579                 sr_err("Failed to setup channel configuration!");
580                 ret = SR_ERR;
581                 goto free_enabled;
582         }
583
584         /*
585          * Start acquisition on the first enabled channel. The
586          * receive routine will continue driving the acquisition.
587          */
588         sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50,
589                         lecroy_xstream_receive_data, (void *)sdi);
590
591         std_session_send_df_header(sdi);
592
593         devc->current_channel = devc->enabled_channels;
594
595         return lecroy_xstream_request_data(sdi);
596
597 free_enabled:
598         g_slist_free(devc->enabled_channels);
599         devc->enabled_channels = NULL;
600
601         return ret;
602 }
603
604 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
605 {
606         struct dev_context *devc;
607         struct sr_scpi_dev_inst *scpi;
608
609         std_session_send_df_end(sdi);
610
611         devc = sdi->priv;
612
613         devc->num_frames = 0;
614         g_slist_free(devc->enabled_channels);
615         devc->enabled_channels = NULL;
616         scpi = sdi->conn;
617         sr_scpi_source_remove(sdi->session, scpi);
618
619         return SR_OK;
620 }
621
622 static struct sr_dev_driver lecroy_xstream_driver_info = {
623         .name = "lecroy-xstream",
624         .longname = "LeCroy X-Stream",
625         .api_version = 1,
626         .init = std_init,
627         .cleanup = std_cleanup,
628         .scan = scan,
629         .dev_list = std_dev_list,
630         .dev_clear = dev_clear,
631         .config_get = config_get,
632         .config_set = config_set,
633         .config_list = config_list,
634         .dev_open = dev_open,
635         .dev_close = dev_close,
636         .dev_acquisition_start = dev_acquisition_start,
637         .dev_acquisition_stop = dev_acquisition_stop,
638         .context = NULL,
639 };
640 SR_REGISTER_DEV_DRIVER(lecroy_xstream_driver_info);