]> sigrok.org Git - libsigrok.git/blame - src/hardware/juntek-jds6600/api.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / juntek-jds6600 / api.c
CommitLineData
b1fa9aac
GS
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2023 Gerhard Sittig <gerhard.sittig@gmx.net>
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
18baeeed
GS
20#include "config.h"
21
b1fa9aac
GS
22#include "protocol.h"
23
18baeeed 24#define DFLT_SERIALCOMM "115200/8n1"
b1fa9aac 25
18baeeed
GS
26#define VENDOR_TEXT "Juntek"
27#define MODEL_TEXT "JDS6600"
b1fa9aac 28
18baeeed
GS
29static const uint32_t scanopts[] = {
30 SR_CONF_CONN,
31};
b1fa9aac 32
18baeeed
GS
33static const uint32_t drvopts[] = {
34 SR_CONF_SIGNAL_GENERATOR,
35};
b1fa9aac 36
18baeeed
GS
37static const uint32_t devopts[] = {
38 SR_CONF_CONN | SR_CONF_GET,
39 SR_CONF_ENABLED | SR_CONF_SET,
40 SR_CONF_PHASE | SR_CONF_GET | SR_CONF_SET,
41};
b1fa9aac 42
18baeeed
GS
43static const uint32_t devopts_cg[] = {
44 SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET,
45 SR_CONF_PATTERN_MODE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
46 SR_CONF_OUTPUT_FREQUENCY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
47 SR_CONF_AMPLITUDE | SR_CONF_GET | SR_CONF_SET,
48 SR_CONF_OFFSET | SR_CONF_GET | SR_CONF_SET,
49 SR_CONF_DUTY_CYCLE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
50};
b1fa9aac 51
18baeeed 52static GSList *scan(struct sr_dev_driver *di, GSList *options)
b1fa9aac 53{
18baeeed
GS
54 GSList *devices;
55 const char *conn, *serialcomm;
56 struct sr_dev_inst *sdi;
57 struct dev_context *devc;
58 struct sr_serial_dev_inst *ser;
59 int ret;
60 size_t ch_idx, idx, ch_nr;
61 char cg_name[8];
62 struct sr_channel_group *cg;
63 struct sr_channel *ch;
b1fa9aac 64
18baeeed 65 devices = NULL;
b1fa9aac 66
18baeeed
GS
67 conn = NULL;
68 serialcomm = DFLT_SERIALCOMM;
69 (void)sr_serial_extract_options(options, &conn, &serialcomm);
70 if (!conn)
71 return devices;
72
73 ser = sr_serial_dev_inst_new(conn, serialcomm);
74 if (!ser)
75 return devices;
76 ret = serial_open(ser, SERIAL_RDWR);
1711287e
GS
77 if (ret != SR_OK) {
78 sr_serial_dev_inst_free(ser);
18baeeed 79 return devices;
1711287e 80 }
18baeeed
GS
81
82 sdi = g_malloc0(sizeof(*sdi));
83 sdi->status = SR_ST_INACTIVE;
84 sdi->inst_type = SR_INST_USB;
85 sdi->conn = ser;
86 sdi->connection_id = g_strdup(conn);
87 devc = g_malloc0(sizeof(*devc));
88 sdi->priv = devc;
89
90 ret = jds6600_identify(sdi);
91 if (ret != SR_OK)
92 goto fail;
93 ret = jds6600_setup_devc(sdi);
94 if (ret != SR_OK)
95 goto fail;
96 (void)serial_close(ser);
97
98 sdi->vendor = g_strdup(VENDOR_TEXT);
99 sdi->model = g_strdup(MODEL_TEXT);
100 if (devc->device.serial_number)
101 sdi->serial_num = g_strdup(devc->device.serial_number);
102
103 ch_idx = 0;
104 for (idx = 0; idx < MAX_GEN_CHANNELS; idx++) {
105 ch_nr = idx + 1;
106 snprintf(cg_name, sizeof(cg_name), "CH%zu", ch_nr);
107 cg = sr_channel_group_new(sdi, cg_name, NULL);
108 (void)cg;
109 ch = sr_channel_new(sdi, ch_idx,
110 SR_CHANNEL_ANALOG, FALSE, cg_name);
111 cg->channels = g_slist_append(cg->channels, ch);
112 ch_idx++;
113 }
b1fa9aac 114
18baeeed
GS
115 devices = g_slist_append(devices, sdi);
116 return std_scan_complete(di, devices);
b1fa9aac 117
18baeeed
GS
118fail:
119 (void)serial_close(ser);
120 sr_serial_dev_inst_free(ser);
121 if (devc) {
122 g_free(devc->device.serial_number);
123 g_free(devc->waveforms.fw_codes);
124 g_free(devc->waveforms.names);
125 }
126 g_free(devc);
127 sr_dev_inst_free(sdi);
b1fa9aac 128
18baeeed 129 return devices;
b1fa9aac
GS
130}
131
132static int config_get(uint32_t key, GVariant **data,
133 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
134{
18baeeed 135 struct dev_context *devc;
b1fa9aac 136 int ret;
18baeeed
GS
137 size_t cg_idx;
138 struct devc_wave *waves;
139 struct devc_chan *chan;
140 double dvalue;
141 const char *s;
142
143 devc = sdi ? sdi->priv : NULL;
144 if (!cg) {
145 switch (key) {
146 case SR_CONF_CONN:
147 if (!sdi->connection_id)
148 return SR_ERR_NA;
149 *data = g_variant_new_string(sdi->connection_id);
150 return SR_OK;
151 case SR_CONF_PHASE:
152 if (!devc)
153 return SR_ERR_NA;
154 ret = jds6600_get_phase_chans(sdi);
155 if (ret != SR_OK)
156 return SR_ERR_NA;
157 dvalue = devc->channels_phase;
158 *data = g_variant_new_double(dvalue);
159 return SR_OK;
160 default:
161 return SR_ERR_NA;
162 }
163 }
b1fa9aac 164
18baeeed
GS
165 if (!devc)
166 return SR_ERR_NA;
167 ret = g_slist_index(sdi->channel_groups, cg);
168 if (ret < 0)
169 return SR_ERR_NA;
170 cg_idx = (size_t)ret;
171 if (cg_idx >= ARRAY_SIZE(devc->channel_config))
172 return SR_ERR_NA;
173 chan = &devc->channel_config[cg_idx];
b1fa9aac 174
b1fa9aac 175 switch (key) {
18baeeed
GS
176 case SR_CONF_ENABLED:
177 ret = jds6600_get_chans_enable(sdi);
178 if (ret != SR_OK)
179 return SR_ERR_NA;
180 *data = g_variant_new_boolean(chan->enabled);
181 return SR_OK;
182 case SR_CONF_PATTERN_MODE:
183 ret = jds6600_get_waveform(sdi, cg_idx);
184 if (ret != SR_OK)
185 return SR_ERR_NA;
186 waves = &devc->waveforms;
187 s = waves->names[chan->waveform_index];
188 *data = g_variant_new_string(s);
189 return SR_OK;
190 case SR_CONF_OUTPUT_FREQUENCY:
191 ret = jds6600_get_frequency(sdi, cg_idx);
192 if (ret != SR_OK)
193 return SR_ERR_NA;
194 dvalue = chan->output_frequency;
195 *data = g_variant_new_double(dvalue);
196 return SR_OK;
197 case SR_CONF_AMPLITUDE:
198 ret = jds6600_get_amplitude(sdi, cg_idx);
199 if (ret != SR_OK)
200 return SR_ERR_NA;
201 dvalue = chan->amplitude;
202 *data = g_variant_new_double(dvalue);
203 return SR_OK;
204 case SR_CONF_OFFSET:
205 ret = jds6600_get_offset(sdi, cg_idx);
206 if (ret != SR_OK)
207 return SR_ERR_NA;
208 dvalue = chan->offset;
209 *data = g_variant_new_double(dvalue);
210 return SR_OK;
211 case SR_CONF_DUTY_CYCLE:
212 ret = jds6600_get_dutycycle(sdi, cg_idx);
213 if (ret != SR_OK)
214 return SR_ERR_NA;
215 dvalue = chan->dutycycle;
216 *data = g_variant_new_double(dvalue);
217 return SR_OK;
b1fa9aac
GS
218 default:
219 return SR_ERR_NA;
220 }
b1fa9aac
GS
221}
222
223static int config_set(uint32_t key, GVariant *data,
224 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
225{
18baeeed
GS
226 struct dev_context *devc;
227 struct devc_wave *waves;
228 struct devc_chan *chan;
229 size_t cg_idx;
230 double dvalue;
231 gboolean on;
232 int ret, idx;
233
234 devc = sdi ? sdi->priv : NULL;
235
236 if (!cg) {
237 switch (key) {
238 case SR_CONF_ENABLED:
239 /* Enable/disable all channels at the same time. */
240 on = g_variant_get_boolean(data);
241 if (!devc)
242 return SR_ERR_ARG;
243 cg_idx = devc->device.channel_count_gen;
244 while (cg_idx) {
245 chan = &devc->channel_config[--cg_idx];
246 chan->enabled = on;
247 }
248 ret = jds6600_set_chans_enable(sdi);
249 if (ret != SR_OK)
250 return SR_ERR_NA;
251 return SR_OK;
252 case SR_CONF_PHASE:
253 if (!devc)
254 return SR_ERR_ARG;
255 dvalue = g_variant_get_double(data);
256 devc->channels_phase = dvalue;
257 ret = jds6600_set_phase_chans(sdi);
258 if (ret != SR_OK)
259 return SR_ERR_NA;
260 return SR_OK;
261 default:
262 return SR_ERR_NA;
263 }
264 }
b1fa9aac 265
18baeeed
GS
266 ret = g_slist_index(sdi->channel_groups, cg);
267 if (ret < 0)
268 return SR_ERR_NA;
269 cg_idx = (size_t)ret;
270 if (cg_idx >= ARRAY_SIZE(devc->channel_config))
271 return SR_ERR_NA;
272 chan = &devc->channel_config[cg_idx];
b1fa9aac 273
b1fa9aac 274 switch (key) {
18baeeed
GS
275 case SR_CONF_ENABLED:
276 on = g_variant_get_boolean(data);
277 chan->enabled = on;
278 ret = jds6600_set_chans_enable(sdi);
279 if (ret != SR_OK)
280 return SR_ERR_NA;
281 return SR_OK;
282 case SR_CONF_PATTERN_MODE:
283 waves = &devc->waveforms;
284 idx = std_str_idx(data, waves->names, waves->names_count);
285 if (idx < 0)
286 return SR_ERR_NA;
287 if ((size_t)idx >= waves->names_count)
288 return SR_ERR_NA;
289 chan->waveform_index = idx;
290 chan->waveform_code = waves->fw_codes[chan->waveform_index];
291 ret = jds6600_set_waveform(sdi, cg_idx);
292 if (ret != SR_OK)
293 return SR_ERR_NA;
294 return SR_OK;
295 case SR_CONF_OUTPUT_FREQUENCY:
296 dvalue = g_variant_get_double(data);
297 chan->output_frequency = dvalue;
298 ret = jds6600_set_frequency(sdi, cg_idx);
299 if (ret != SR_OK)
300 return SR_ERR_NA;
301 return SR_OK;
302 case SR_CONF_AMPLITUDE:
303 dvalue = g_variant_get_double(data);
304 chan->amplitude = dvalue;
305 ret = jds6600_set_amplitude(sdi, cg_idx);
306 if (ret != SR_OK)
307 return SR_ERR_NA;
308 return SR_OK;
309 case SR_CONF_OFFSET:
310 dvalue = g_variant_get_double(data);
311 chan->offset = dvalue;
312 ret = jds6600_set_offset(sdi, cg_idx);
313 if (ret != SR_OK)
314 return SR_ERR_NA;
315 return SR_OK;
316 case SR_CONF_DUTY_CYCLE:
317 dvalue = g_variant_get_double(data);
318 chan->dutycycle = dvalue;
319 ret = jds6600_set_dutycycle(sdi, cg_idx);
320 if (ret != SR_OK)
321 return SR_ERR_NA;
322 return SR_OK;
b1fa9aac 323 default:
18baeeed 324 return SR_ERR_NA;
b1fa9aac 325 }
b1fa9aac
GS
326}
327
328static int config_list(uint32_t key, GVariant **data,
329 const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
330{
18baeeed
GS
331 struct dev_context *devc;
332 struct devc_wave *waves;
333 double fspec[3];
334
335 if (!cg) {
336 switch (key) {
337 case SR_CONF_SCAN_OPTIONS:
338 case SR_CONF_DEVICE_OPTIONS:
339 return STD_CONFIG_LIST(key, data, sdi, cg,
340 scanopts, drvopts, devopts);
341 default:
342 return SR_ERR_NA;
343 }
344 }
b1fa9aac 345
18baeeed
GS
346 if (!sdi)
347 return SR_ERR_NA;
348 devc = sdi->priv;
349 if (!devc)
350 return SR_ERR_NA;
b1fa9aac 351 switch (key) {
18baeeed
GS
352 case SR_CONF_DEVICE_OPTIONS:
353 *data =std_gvar_array_u32(ARRAY_AND_SIZE(devopts_cg));
354 return SR_OK;
355 case SR_CONF_PATTERN_MODE:
356 waves = &devc->waveforms;
357 *data = std_gvar_array_str(waves->names, waves->names_count);
358 return SR_OK;
359 case SR_CONF_OUTPUT_FREQUENCY:
1711287e 360 /* Announce range as tuple of min, max, step. */
18baeeed
GS
361 fspec[0] = 0.01;
362 fspec[1] = devc->device.max_output_frequency;
363 fspec[2] = 0.01;
364 *data = std_gvar_min_max_step_array(fspec);
365 return SR_OK;
366 case SR_CONF_DUTY_CYCLE:
1711287e 367 /* Announce range as tuple of min, max, step. */
18baeeed
GS
368 fspec[0] = 0.0;
369 fspec[1] = 1.0;
370 fspec[2] = 0.001;
371 *data = std_gvar_min_max_step_array(fspec);
372 return SR_OK;
b1fa9aac
GS
373 default:
374 return SR_ERR_NA;
375 }
b1fa9aac
GS
376}
377
18baeeed 378static void clear_helper(struct dev_context *devc)
b1fa9aac 379{
18baeeed
GS
380 struct devc_wave *waves;
381
382 if (!devc)
383 return;
384
385 g_free(devc->device.serial_number);
386 waves = &devc->waveforms;
387 while (waves->names_count)
388 g_free((char *)waves->names[--waves->names_count]);
389 g_free(waves->names);
390 g_free(waves->fw_codes);
391 if (devc->quick_req)
392 g_string_free(devc->quick_req, TRUE);
b1fa9aac
GS
393}
394
18baeeed 395static int dev_clear(const struct sr_dev_driver *driver)
b1fa9aac 396{
18baeeed
GS
397 return std_dev_clear_with_callback(driver,
398 (std_dev_clear_callback)clear_helper);
b1fa9aac
GS
399}
400
401static struct sr_dev_driver juntek_jds6600_driver_info = {
402 .name = "juntek-jds6600",
403 .longname = "JUNTEK JDS6600",
404 .api_version = 1,
405 .init = std_init,
406 .cleanup = std_cleanup,
407 .scan = scan,
408 .dev_list = std_dev_list,
18baeeed 409 .dev_clear = dev_clear,
b1fa9aac
GS
410 .config_get = config_get,
411 .config_set = config_set,
412 .config_list = config_list,
18baeeed
GS
413 .dev_open = std_serial_dev_open,
414 .dev_close = std_serial_dev_close,
415 .dev_acquisition_start = std_dummy_dev_acquisition_start,
416 .dev_acquisition_stop = std_dummy_dev_acquisition_stop,
b1fa9aac
GS
417 .context = NULL,
418};
419SR_REGISTER_DEV_DRIVER(juntek_jds6600_driver_info);