]> sigrok.org Git - libsigrok.git/blob - src/hardware/rigol-dg/api.c
43121aed57c02cf79685065075fb50fe5674ae9d
[libsigrok.git] / src / hardware / rigol-dg / api.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2020 Timo Kokkonen <tjko@iki.fi>
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 <string.h>
22 #include "scpi.h"
23 #include "protocol.h"
24
25 static struct sr_dev_driver rigol_dg_driver_info;
26
27 static const uint32_t scanopts[] = {
28         SR_CONF_CONN,
29 };
30
31 static const uint32_t drvopts[] = {
32         SR_CONF_SIGNAL_GENERATOR,
33 };
34
35 static const uint32_t dg1000z_devopts[] = {
36         SR_CONF_CONTINUOUS,
37         SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
38         SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
39 };
40
41 static const uint32_t dg1000z_devopts_cg[] = {
42         SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
43         SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
44         SR_CONF_OUTPUT_FREQUENCY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
45         SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
46         SR_CONF_OFFSET | SR_CONF_GET | SR_CONF_SET,
47         SR_CONF_PHASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
48         SR_CONF_DUTY_CYCLE | SR_CONF_GET | SR_CONF_SET,
49 };
50
51 static const double phase_min_max_step[] = { 0.0, 360.0, 0.001 };
52
53 #define WAVEFORM_DEFAULT WFO_FREQUENCY | WFO_AMPLITUDE | WFO_OFFSET | WFO_PHASE
54
55 static const struct waveform_spec dg810_waveforms[] = {
56         { "SIN",   WF_SINE,     1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
57         { "SQU",   WF_SQUARE,   1.0E-6,   5.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
58         { "RAMP",  WF_RAMP,     1.0E-6,   0.2E+6, 1.0E-6, WAVEFORM_DEFAULT },
59         { "PULSE", WF_PULSE,    1.0E-6,   5.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
60         { "USER",  WF_ARB,      1.0E-6,   5.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
61         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
62         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
63 };
64
65 static const struct channel_spec dg811_channels[] = {
66         { "CH1",  ARRAY_AND_SIZE(dg810_waveforms) },
67 };
68
69 static const struct channel_spec dg812_channels[] = {
70         { "CH1",  ARRAY_AND_SIZE(dg810_waveforms) },
71         { "CH2",  ARRAY_AND_SIZE(dg810_waveforms) },
72 };
73
74 static const struct waveform_spec dg820_waveforms[] = {
75         { "SIN",   WF_SINE,     1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
76         { "SQU",   WF_SQUARE,   1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
77         { "RAMP",  WF_RAMP,     1.0E-6,   0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
78         { "PULSE", WF_PULSE,    1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
79         { "USER",  WF_ARB,      1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
80         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
81         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
82 };
83
84 static const struct channel_spec dg821_channels[] = {
85         { "CH1",  ARRAY_AND_SIZE(dg820_waveforms) },
86 };
87
88 static const struct channel_spec dg822_channels[] = {
89         { "CH1",  ARRAY_AND_SIZE(dg820_waveforms) },
90         { "CH2",  ARRAY_AND_SIZE(dg820_waveforms) },
91 };
92
93 static const struct waveform_spec dg830_waveforms[] = {
94         { "SIN",   WF_SINE,     1.0E-6,  35.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
95         { "SQU",   WF_SQUARE,   1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
96         { "RAMP",  WF_RAMP,     1.0E-6,   1.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
97         { "PULSE", WF_PULSE,    1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
98         { "USER",  WF_ARB,      1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
99         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
100         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
101 };
102
103 static const struct channel_spec dg831_channels[] = {
104         { "CH1",  ARRAY_AND_SIZE(dg830_waveforms) },
105 };
106
107 static const struct channel_spec dg832_channels[] = {
108         { "CH1",  ARRAY_AND_SIZE(dg830_waveforms) },
109         { "CH2",  ARRAY_AND_SIZE(dg830_waveforms) },
110 };
111
112 static const struct waveform_spec dg952_waveforms[] = {
113         { "SIN",   WF_SINE,     1.0E-6,  50.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
114         { "SQU",   WF_SQUARE,   1.0E-6,  15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
115         { "RAMP",  WF_RAMP,     1.0E-6,   1.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
116         { "PULSE", WF_PULSE,    1.0E-6,  15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
117         { "USER",  WF_ARB,      1.0E-6,  15.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
118         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
119         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
120 };
121
122 static const struct channel_spec dg952_channels[] = {
123         { "CH1",  ARRAY_AND_SIZE(dg952_waveforms) },
124         { "CH2",  ARRAY_AND_SIZE(dg952_waveforms) },
125 };
126
127 static const struct waveform_spec dg972_waveforms[] = {
128         { "SIN",   WF_SINE,     1.0E-6,  70.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
129         { "SQU",   WF_SQUARE,   1.0E-6,  20.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
130         { "RAMP",  WF_RAMP,     1.0E-6,   1.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
131         { "PULSE", WF_PULSE,    1.0E-6,  20.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
132         { "USER",  WF_ARB,      1.0E-6,  20.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
133         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
134         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
135 };
136
137 static const struct channel_spec dg972_channels[] = {
138         { "CH1",  ARRAY_AND_SIZE(dg972_waveforms) },
139         { "CH2",  ARRAY_AND_SIZE(dg972_waveforms) },
140 };
141
142 static const struct waveform_spec dg992_waveforms[] = {
143         { "SIN",   WF_SINE,     1.0E-6, 100.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
144         { "SQU",   WF_SQUARE,   1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
145         { "RAMP",  WF_RAMP,     1.0E-6,   2.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
146         { "PULSE", WF_PULSE,    1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
147         { "USER",  WF_ARB,      1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
148         { "NOISE", WF_NOISE,  100.0E+6, 100.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
149         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
150 };
151
152 static const struct channel_spec dg992_channels[] = {
153         { "CH1",  ARRAY_AND_SIZE(dg992_waveforms) },
154         { "CH2",  ARRAY_AND_SIZE(dg992_waveforms) },
155 };
156
157 static const struct waveform_spec dg1022z_waveforms[] = {
158         { "SIN",   WF_SINE,     1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
159         { "SQU",   WF_SQUARE,   1.0E-6,  25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
160         { "RAMP",  WF_RAMP,     1.0E-6,   0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
161         { "PULSE", WF_PULSE,    1.0E-6,  15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
162         { "USER",  WF_ARB,      1.0E-6,  10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
163         { "NOISE", WF_NOISE,   25.0E+6,  25.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
164         { "DC",    WF_DC,       0.0E-0,   0.0E+0, 0.0E-0, WFO_OFFSET },
165 };
166
167 static const struct channel_spec dg1022z_channels[] = {
168         { "CH1",  ARRAY_AND_SIZE(dg1022z_waveforms) },
169         { "CH2",  ARRAY_AND_SIZE(dg1022z_waveforms) },
170 };
171
172 static const struct waveform_spec dg1032z_waveforms[] = {
173         { "SIN",   WF_SINE,     1.0E-6, 30.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
174         { "SQU",   WF_SQUARE,   1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
175         { "RAMP",  WF_RAMP,     1.0E-6,  0.5E+6, 1.0E-6, WAVEFORM_DEFAULT },
176         { "PULSE", WF_PULSE,    1.0E-6, 15.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
177         { "USER",  WF_ARB,      1.0E-6, 10.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
178         { "NOISE", WF_NOISE,   30.0E+6, 30.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
179         { "DC",    WF_DC,       0.0E-0 , 0.0E+0, 0.0E-0, WFO_OFFSET },
180 };
181
182 static const struct channel_spec dg1032z_channels[] = {
183         { "CH1",  ARRAY_AND_SIZE(dg1032z_waveforms) },
184         { "CH2",  ARRAY_AND_SIZE(dg1032z_waveforms) },
185 };
186
187 static const struct waveform_spec dg1062z_waveforms[] = {
188         { "SIN",   WF_SINE,     1.0E-6, 60.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
189         { "SQU",   WF_SQUARE,   1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
190         { "RAMP",  WF_RAMP,     1.0E-6,  1.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
191         { "PULSE", WF_PULSE,    1.0E-6, 25.0E+6, 1.0E-6, WAVEFORM_DEFAULT | WFO_DUTY_CYCLE },
192         { "USER",  WF_ARB,      1.0E-6, 20.0E+6, 1.0E-6, WAVEFORM_DEFAULT },
193         { "NOISE", WF_NOISE,   60.0E+6, 60.0E+6, 0.0E-0, WFO_AMPLITUDE | WFO_OFFSET },
194         { "DC",    WF_DC,       0.0E-0,  0.0E+0, 0.0E-0, WFO_OFFSET },
195 };
196
197 static const struct channel_spec dg1062z_channels[] = {
198         { "CH1",  ARRAY_AND_SIZE(dg1062z_waveforms) },
199         { "CH2",  ARRAY_AND_SIZE(dg1062z_waveforms) },
200 };
201
202 static const struct scpi_command cmdset_dg1000z[] = {
203         { PSG_CMD_SETUP_LOCAL, "SYST:KLOC:STATE OFF", },
204 /*      { PSG_CMD_SELECT_CHANNEL, "SYST:CHAN:CUR CH%s", }, */
205         { PSG_CMD_GET_CHANNEL, "SYST:CHAN:CUR?", },
206         { PSG_CMD_GET_ENABLED, "OUTP%s:STATE?", },
207         { PSG_CMD_SET_ENABLE, "OUTP%s:STATE ON", },
208         { PSG_CMD_SET_DISABLE, "OUTP%s:STATE OFF", },
209         { PSG_CMD_GET_SOURCE, "SOUR%s:APPL?", },
210         { PSG_CMD_SET_SOURCE, "SOUR%s:APPL:%s", },
211         { PSG_CMD_GET_FREQUENCY, "SOUR%s:FREQ?", },
212         { PSG_CMD_SET_FREQUENCY, "SOUR%s:FREQ %f", },
213         { PSG_CMD_GET_AMPLITUDE, "SOUR%s:VOLT?", },
214         { PSG_CMD_SET_AMPLITUDE, "SOUR%s:VOLT %f", },
215         { PSG_CMD_GET_OFFSET, "SOUR%s:VOLT:OFFS?", },
216         { PSG_CMD_SET_OFFSET, "SOUR%s:VOLT:OFFS %f", },
217         { PSG_CMD_GET_PHASE, "SOUR%s:PHAS?", },
218         { PSG_CMD_SET_PHASE, "SOUR%s:PHAS %f", },
219         { PSG_CMD_GET_DCYCL_PULSE, "SOUR%s:FUNC:PULS:DCYC?", },
220         { PSG_CMD_SET_DCYCL_PULSE, "SOUR%s:FUNC:PULS:DCYC %f", },
221         { PSG_CMD_GET_DCYCL_SQUARE, "SOUR%s:FUNC:SQU:DCYC?", },
222         { PSG_CMD_SET_DCYCL_SQUARE, "SOUR%s:FUNC:SQU:DCYC %f", },
223         { PSG_CMD_COUNTER_GET_ENABLED, "COUN:STAT?", },
224         { PSG_CMD_COUNTER_SET_ENABLE, "COUN:STAT ON", },
225         { PSG_CMD_COUNTER_SET_DISABLE, "COUN:STAT OFF", },
226         { PSG_CMD_COUNTER_MEASURE, "COUN:MEAS?", },
227         ALL_ZERO
228 };
229
230 static const struct device_spec device_models[] = {
231         { "Rigol Technologies", "DG811",
232                 ARRAY_AND_SIZE(dg1000z_devopts),
233                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
234                 ARRAY_AND_SIZE(dg811_channels),
235                 cmdset_dg1000z,
236         },
237         { "Rigol Technologies", "DG812",
238                 ARRAY_AND_SIZE(dg1000z_devopts),
239                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
240                 ARRAY_AND_SIZE(dg812_channels),
241                 cmdset_dg1000z,
242         },
243         { "Rigol Technologies", "DG821",
244                 ARRAY_AND_SIZE(dg1000z_devopts),
245                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
246                 ARRAY_AND_SIZE(dg821_channels),
247                 cmdset_dg1000z,
248         },
249         { "Rigol Technologies", "DG822",
250                 ARRAY_AND_SIZE(dg1000z_devopts),
251                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
252                 ARRAY_AND_SIZE(dg822_channels),
253                 cmdset_dg1000z,
254         },
255         { "Rigol Technologies", "DG831",
256                 ARRAY_AND_SIZE(dg1000z_devopts),
257                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
258                 ARRAY_AND_SIZE(dg831_channels),
259                 cmdset_dg1000z,
260         },
261         { "Rigol Technologies", "DG832",
262                 ARRAY_AND_SIZE(dg1000z_devopts),
263                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
264                 ARRAY_AND_SIZE(dg832_channels),
265                 cmdset_dg1000z,
266         },
267         { "Rigol Technologies", "DG952",
268                 ARRAY_AND_SIZE(dg1000z_devopts),
269                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
270                 ARRAY_AND_SIZE(dg952_channels),
271                 cmdset_dg1000z,
272         },
273         { "Rigol Technologies", "DG972",
274                 ARRAY_AND_SIZE(dg1000z_devopts),
275                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
276                 ARRAY_AND_SIZE(dg972_channels),
277                 cmdset_dg1000z,
278         },
279         { "Rigol Technologies", "DG992",
280                 ARRAY_AND_SIZE(dg1000z_devopts),
281                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
282                 ARRAY_AND_SIZE(dg992_channels),
283                 cmdset_dg1000z,
284         },
285         { "Rigol Technologies", "DG1022Z",
286                 ARRAY_AND_SIZE(dg1000z_devopts),
287                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
288                 ARRAY_AND_SIZE(dg1022z_channels),
289                 cmdset_dg1000z,
290         },
291         { "Rigol Technologies", "DG1032Z",
292                 ARRAY_AND_SIZE(dg1000z_devopts),
293                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
294                 ARRAY_AND_SIZE(dg1032z_channels),
295                 cmdset_dg1000z,
296         },
297         { "Rigol Technologies", "DG1062Z",
298                 ARRAY_AND_SIZE(dg1000z_devopts),
299                 ARRAY_AND_SIZE(dg1000z_devopts_cg),
300                 ARRAY_AND_SIZE(dg1062z_channels),
301                 cmdset_dg1000z,
302         },
303 };
304
305 static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
306 {
307         struct sr_dev_inst *sdi;
308         struct dev_context *devc;
309         struct sr_scpi_hw_info *hw_info;
310         const struct device_spec *device;
311         const struct scpi_command *cmdset;
312         struct sr_channel *ch;
313         struct sr_channel_group *cg;
314         const char *command;
315         unsigned int i, ch_idx;
316         char tmp[16];
317
318         sdi = NULL;
319         devc = NULL;
320         hw_info = NULL;
321
322         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK)
323                 goto error;
324
325         device = NULL;
326         for (i = 0; i < ARRAY_SIZE(device_models); i++) {
327                 if (g_ascii_strcasecmp(hw_info->manufacturer,
328                                 device_models[i].vendor) != 0)
329                         continue;
330                 if (g_ascii_strcasecmp(hw_info->model,
331                                 device_models[i].model) != 0)
332                         continue;
333                 device = &device_models[i];
334                 cmdset = device_models[i].cmdset;
335                 break;
336         }
337         if (!device)
338                 goto error;
339
340         sdi = g_malloc0(sizeof(*sdi));
341         sdi->vendor = g_strdup(hw_info->manufacturer);
342         sdi->model = g_strdup(hw_info->model);
343         sdi->version = g_strdup(hw_info->firmware_version);
344         sdi->serial_num = g_strdup(hw_info->serial_number);
345         sdi->conn = scpi;
346         sdi->driver = &rigol_dg_driver_info;
347         sdi->inst_type = SR_INST_SCPI;
348
349         devc = g_malloc0(sizeof(*devc));
350         devc->cmdset = cmdset;
351         devc->device = device;
352         devc->ch_status = g_malloc0((device->num_channels + 1) *
353                         sizeof(devc->ch_status[0]));
354         sr_sw_limits_init(&devc->limits);
355         sdi->priv = devc;
356
357         /* Create channel group and channel for each device channel. */
358         ch_idx = 0;
359         for (i = 0; i < device->num_channels; i++) {
360                 ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE,
361                                 device->channels[i].name);
362                 cg = g_malloc0(sizeof(*cg));
363                 snprintf(tmp, sizeof(tmp), "%u", i + 1);
364                 cg->name = g_strdup(tmp);
365                 cg->channels = g_slist_append(cg->channels, ch);
366
367                 sdi->channel_groups = g_slist_append(sdi->channel_groups, cg);
368         }
369
370         /* Create channels for the frequency counter output. */
371         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "FREQ1");
372         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "PERIOD1");
373         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "DUTY1");
374         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "WIDTH1");
375
376         /* Put device back to "local" mode, in case only a scan was done... */
377         command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_SETUP_LOCAL);
378         if (command && *command) {
379                 sr_scpi_get_opc(scpi);
380                 sr_scpi_send(scpi, command);
381         }
382
383         sr_scpi_hw_info_free(hw_info);
384
385         return sdi;
386
387 error:
388         sr_scpi_hw_info_free(hw_info);
389         g_free(devc);
390         sr_dev_inst_free(sdi);
391
392         return NULL;
393 }
394
395 static GSList *scan(struct sr_dev_driver *di, GSList *options)
396 {
397         return sr_scpi_scan(di->context, options, probe_device);
398 }
399
400 static int dev_open(struct sr_dev_inst *sdi)
401 {
402         return sr_scpi_open(sdi->conn);
403 }
404
405 static int dev_close(struct sr_dev_inst *sdi)
406 {
407         struct dev_context *devc;
408         struct sr_scpi_dev_inst *scpi;
409         const char *command;
410
411         devc = sdi->priv;
412         scpi = sdi->conn;
413         if (!scpi)
414                 return SR_ERR_BUG;
415
416         /* Put unit back to "local" mode. */
417         command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_SETUP_LOCAL);
418         if (command && *command) {
419                 sr_scpi_get_opc(scpi);
420                 sr_scpi_send(scpi, command);
421         }
422
423         return sr_scpi_close(sdi->conn);
424 }
425
426 static int config_get(uint32_t key, GVariant **data,
427         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
428 {
429         struct dev_context *devc;
430         struct sr_scpi_dev_inst *scpi;
431         struct sr_channel *ch;
432         struct channel_status *ch_status;
433         const struct sr_key_info *kinfo;
434         uint32_t cmd;
435         int ret;
436
437         if (!sdi || !data)
438                 return SR_ERR_ARG;
439
440         devc = sdi->priv;
441         scpi = sdi->conn;
442         ret = SR_OK;
443         kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
444
445         if (!cg) {
446                 switch (key) {
447                 case SR_CONF_LIMIT_SAMPLES:
448                 case SR_CONF_LIMIT_MSEC:
449                         ret = sr_sw_limits_config_get(&devc->limits, key, data);
450                         break;
451                 default:
452                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
453                                 (int)key, (kinfo ? kinfo->name : "unknown"));
454                         ret = SR_ERR_NA;
455                         break;
456                 }
457         } else {
458                 ch = cg->channels->data;
459                 ch_status = &devc->ch_status[ch->index];
460
461                 switch (key) {
462                 case SR_CONF_ENABLED:
463                         sr_scpi_get_opc(scpi);
464                         ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
465                                 PSG_CMD_SELECT_CHANNEL, cg->name, data,
466                                 G_VARIANT_TYPE_BOOLEAN, PSG_CMD_GET_ENABLED,
467                                 cg->name);
468                         break;
469                 case SR_CONF_PATTERN_MODE:
470                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK) {
471                                 *data = g_variant_new_string(
472                                          rigol_dg_waveform_to_string(
473                                                  ch_status->wf));
474                         }
475                         break;
476                 case SR_CONF_OUTPUT_FREQUENCY:
477                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
478                                 *data = g_variant_new_double(ch_status->freq);
479                         break;
480                 case SR_CONF_AMPLITUDE:
481                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
482                                 *data = g_variant_new_double(ch_status->ampl);
483                         break;
484                 case SR_CONF_OFFSET:
485                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
486                                 *data = g_variant_new_double(ch_status->offset);
487                         break;
488                 case SR_CONF_PHASE:
489                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
490                                 *data = g_variant_new_double(ch_status->phase);
491                         break;
492                 case SR_CONF_DUTY_CYCLE:
493                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
494                                 break;
495                         if (ch_status->wf == WF_SQUARE) {
496                                 cmd = PSG_CMD_GET_DCYCL_SQUARE;
497                         } else if (ch_status->wf == WF_PULSE) {
498                                 cmd = PSG_CMD_GET_DCYCL_PULSE;
499                         } else {
500                                 ret = SR_ERR_NA;
501                                 break;
502                         }
503                         sr_scpi_get_opc(scpi);
504                         ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
505                                 PSG_CMD_SELECT_CHANNEL, cg->name, data,
506                                 G_VARIANT_TYPE_DOUBLE, cmd, cg->name);
507                         break;
508                 default:
509                         sr_dbg("%s: Unsupported (cg) key: %d (%s)", __func__,
510                                 (int)key, (kinfo ? kinfo->name : "unknown"));
511                         ret = SR_ERR_NA;
512                         break;
513                 }
514         }
515
516         return ret;
517 }
518
519 static int config_set(uint32_t key, GVariant *data,
520         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
521 {
522         struct dev_context *devc;
523         struct sr_scpi_dev_inst *scpi;
524         struct sr_channel *ch;
525         const struct channel_spec *ch_spec;
526         struct channel_status *ch_status;
527         const struct sr_key_info *kinfo;
528         int ret;
529         uint32_t cmd;
530         const char *mode, *mode_name, *new_mode;
531         unsigned int i;
532
533         if (!data || !sdi)
534                 return SR_ERR_ARG;
535
536         devc = sdi->priv;
537         scpi = sdi->conn;
538         kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
539
540         ret = SR_OK;
541
542         if (!cg) {
543                 switch (key) {
544                 case SR_CONF_LIMIT_MSEC:
545                 case SR_CONF_LIMIT_SAMPLES:
546                         ret = sr_sw_limits_config_set(&devc->limits, key, data);
547                         break;
548                 default:
549                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
550                                 (int)key, (kinfo ? kinfo->name : "unknown"));
551                         ret = SR_ERR_NA;
552                         break;
553                 }
554         } else {
555                 ch = cg->channels->data;
556                 ch_spec = &devc->device->channels[ch->index];
557                 ch_status = &devc->ch_status[ch->index];
558
559                 if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
560                         return ret;
561                 sr_scpi_get_opc(scpi);
562
563                 switch (key) {
564                 case SR_CONF_ENABLED:
565                         if (g_variant_get_boolean(data))
566                                 cmd = PSG_CMD_SET_ENABLE;
567                         else
568                                 cmd = PSG_CMD_SET_DISABLE;
569                         ret = sr_scpi_cmd(sdi, devc->cmdset,
570                                 PSG_CMD_SELECT_CHANNEL, cg->name, cmd, cg->name);
571                         break;
572                 case SR_CONF_PATTERN_MODE:
573                         ret = SR_ERR_NA;
574                         new_mode = NULL;
575                         mode = g_variant_get_string(data, NULL);
576                         for (i = 0; i < ch_spec->num_waveforms; i++) {
577                                 mode_name = rigol_dg_waveform_to_string(
578                                                 ch_spec->waveforms[i].waveform);
579                                 if (g_ascii_strncasecmp(mode, mode_name,
580                                                 strlen(mode_name)) == 0)
581                                         new_mode = ch_spec->waveforms[i].name;
582                         }
583                         if (new_mode)
584                                 ret = sr_scpi_cmd(sdi, devc->cmdset,
585                                         PSG_CMD_SELECT_CHANNEL, cg->name,
586                                         PSG_CMD_SET_SOURCE, cg->name, new_mode);
587                         break;
588                 case SR_CONF_OUTPUT_FREQUENCY:
589                         ret = SR_ERR_NA;
590                         if (!(ch_status->wf_spec->opts & WFO_FREQUENCY))
591                                 break;
592                         ret = sr_scpi_cmd(sdi, devc->cmdset,
593                                 PSG_CMD_SELECT_CHANNEL, cg->name,
594                                 PSG_CMD_SET_FREQUENCY, cg->name,
595                                 g_variant_get_double(data));
596                         break;
597                 case SR_CONF_AMPLITUDE:
598                         ret = SR_ERR_NA;
599                         if (!(ch_status->wf_spec->opts & WFO_AMPLITUDE))
600                                 break;
601                         ret = sr_scpi_cmd(sdi, devc->cmdset,
602                                 PSG_CMD_SELECT_CHANNEL, cg->name,
603                                 PSG_CMD_SET_AMPLITUDE, cg->name,
604                                 g_variant_get_double(data));
605                         break;
606                 case SR_CONF_OFFSET:
607                         ret = SR_ERR_NA;
608                         if (!(ch_status->wf_spec->opts & WFO_OFFSET))
609                                 break;
610                         ret = sr_scpi_cmd(sdi, devc->cmdset,
611                                 PSG_CMD_SELECT_CHANNEL, cg->name,
612                                 PSG_CMD_SET_OFFSET, cg->name,
613                                 g_variant_get_double(data));
614                         break;
615                 case SR_CONF_PHASE:
616                         ret = SR_ERR_NA;
617                         if (!(ch_status->wf_spec->opts & WFO_PHASE))
618                                 break;
619                         ret = sr_scpi_cmd(sdi, devc->cmdset,
620                                 PSG_CMD_SELECT_CHANNEL, cg->name,
621                                 PSG_CMD_SET_PHASE, cg->name,
622                                 g_variant_get_double(data));
623                         break;
624                 case SR_CONF_DUTY_CYCLE:
625                         ret = SR_ERR_NA;
626                         if (!(ch_status->wf_spec->opts & WFO_DUTY_CYCLE))
627                                 break;
628                         if (ch_status->wf == WF_SQUARE)
629                                 cmd = PSG_CMD_SET_DCYCL_SQUARE;
630                         else if (ch_status->wf == WF_PULSE)
631                                 cmd = PSG_CMD_SET_DCYCL_PULSE;
632                         else
633                                 break;
634                         ret = sr_scpi_cmd(sdi, devc->cmdset,
635                                 PSG_CMD_SELECT_CHANNEL, cg->name,
636                                 cmd, cg->name, g_variant_get_double(data));
637                         break;
638                 default:
639                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
640                                 (int)key, (kinfo ? kinfo->name : "unknown"));
641                         ret = SR_ERR_NA;
642                         break;
643                 }
644         }
645
646         return ret;
647 }
648
649 static int config_list(uint32_t key, GVariant **data,
650         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
651 {
652         struct dev_context *devc;
653         struct sr_channel *ch;
654         const struct channel_spec *ch_spec;
655         const struct waveform_spec *wf_spec;
656         struct channel_status *ch_status;
657         GVariantBuilder *b;
658         unsigned int i;
659         double fspec[3];
660
661         devc = NULL;
662         if (sdi)
663                 devc = sdi->priv;
664
665         if (!cg) {
666                 switch (key) {
667                 case SR_CONF_SCAN_OPTIONS:
668                 case SR_CONF_DEVICE_OPTIONS:
669                         return std_opts_config_list(key, data, sdi, cg,
670                                 ARRAY_AND_SIZE(scanopts),
671                                 ARRAY_AND_SIZE(drvopts),
672                                 (devc && devc->device) ? devc->device->devopts : NULL,
673                                 (devc && devc->device) ? devc->device->num_devopts : 0);
674                 default:
675                         return SR_ERR_NA;
676                 }
677         } else {
678                 if (!devc || !devc->device)
679                         return SR_ERR_ARG;
680                 ch = cg->channels->data;
681                 ch_spec = &devc->device->channels[ch->index];
682                 ch_status = &devc->ch_status[ch->index];
683
684                 switch(key) {
685                 case SR_CONF_DEVICE_OPTIONS:
686                         *data = std_gvar_array_u32(devc->device->devopts_cg,
687                                         devc->device->num_devopts_cg);
688                         break;
689                 case SR_CONF_PATTERN_MODE:
690                         b = g_variant_builder_new(G_VARIANT_TYPE("as"));
691                         for (i = 0; i < ch_spec->num_waveforms; i++) {
692                                 g_variant_builder_add(b, "s",
693                                         rigol_dg_waveform_to_string(
694                                                 ch_spec->waveforms[i].waveform));
695                         }
696                         *data = g_variant_new("as", b);
697                         g_variant_builder_unref(b);
698                         break;
699                 case SR_CONF_OUTPUT_FREQUENCY:
700                         /*
701                          * Frequency range depends on the currently active
702                          * wave form.
703                          */
704                         if (rigol_dg_get_channel_state(sdi, cg) != SR_OK)
705                                 return SR_ERR_NA;
706                         wf_spec = rigol_dg_get_waveform_spec(ch_spec,
707                                         ch_status->wf);
708                         if (!wf_spec)
709                                 return SR_ERR_BUG;
710                         fspec[0] = wf_spec->freq_min;
711                         fspec[1] = wf_spec->freq_max;
712                         fspec[2] = wf_spec->freq_step;
713                         *data = std_gvar_min_max_step_array(fspec);
714                         break;
715                 case SR_CONF_PHASE:
716                         *data = std_gvar_min_max_step_array(phase_min_max_step);
717                         break;
718                 default:
719                         return SR_ERR_NA;
720                 }
721         }
722
723         return SR_OK;
724 }
725
726 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
727 {
728         struct dev_context *devc;
729         struct sr_scpi_dev_inst *scpi;
730         const char *cmd;
731         char *response;
732         int ret;
733
734         if (!sdi)
735                 return SR_ERR_ARG;
736
737         devc = sdi->priv;
738         scpi = sdi->conn;
739         response = NULL;
740         ret = SR_OK;
741
742         if (!scpi)
743                 return SR_ERR_BUG;
744
745         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_GET_ENABLED);
746         if (cmd && *cmd) {
747                 /* Check if counter is currently enabled. */
748                 ret = sr_scpi_get_string(scpi, cmd, &response);
749                 if (ret != SR_OK)
750                         return SR_ERR_NA;
751                 if (g_ascii_strncasecmp(response, "RUN", strlen("RUN")) == 0)
752                         devc->counter_enabled = TRUE;
753                 else
754                         devc->counter_enabled = FALSE;
755
756                 if (!devc->counter_enabled) {
757                         /* Enable counter if it was not already running. */
758                         cmd = sr_scpi_cmd_get(devc->cmdset,
759                                         PSG_CMD_COUNTER_SET_ENABLE);
760                         if (!cmd)
761                                 return SR_ERR_BUG;
762                         sr_scpi_get_opc(scpi);
763                         ret = sr_scpi_send(scpi, cmd);
764                 }
765         }
766
767         if (ret == SR_OK) {
768                 sr_sw_limits_acquisition_start(&devc->limits);
769                 ret = std_session_send_df_header(sdi);
770                 if (ret == SR_OK) {
771                         ret = sr_scpi_source_add(sdi->session, scpi,
772                                 G_IO_IN, 100, rigol_dg_receive_data,
773                                 (void *)sdi);
774                 }
775         }
776
777         g_free(response);
778
779         return ret;
780 }
781
782 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
783 {
784         struct dev_context *devc;
785         struct sr_scpi_dev_inst *scpi;
786         const char *cmd;
787         int ret;
788
789         if (!sdi)
790                 return SR_ERR_ARG;
791
792         devc = sdi->priv;
793         scpi = sdi->conn;
794         ret = SR_OK;
795
796         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_SET_DISABLE);
797         if (cmd && *cmd && !devc->counter_enabled) {
798                 /*
799                  * If counter was not running when acquisiton started,
800                  * turn it off now...
801                  */
802                 sr_scpi_get_opc(scpi);
803                 ret = sr_scpi_send(scpi, cmd);
804         }
805
806         sr_scpi_source_remove(sdi->session, scpi);
807         std_session_send_df_end(sdi);
808
809         return ret;
810 }
811
812 static struct sr_dev_driver rigol_dg_driver_info = {
813         .name = "rigol-dg",
814         .longname = "Rigol DG Series",
815         .api_version = 1,
816         .init = std_init,
817         .cleanup = std_cleanup,
818         .scan = scan,
819         .dev_list = std_dev_list,
820         .dev_clear = std_dev_clear,
821         .config_get = config_get,
822         .config_set = config_set,
823         .config_list = config_list,
824         .dev_open = dev_open,
825         .dev_close = dev_close,
826         .dev_acquisition_start = dev_acquisition_start,
827         .dev_acquisition_stop = dev_acquisition_stop,
828         .context = NULL,
829 };
830 SR_REGISTER_DEV_DRIVER(rigol_dg_driver_info);