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