]> sigrok.org Git - libsigrok.git/blob - src/hardware/rigol-dg/api.c
output/csv: use intermediate time_t var, silence compiler warning
[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 void check_device_quirks(struct sr_dev_inst *sdi)
306 {
307         struct dev_context *devc;
308         gboolean is_8xx, is_9xx;
309
310         devc = sdi->priv;
311
312         /*
313          * Check for counter issue in DG800/DG900 units...
314          *
315          * TODO: Add firmware version check if Rigol fixes this issue
316          *       in future firmware versions.
317          */
318         is_8xx = g_ascii_strncasecmp(sdi->model, "DG8", strlen("DG8")) == 0;
319         is_9xx = g_ascii_strncasecmp(sdi->model, "DG9", strlen("DG9")) == 0;
320         if (is_8xx || is_9xx) {
321                 devc->quirks |= RIGOL_DG_COUNTER_BUG;
322                 devc->quirks |= RIGOL_DG_COUNTER_CH2_CONFLICT;
323         }
324 }
325
326 static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
327 {
328         struct sr_dev_inst *sdi;
329         struct dev_context *devc;
330         struct sr_scpi_hw_info *hw_info;
331         const struct device_spec *device;
332         const struct scpi_command *cmdset;
333         struct sr_channel *ch;
334         struct sr_channel_group *cg;
335         const char *command;
336         unsigned int i, ch_idx;
337         char tmp[16];
338
339         sdi = NULL;
340         devc = NULL;
341         hw_info = NULL;
342
343         if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK)
344                 goto error;
345
346         device = NULL;
347         for (i = 0; i < ARRAY_SIZE(device_models); i++) {
348                 if (g_ascii_strcasecmp(hw_info->manufacturer,
349                                 device_models[i].vendor) != 0)
350                         continue;
351                 if (g_ascii_strcasecmp(hw_info->model,
352                                 device_models[i].model) != 0)
353                         continue;
354                 device = &device_models[i];
355                 cmdset = device_models[i].cmdset;
356                 break;
357         }
358         if (!device)
359                 goto error;
360
361         sdi = g_malloc0(sizeof(*sdi));
362         sdi->vendor = g_strdup(hw_info->manufacturer);
363         sdi->model = g_strdup(hw_info->model);
364         sdi->version = g_strdup(hw_info->firmware_version);
365         sdi->serial_num = g_strdup(hw_info->serial_number);
366         sdi->conn = scpi;
367         sdi->driver = &rigol_dg_driver_info;
368         sdi->inst_type = SR_INST_SCPI;
369
370         devc = g_malloc0(sizeof(*devc));
371         devc->cmdset = cmdset;
372         devc->device = device;
373         devc->ch_status = g_malloc0((device->num_channels + 1) *
374                         sizeof(devc->ch_status[0]));
375         sr_sw_limits_init(&devc->limits);
376         sdi->priv = devc;
377
378         /* Create channel group and channel for each device channel. */
379         ch_idx = 0;
380         for (i = 0; i < device->num_channels; i++) {
381                 ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE,
382                                 device->channels[i].name);
383                 snprintf(tmp, sizeof(tmp), "%u", i + 1);
384                 cg = sr_channel_group_new(sdi, tmp, NULL);
385                 cg->channels = g_slist_append(cg->channels, ch);
386         }
387
388         /* Create channels for the frequency counter output. */
389         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "FREQ1");
390         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "PERIOD1");
391         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "DUTY1");
392         ch = sr_channel_new(sdi, ch_idx++, SR_CHANNEL_ANALOG, TRUE, "WIDTH1");
393
394         /* Put device back to "local" mode, in case only a scan was done... */
395         command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_SETUP_LOCAL);
396         if (command && *command) {
397                 sr_scpi_get_opc(scpi);
398                 sr_scpi_send(scpi, command);
399         }
400
401         sr_scpi_hw_info_free(hw_info);
402
403         /* Check for device/firmware specific issues. */
404         check_device_quirks(sdi);
405
406         return sdi;
407
408 error:
409         sr_scpi_hw_info_free(hw_info);
410         g_free(devc);
411         sr_dev_inst_free(sdi);
412
413         return NULL;
414 }
415
416 static GSList *scan(struct sr_dev_driver *di, GSList *options)
417 {
418         return sr_scpi_scan(di->context, options, probe_device);
419 }
420
421 static int dev_open(struct sr_dev_inst *sdi)
422 {
423         return sr_scpi_open(sdi->conn);
424 }
425
426 static int dev_close(struct sr_dev_inst *sdi)
427 {
428         struct dev_context *devc;
429         struct sr_scpi_dev_inst *scpi;
430         const char *command;
431
432         devc = sdi->priv;
433         scpi = sdi->conn;
434         if (!scpi)
435                 return SR_ERR_BUG;
436
437         /* Put unit back to "local" mode. */
438         command = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_SETUP_LOCAL);
439         if (command && *command) {
440                 sr_scpi_get_opc(scpi);
441                 sr_scpi_send(scpi, command);
442         }
443
444         return sr_scpi_close(sdi->conn);
445 }
446
447 static int config_get(uint32_t key, GVariant **data,
448         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
449 {
450         struct dev_context *devc;
451         struct sr_scpi_dev_inst *scpi;
452         struct sr_channel *ch;
453         struct channel_status *ch_status;
454         const struct sr_key_info *kinfo;
455         uint32_t cmd;
456         int ret;
457
458         if (!sdi || !data)
459                 return SR_ERR_ARG;
460
461         devc = sdi->priv;
462         scpi = sdi->conn;
463         ret = SR_OK;
464         kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
465
466         if (!cg) {
467                 switch (key) {
468                 case SR_CONF_LIMIT_SAMPLES:
469                 case SR_CONF_LIMIT_MSEC:
470                         ret = sr_sw_limits_config_get(&devc->limits, key, data);
471                         break;
472                 default:
473                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
474                                 (int)key, (kinfo ? kinfo->name : "unknown"));
475                         ret = SR_ERR_NA;
476                         break;
477                 }
478         } else {
479                 ch = cg->channels->data;
480                 ch_status = &devc->ch_status[ch->index];
481
482                 switch (key) {
483                 case SR_CONF_ENABLED:
484                         sr_scpi_get_opc(scpi);
485                         ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
486                                 PSG_CMD_SELECT_CHANNEL, cg->name, data,
487                                 G_VARIANT_TYPE_BOOLEAN, PSG_CMD_GET_ENABLED,
488                                 cg->name);
489                         break;
490                 case SR_CONF_PATTERN_MODE:
491                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK) {
492                                 *data = g_variant_new_string(
493                                          rigol_dg_waveform_to_string(
494                                                  ch_status->wf));
495                         }
496                         break;
497                 case SR_CONF_OUTPUT_FREQUENCY:
498                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
499                                 *data = g_variant_new_double(ch_status->freq);
500                         break;
501                 case SR_CONF_AMPLITUDE:
502                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
503                                 *data = g_variant_new_double(ch_status->ampl);
504                         break;
505                 case SR_CONF_OFFSET:
506                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
507                                 *data = g_variant_new_double(ch_status->offset);
508                         break;
509                 case SR_CONF_PHASE:
510                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) == SR_OK)
511                                 *data = g_variant_new_double(ch_status->phase);
512                         break;
513                 case SR_CONF_DUTY_CYCLE:
514                         if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
515                                 break;
516                         if (ch_status->wf == WF_SQUARE) {
517                                 cmd = PSG_CMD_GET_DCYCL_SQUARE;
518                         } else if (ch_status->wf == WF_PULSE) {
519                                 cmd = PSG_CMD_GET_DCYCL_PULSE;
520                         } else {
521                                 ret = SR_ERR_NA;
522                                 break;
523                         }
524                         sr_scpi_get_opc(scpi);
525                         ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
526                                 PSG_CMD_SELECT_CHANNEL, cg->name, data,
527                                 G_VARIANT_TYPE_DOUBLE, cmd, cg->name);
528                         break;
529                 default:
530                         sr_dbg("%s: Unsupported (cg) key: %d (%s)", __func__,
531                                 (int)key, (kinfo ? kinfo->name : "unknown"));
532                         ret = SR_ERR_NA;
533                         break;
534                 }
535         }
536
537         return ret;
538 }
539
540 static int config_set(uint32_t key, GVariant *data,
541         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
542 {
543         struct dev_context *devc;
544         struct sr_scpi_dev_inst *scpi;
545         struct sr_channel *ch;
546         const struct channel_spec *ch_spec;
547         struct channel_status *ch_status;
548         const struct sr_key_info *kinfo;
549         int ret;
550         uint32_t cmd;
551         const char *mode, *mode_name, *new_mode;
552         unsigned int i;
553
554         if (!data || !sdi)
555                 return SR_ERR_ARG;
556
557         devc = sdi->priv;
558         scpi = sdi->conn;
559         kinfo = sr_key_info_get(SR_KEY_CONFIG, key);
560
561         ret = SR_OK;
562
563         if (!cg) {
564                 switch (key) {
565                 case SR_CONF_LIMIT_MSEC:
566                 case SR_CONF_LIMIT_SAMPLES:
567                         ret = sr_sw_limits_config_set(&devc->limits, key, data);
568                         break;
569                 default:
570                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
571                                 (int)key, (kinfo ? kinfo->name : "unknown"));
572                         ret = SR_ERR_NA;
573                         break;
574                 }
575         } else {
576                 ch = cg->channels->data;
577                 ch_spec = &devc->device->channels[ch->index];
578                 ch_status = &devc->ch_status[ch->index];
579
580                 if ((ret = rigol_dg_get_channel_state(sdi, cg)) != SR_OK)
581                         return ret;
582                 sr_scpi_get_opc(scpi);
583
584                 switch (key) {
585                 case SR_CONF_ENABLED:
586                         if (g_variant_get_boolean(data))
587                                 cmd = PSG_CMD_SET_ENABLE;
588                         else
589                                 cmd = PSG_CMD_SET_DISABLE;
590                         ret = sr_scpi_cmd(sdi, devc->cmdset,
591                                 PSG_CMD_SELECT_CHANNEL, cg->name, cmd, cg->name);
592                         break;
593                 case SR_CONF_PATTERN_MODE:
594                         ret = SR_ERR_NA;
595                         new_mode = NULL;
596                         mode = g_variant_get_string(data, NULL);
597                         for (i = 0; i < ch_spec->num_waveforms; i++) {
598                                 mode_name = rigol_dg_waveform_to_string(
599                                                 ch_spec->waveforms[i].waveform);
600                                 if (g_ascii_strncasecmp(mode, mode_name,
601                                                 strlen(mode_name)) == 0)
602                                         new_mode = ch_spec->waveforms[i].name;
603                         }
604                         if (new_mode)
605                                 ret = sr_scpi_cmd(sdi, devc->cmdset,
606                                         PSG_CMD_SELECT_CHANNEL, cg->name,
607                                         PSG_CMD_SET_SOURCE, cg->name, new_mode);
608                         break;
609                 case SR_CONF_OUTPUT_FREQUENCY:
610                         ret = SR_ERR_NA;
611                         if (!(ch_status->wf_spec->opts & WFO_FREQUENCY))
612                                 break;
613                         ret = sr_scpi_cmd(sdi, devc->cmdset,
614                                 PSG_CMD_SELECT_CHANNEL, cg->name,
615                                 PSG_CMD_SET_FREQUENCY, cg->name,
616                                 g_variant_get_double(data));
617                         break;
618                 case SR_CONF_AMPLITUDE:
619                         ret = SR_ERR_NA;
620                         if (!(ch_status->wf_spec->opts & WFO_AMPLITUDE))
621                                 break;
622                         ret = sr_scpi_cmd(sdi, devc->cmdset,
623                                 PSG_CMD_SELECT_CHANNEL, cg->name,
624                                 PSG_CMD_SET_AMPLITUDE, cg->name,
625                                 g_variant_get_double(data));
626                         break;
627                 case SR_CONF_OFFSET:
628                         ret = SR_ERR_NA;
629                         if (!(ch_status->wf_spec->opts & WFO_OFFSET))
630                                 break;
631                         ret = sr_scpi_cmd(sdi, devc->cmdset,
632                                 PSG_CMD_SELECT_CHANNEL, cg->name,
633                                 PSG_CMD_SET_OFFSET, cg->name,
634                                 g_variant_get_double(data));
635                         break;
636                 case SR_CONF_PHASE:
637                         ret = SR_ERR_NA;
638                         if (!(ch_status->wf_spec->opts & WFO_PHASE))
639                                 break;
640                         ret = sr_scpi_cmd(sdi, devc->cmdset,
641                                 PSG_CMD_SELECT_CHANNEL, cg->name,
642                                 PSG_CMD_SET_PHASE, cg->name,
643                                 g_variant_get_double(data));
644                         break;
645                 case SR_CONF_DUTY_CYCLE:
646                         ret = SR_ERR_NA;
647                         if (!(ch_status->wf_spec->opts & WFO_DUTY_CYCLE))
648                                 break;
649                         if (ch_status->wf == WF_SQUARE)
650                                 cmd = PSG_CMD_SET_DCYCL_SQUARE;
651                         else if (ch_status->wf == WF_PULSE)
652                                 cmd = PSG_CMD_SET_DCYCL_PULSE;
653                         else
654                                 break;
655                         ret = sr_scpi_cmd(sdi, devc->cmdset,
656                                 PSG_CMD_SELECT_CHANNEL, cg->name,
657                                 cmd, cg->name, g_variant_get_double(data));
658                         break;
659                 default:
660                         sr_dbg("%s: Unsupported key: %d (%s)", __func__,
661                                 (int)key, (kinfo ? kinfo->name : "unknown"));
662                         ret = SR_ERR_NA;
663                         break;
664                 }
665         }
666
667         return ret;
668 }
669
670 static int config_list(uint32_t key, GVariant **data,
671         const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
672 {
673         struct dev_context *devc;
674         struct sr_channel *ch;
675         const struct channel_spec *ch_spec;
676         const struct waveform_spec *wf_spec;
677         struct channel_status *ch_status;
678         GVariantBuilder *b;
679         unsigned int i;
680         double fspec[3];
681
682         devc = NULL;
683         if (sdi)
684                 devc = sdi->priv;
685
686         if (!cg) {
687                 switch (key) {
688                 case SR_CONF_SCAN_OPTIONS:
689                 case SR_CONF_DEVICE_OPTIONS:
690                         return std_opts_config_list(key, data, sdi, cg,
691                                 ARRAY_AND_SIZE(scanopts),
692                                 ARRAY_AND_SIZE(drvopts),
693                                 (devc && devc->device) ? devc->device->devopts : NULL,
694                                 (devc && devc->device) ? devc->device->num_devopts : 0);
695                 default:
696                         return SR_ERR_NA;
697                 }
698         } else {
699                 if (!devc || !devc->device)
700                         return SR_ERR_ARG;
701                 ch = cg->channels->data;
702                 ch_spec = &devc->device->channels[ch->index];
703                 ch_status = &devc->ch_status[ch->index];
704
705                 switch(key) {
706                 case SR_CONF_DEVICE_OPTIONS:
707                         *data = std_gvar_array_u32(devc->device->devopts_cg,
708                                         devc->device->num_devopts_cg);
709                         break;
710                 case SR_CONF_PATTERN_MODE:
711                         b = g_variant_builder_new(G_VARIANT_TYPE("as"));
712                         for (i = 0; i < ch_spec->num_waveforms; i++) {
713                                 g_variant_builder_add(b, "s",
714                                         rigol_dg_waveform_to_string(
715                                                 ch_spec->waveforms[i].waveform));
716                         }
717                         *data = g_variant_new("as", b);
718                         g_variant_builder_unref(b);
719                         break;
720                 case SR_CONF_OUTPUT_FREQUENCY:
721                         /*
722                          * Frequency range depends on the currently active
723                          * wave form.
724                          */
725                         if (rigol_dg_get_channel_state(sdi, cg) != SR_OK)
726                                 return SR_ERR_NA;
727                         wf_spec = rigol_dg_get_waveform_spec(ch_spec,
728                                         ch_status->wf);
729                         if (!wf_spec)
730                                 return SR_ERR_BUG;
731                         fspec[0] = wf_spec->freq_min;
732                         fspec[1] = wf_spec->freq_max;
733                         fspec[2] = wf_spec->freq_step;
734                         *data = std_gvar_min_max_step_array(fspec);
735                         break;
736                 case SR_CONF_PHASE:
737                         *data = std_gvar_min_max_step_array(phase_min_max_step);
738                         break;
739                 default:
740                         return SR_ERR_NA;
741                 }
742         }
743
744         return SR_OK;
745 }
746
747 static int dev_acquisition_start(const struct sr_dev_inst *sdi)
748 {
749         struct dev_context *devc;
750         struct sr_scpi_dev_inst *scpi;
751         const char *cmd;
752         char *response;
753         GVariant *data;
754         gboolean need_quirk;
755         gboolean ch_active;
756         int ret;
757
758         if (!sdi)
759                 return SR_ERR_ARG;
760
761         devc = sdi->priv;
762         scpi = sdi->conn;
763         response = NULL;
764         data = NULL;
765         ret = SR_OK;
766
767         if (!scpi)
768                 return SR_ERR_BUG;
769
770         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_GET_ENABLED);
771         if (cmd && *cmd) {
772                 /* Check if counter is currently enabled. */
773                 ret = sr_scpi_get_string(scpi, cmd, &response);
774                 if (ret != SR_OK)
775                         return SR_ERR_NA;
776                 if (g_ascii_strncasecmp(response, "RUN", strlen("RUN")) == 0)
777                         devc->counter_enabled = TRUE;
778                 else
779                         devc->counter_enabled = FALSE;
780                 g_free(response);
781
782                 if (!devc->counter_enabled) {
783                         /*
784                          * Enable counter if it was not already running.
785                          * Some devices cannot use channel 2 and the counter
786                          * at the same time. Some cannot respond right after
787                          * enabling the counter and need a delay.
788                          */
789
790                         need_quirk = devc->quirks & RIGOL_DG_COUNTER_CH2_CONFLICT;
791                         need_quirk &= devc->device->num_channels > 1;
792                         if (need_quirk) {
793                                 sr_scpi_get_opc(scpi);
794                                 ret = sr_scpi_cmd_resp(sdi, devc->cmdset,
795                                         PSG_CMD_SELECT_CHANNEL, "2",
796                                         &data, G_VARIANT_TYPE_BOOLEAN,
797                                         PSG_CMD_GET_ENABLED, "2");
798                                 if (ret != SR_OK)
799                                         return SR_ERR_NA;
800                                 ch_active = g_variant_get_boolean(data);
801                                 g_variant_unref(data);
802                                 if (ch_active) {
803                                         sr_scpi_get_opc(scpi);
804                                         ret = sr_scpi_cmd(sdi, devc->cmdset,
805                                                 PSG_CMD_SELECT_CHANNEL, "2",
806                                                 PSG_CMD_SET_DISABLE, "2");
807                                         if (ret != SR_OK)
808                                                 return SR_ERR_NA;
809                                 }
810                         }
811
812                         cmd = sr_scpi_cmd_get(devc->cmdset,
813                                         PSG_CMD_COUNTER_SET_ENABLE);
814                         if (!cmd)
815                                 return SR_ERR_BUG;
816                         sr_scpi_get_opc(scpi);
817                         ret = sr_scpi_send(scpi, cmd);
818
819                         need_quirk = devc->quirks & RIGOL_DG_COUNTER_BUG;
820                         if (need_quirk)
821                                 g_usleep(RIGOL_DG_COUNTER_BUG_DELAY);
822                 }
823         }
824
825         if (ret == SR_OK) {
826                 sr_sw_limits_acquisition_start(&devc->limits);
827                 ret = std_session_send_df_header(sdi);
828                 if (ret == SR_OK) {
829                         ret = sr_scpi_source_add(sdi->session, scpi,
830                                 G_IO_IN, 100, rigol_dg_receive_data,
831                                 (void *)sdi);
832                 }
833         }
834
835         return ret;
836 }
837
838 static int dev_acquisition_stop(struct sr_dev_inst *sdi)
839 {
840         struct dev_context *devc;
841         struct sr_scpi_dev_inst *scpi;
842         const char *cmd;
843         int ret;
844
845         if (!sdi)
846                 return SR_ERR_ARG;
847
848         devc = sdi->priv;
849         scpi = sdi->conn;
850         ret = SR_OK;
851
852         cmd = sr_scpi_cmd_get(devc->cmdset, PSG_CMD_COUNTER_SET_DISABLE);
853         if (cmd && *cmd && !devc->counter_enabled) {
854                 /*
855                  * If counter was not running when acquisiton started,
856                  * turn it off now. Some devices need a delay after
857                  * disabling the counter.
858                  */
859                 sr_scpi_get_opc(scpi);
860                 ret = sr_scpi_send(scpi, cmd);
861                 if (devc->quirks & RIGOL_DG_COUNTER_BUG)
862                         g_usleep(RIGOL_DG_COUNTER_BUG_DELAY);
863         }
864
865         sr_scpi_source_remove(sdi->session, scpi);
866         std_session_send_df_end(sdi);
867
868         return ret;
869 }
870
871 static struct sr_dev_driver rigol_dg_driver_info = {
872         .name = "rigol-dg",
873         .longname = "Rigol DG Series",
874         .api_version = 1,
875         .init = std_init,
876         .cleanup = std_cleanup,
877         .scan = scan,
878         .dev_list = std_dev_list,
879         .dev_clear = std_dev_clear,
880         .config_get = config_get,
881         .config_set = config_set,
882         .config_list = config_list,
883         .dev_open = dev_open,
884         .dev_close = dev_close,
885         .dev_acquisition_start = dev_acquisition_start,
886         .dev_acquisition_stop = dev_acquisition_stop,
887         .context = NULL,
888 };
889 SR_REGISTER_DEV_DRIVER(rigol_dg_driver_info);