]> sigrok.org Git - libsigrok.git/blob - src/hardware/rigol-dg/api.c
efe7db62ebe8aba650b629754412a25d138e84d8
[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 (ch_status->wf == WF_SQUARE) {
494                                 cmd = PSG_CMD_GET_DCYCL_SQUARE;
495                         } else if (ch_status->wf == WF_PULSE) {
496                                 cmd = PSG_CMD_GET_DCYCL_PULSE;
497                         } else {
498                                 ret = SR_ERR_NA;
499                                 break;
500                         }
501                         sr_scpi_get_opc(scpi);
502                         ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
503                                 PSG_CMD_SELECT_CHANNEL, cg->name, data,
504                                 G_VARIANT_TYPE_DOUBLE, cmd, cg->name);
505                         break;
506                 default:
507                         sr_dbg("%s: Unsupported (cg) key: %d (%s)", __func__,
508                                 (int)key, (kinfo ? kinfo->name : "unknown"));
509                         ret = SR_ERR_NA;
510                         break;
511                 }
512         }
513
514         return ret;
515 }
516
517 static int config_set(uint32_t key, GVariant *data,
518         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
519 {
520         struct dev_context *devc;
521         struct sr_scpi_dev_inst *scpi;
522         struct sr_channel *ch;
523         const struct channel_spec *ch_spec;
524         struct channel_status *ch_status;
525         const struct sr_key_info *kinfo;
526         int ret;
527         uint32_t cmd;
528         const char *mode, *mode_name, *new_mode;
529         unsigned int i;
530
531         if (!data || !sdi)
532                 return SR_ERR_ARG;
533
534         devc = sdi->priv;
535         scpi = sdi->conn;
536         kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
537
538         ret = SR_OK;
539
540         if (!cg) {
541                 switch (key) {
542                 case SR_CONF_LIMIT_MSEC:
543                 case SR_CONF_LIMIT_SAMPLES:
544                         ret = sr_sw_limits_config_set(&devc->limits, key, data);
545                         break;
546                 default:
547                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
548                                 (int)key, (kinfo ? kinfo->name : "unknown"));
549                         ret = SR_ERR_NA;
550                         break;
551                 }
552         } else {
553                 ch = cg->channels->data;
554                 ch_spec = &devc->device->channels[ch->index];
555                 ch_status = &devc->ch_status[ch->index];
556
557                 if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
558                         return ret;
559                 sr_scpi_get_opc(scpi);
560
561                 switch (key) {
562                 case SR_CONF_ENABLED:
563                         if (g_variant_get_boolean(data))
564                                 cmd = PSG_CMD_SET_ENABLE;
565                         else
566                                 cmd = PSG_CMD_SET_DISABLE;
567                         ret = sr_scpi_cmd(sdi, devc->cmdset,
568                                 PSG_CMD_SELECT_CHANNEL, cg->name, cmd, cg->name);
569                         break;
570                 case SR_CONF_PATTERN_MODE:
571                         ret = SR_ERR_NA;
572                         new_mode = NULL;
573                         mode = g_variant_get_string(data, NULL);
574                         for (i = 0; i < ch_spec->num_waveforms; i++) {
575                                 mode_name = rigol_dg_waveform_to_string(
576                                                 ch_spec->waveforms[i].waveform);
577                                 if (g_ascii_strncasecmp(mode, mode_name,
578                                                 strlen(mode_name)) == 0)
579                                         new_mode = ch_spec->waveforms[i].name;
580                         }
581                         if (new_mode)
582                                 ret = sr_scpi_cmd(sdi, devc->cmdset,
583                                         PSG_CMD_SELECT_CHANNEL, cg->name,
584                                         PSG_CMD_SET_SOURCE, cg->name, new_mode);
585                         break;
586                 case SR_CONF_OUTPUT_FREQUENCY:
587                         ret = SR_ERR_NA;
588                         if (!(ch_status->wf_spec->opts & WFO_FREQUENCY))
589                                 break;
590                         ret = sr_scpi_cmd(sdi, devc->cmdset,
591                                 PSG_CMD_SELECT_CHANNEL, cg->name,
592                                 PSG_CMD_SET_FREQUENCY, cg->name,
593                                 g_variant_get_double(data));
594                         break;
595                 case SR_CONF_AMPLITUDE:
596                         ret = SR_ERR_NA;
597                         if (!(ch_status->wf_spec->opts & WFO_AMPLITUDE))
598                                 break;
599                         ret = sr_scpi_cmd(sdi, devc->cmdset,
600                                 PSG_CMD_SELECT_CHANNEL, cg->name,
601                                 PSG_CMD_SET_AMPLITUDE, cg->name,
602                                 g_variant_get_double(data));
603                         break;
604                 case SR_CONF_OFFSET:
605                         ret = SR_ERR_NA;
606                         if (!(ch_status->wf_spec->opts & WFO_OFFSET))
607                                 break;
608                         ret = sr_scpi_cmd(sdi, devc->cmdset,
609                                 PSG_CMD_SELECT_CHANNEL, cg->name,
610                                 PSG_CMD_SET_OFFSET, cg->name,
611                                 g_variant_get_double(data));
612                         break;
613                 case SR_CONF_PHASE:
614                         ret = SR_ERR_NA;
615                         if (!(ch_status->wf_spec->opts & WFO_PHASE))
616                                 break;
617                         ret = sr_scpi_cmd(sdi, devc->cmdset,
618                                 PSG_CMD_SELECT_CHANNEL, cg->name,
619                                 PSG_CMD_SET_PHASE, cg->name,
620                                 g_variant_get_double(data));
621                         break;
622                 case SR_CONF_DUTY_CYCLE:
623                         ret = SR_ERR_NA;
624                         if (!(ch_status->wf_spec->opts & WFO_DUTY_CYCLE))
625                                 break;
626                         if (ch_status->wf == WF_SQUARE)
627                                 cmd = PSG_CMD_SET_DCYCL_SQUARE;
628                         else if (ch_status->wf == WF_PULSE)
629                                 cmd = PSG_CMD_SET_DCYCL_PULSE;
630                         else
631                                 break;
632                         ret = sr_scpi_cmd(sdi, devc->cmdset,
633                                 PSG_CMD_SELECT_CHANNEL, cg->name,
634                                 cmd, cg->name, g_variant_get_double(data));
635                         break;
636                 default:
637                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
638                                 (int)key, (kinfo ? kinfo->name : "unknown"));
639                         ret = SR_ERR_NA;
640                         break;
641                 }
642         }
643
644         return ret;
645 }
646
647 static int config_list(uint32_t key, GVariant **data,
648         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
649 {
650         struct dev_context *devc;
651         struct sr_channel *ch;
652         const struct channel_spec *ch_spec;
653         const struct waveform_spec *wf_spec;
654         struct channel_status *ch_status;
655         GVariantBuilder *b;
656         unsigned int i;
657         double fspec[3];
658
659         devc = NULL;
660         if (sdi)
661                 devc = sdi->priv;
662
663         if (!cg) {
664                 switch (key) {
665                 case SR_CONF_SCAN_OPTIONS:
666                 case SR_CONF_DEVICE_OPTIONS:
667                         return std_opts_config_list(key, data, sdi, cg,
668                                 ARRAY_AND_SIZE(scanopts),
669                                 ARRAY_AND_SIZE(drvopts),
670                                 (devc && devc->device) ? devc->device->devopts : NULL,
671                                 (devc && devc->device) ? devc->device->num_devopts : 0);
672                 default:
673                         return SR_ERR_NA;
674                 }
675         } else {
676                 if (!devc || !devc->device)
677                         return SR_ERR_ARG;
678                 ch = cg->channels->data;
679                 ch_spec = &devc->device->channels[ch->index];
680                 ch_status = &devc->ch_status[ch->index];
681
682                 switch(key) {
683                 case SR_CONF_DEVICE_OPTIONS:
684                         *data = std_gvar_array_u32(devc->device->devopts_cg,
685                                         devc->device->num_devopts_cg);
686                         break;
687                 case SR_CONF_PATTERN_MODE:
688                         b = g_variant_builder_new(G_VARIANT_TYPE("as"));
689                         for (i = 0; i < ch_spec->num_waveforms; i++) {
690                                 g_variant_builder_add(b, "s",
691                                         rigol_dg_waveform_to_string(
692                                                 ch_spec->waveforms[i].waveform));
693                         }
694                         *data = g_variant_new("as", b);
695                         g_variant_builder_unref(b);
696                         break;
697                 case SR_CONF_OUTPUT_FREQUENCY:
698                         /*
699                          * Frequency range depends on the currently active
700                          * wave form.
701                          */
702                         if (rigol_dg_get_channel_state(sdi, cg) != SR_OK)
703                                 return SR_ERR_NA;
704                         wf_spec = rigol_dg_get_waveform_spec(ch_spec,
705                                         ch_status->wf);
706                         if (!wf_spec)
707                                 return SR_ERR_BUG;
708                         fspec[0] = wf_spec->freq_min;
709                         fspec[1] = wf_spec->freq_max;
710                         fspec[2] = wf_spec->freq_step;
711                         *data = std_gvar_min_max_step_array(fspec);
712                         break;
713                 case SR_CONF_PHASE:
714                         *data = std_gvar_min_max_step_array(phase_min_max_step);
715                         break;
716                 default:
717                         return SR_ERR_NA;
718                 }
719         }
720
721         return SR_OK;
722 }
723
724 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
725 {
726         struct dev_context *devc;
727         struct sr_scpi_dev_inst *scpi;
728         const char *cmd;
729         char *response;
730         int ret;
731
732         if (!sdi)
733                 return SR_ERR_ARG;
734
735         devc = sdi->priv;
736         scpi = sdi->conn;
737         response = NULL;
738         ret = SR_OK;
739
740         if (!scpi)
741                 return SR_ERR_BUG;
742
743         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_GET_ENABLED);
744         if (cmd && *cmd) {
745                 /* Check if counter is currently enabled. */
746                 ret = sr_scpi_get_string(scpi, cmd, &response);
747                 if (ret != SR_OK)
748                         return SR_ERR_NA;
749                 if (g_ascii_strncasecmp(response, "RUN", strlen("RUN")) == 0)
750                         devc->counter_enabled = TRUE;
751                 else
752                         devc->counter_enabled = FALSE;
753
754                 if (!devc->counter_enabled) {
755                         /* Enable counter if it was not already running. */
756                         cmd = sr_scpi_cmd_get(devc->cmdset,
757                                         PSG_CMD_COUNTER_SET_ENABLE);
758                         if (!cmd)
759                                 return SR_ERR_BUG;
760                         sr_scpi_get_opc(scpi);
761                         ret = sr_scpi_send(scpi, cmd);
762                 }
763         }
764
765         if (ret == SR_OK) {
766                 sr_sw_limits_acquisition_start(&devc->limits);
767                 ret = std_session_send_df_header(sdi);
768                 if (ret == SR_OK) {
769                         ret = sr_scpi_source_add(sdi->session, scpi,
770                                 G_IO_IN, 100, rigol_dg_receive_data,
771                                 (void *)sdi);
772                 }
773         }
774
775         g_free(response);
776
777         return ret;
778 }
779
780 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
781 {
782         struct dev_context *devc;
783         struct sr_scpi_dev_inst *scpi;
784         const char *cmd;
785         int ret;
786
787         if (!sdi)
788                 return SR_ERR_ARG;
789
790         devc = sdi->priv;
791         scpi = sdi->conn;
792         ret = SR_OK;
793
794         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_SET_DISABLE);
795         if (cmd && *cmd && !devc->counter_enabled) {
796                 /*
797                  * If counter was not running when acquisiton started,
798                  * turn it off now...
799                  */
800                 sr_scpi_get_opc(scpi);
801                 ret = sr_scpi_send(scpi, cmd);
802         }
803
804         sr_scpi_source_remove(sdi->session, scpi);
805         std_session_send_df_end(sdi);
806
807         return ret;
808 }
809
810 static struct sr_dev_driver rigol_dg_driver_info = {
811         .name = "rigol-dg",
812         .longname = "Rigol DG Series",
813         .api_version = 1,
814         .init = std_init,
815         .cleanup = std_cleanup,
816         .scan = scan,
817         .dev_list = std_dev_list,
818         .dev_clear = std_dev_clear,
819         .config_get = config_get,
820         .config_set = config_set,
821         .config_list = config_list,
822         .dev_open = dev_open,
823         .dev_close = dev_close,
824         .dev_acquisition_start = dev_acquisition_start,
825         .dev_acquisition_stop = dev_acquisition_stop,
826         .context = NULL,
827 };
828 SR_REGISTER_DEV_DRIVER(rigol_dg_driver_info);