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