]> sigrok.org Git - libsigrok.git/blame - src/hardware/juntek-jds6600/protocol.c
juntek-jds6600: implement device support, tested with Joy-IT JDS6600
[libsigrok.git] / src / hardware / juntek-jds6600 / protocol.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/*
21 * Juntek JDS6600 is a DDS signal generator.
22 * Often rebranded, goes by different names, among them Joy-IT JDS6600.
23 *
24 * This driver was built using Kristoff Bonne's knowledge as seen in his
25 * MIT licensed Python code for JDS6600 control. For details see the
26 * https://github.com/on1arf/jds6600_python repository.
27 *
28 * Supported features:
29 * - Model detection, which determines the upper output frequency limit
30 * (15..60MHz models exist).
31 * - Assumes exactly two channels. Other models were not seen out there.
32 * - Per channel configuration of: Waveform, output frequency, amplitude,
33 * offset, duty cycle.
34 * - Phase between channels is a global property and affects multiple
35 * channels at the same time (their relation to each other).
36 *
37 * TODO
38 * - Add support for the frequency measurement and/or the counter. This
39 * feature's availability may depend on or interact with the state of
40 * other generator channels. Needs consideration of constraints.
41 * - Add support for modulation (sweep, pulse, burst). Add support for
42 * other "modes"?
43 * - Add support for download/upload of arbitrary waveforms. This needs
44 * infrastructure in common libsigrok code as well as in applications.
45 * At the moment "blob transfer" (waveform upload/download) appears to
46 * not be supported.
47 * - Re-consider parameter value ranges. Frequency depends on the model.
48 * Amplitude range depends on the model and frequencies and interact
49 * with the offset offset configuration. Can be -20..+20, or -10..+10,
50 * or -5..+5 ranges. This implementation caps to the -20..+20 range.
51 * Many values are passed to the device and may result in capping or
52 * transformation there in the firwmare.
53 *
54 * Implementation details:
55 * - Communicates via USB CDC at 115200/8n1 (virtual COM port).
56 * - Requests are in text format. Start with a ':' colon, followed by a
57 * single letter instruction opcode, followed by a number which either
58 * addresses a parameter (think hardware register) or storage slot for
59 * an arbitrary waveform. Can be followed by an '=' equals sign and a
60 * value. Multiple values are comma separated. The line may end in a
61 * '.' period. Several end-of-line conventions are supported by the
62 * devices' firmware versions, LF and CR/LF are reported to work.
63 * - Responses also are in text format. Start with a ':' colon, followed
64 * by an instruction letter, followed by a number (a parameter index,
65 * or a waveform index), followed by '=' equal sign and one or more
66 * values. Optionally ending in a '.' period. And ending in the
67 * firmware's end-of-line. Read requests will have this format.
68 * Alternatively write requests may just respond with the ":ok"
69 * text phrase.
70 * - There are four instructions: 'r' to read and 'w' to write parameters
71 * (think hardware registers, optionaly multi-valued), 'a' to write and
72 * 'b' to read arbitrary waveform data (sequence of sample values).
73 * - Am not aware of a vendor's documentation for the protocol. Joy-IT
74 * provides the JT-JDS6600-Communication-protocol.pdf document which
75 * leaves a lot of questions. This sigrok driver implementation used
76 * a lot of https://github.com/on1arf/jds6600_python knowledge for
77 * the initial version (MIT licenced Python code by Kristoff Bonne).
78 * - The requests take effect when sent from application code. While
79 * the requests remain uneffective when typed in interactive terminal
80 * sessions. Though there are ":ok" responses, the action would not
81 * happen in the device. It's assumed to be a firmware implementation
82 * constraint that is essential to keep in mind.
83 * - The right hand side of write requests or read responses can carry
84 * any number of values, both numbers and text, integers and floats.
85 * Still some of the parameters (voltages, times, frequencies) come in
86 * interesting formats. A floating point "mantissa" and an integer code
87 * for scaling the value. Not an exponent, but some kind of index. In
88 * addition to an open coded "fixed point" style multiplier that is
89 * implied and essential, but doesn't show on the wire. Interpretation
90 * of responses and phrasing of values in requests is arbitrary, this
91 * "black magic" was found by local experimentation (reading back the
92 * values which were configured by local UI interaction).
93 */
94
95#include "config.h"
96
97#include <glib.h>
98#include <math.h>
99#include <string.h>
100
b1fa9aac
GS
101#include "protocol.h"
102
18baeeed
GS
103#define WITH_ARBWAVE_DOWNLOAD 0 /* Development HACK */
104
105/*
106 * The firmware's maximum response length. Seen when an arbitrary
107 * waveform gets retrieved. Carries 2048 samples in the 0..4095 range.
108 * Plus some decoration around that data.
109 * :b01=4095,4095,...,4095,<CRLF>
110 */
111#define MAX_RSP_LENGTH (8 + 2048 * 5)
112
113/* Times are in milliseconds. */
114#define DELAY_AFTER_WRITE 10
115#define DELAY_AFTER_FLASH 100
116#define TIMEOUT_READ_CHUNK 20
117#define TIMEOUT_IDENTIFY 200
118
119/* Instruction codes. Read/write parameters/waveforms. */
120#define INSN_WRITE_PARA 'w'
121#define INSN_READ_PARA 'r'
122#define INSN_WRITE_WAVE 'a'
123#define INSN_READ_WAVE 'b'
124
125/* Indices for "register access". */
126enum param_index {
127 IDX_DEVICE_TYPE = 0,
128 IDX_SERIAL_NUMBER = 1,
129 IDX_CHANNELS_ENABLE = 20,
130 IDX_WAVEFORM_CH1 = 21,
131 IDX_WAVEFORM_CH2 = 22,
132 IDX_FREQUENCY_CH1 = 23,
133 IDX_FREQUENCY_CH2 = 24,
134 IDX_AMPLITUDE_CH1 = 25,
135 IDX_AMPLITUDE_CH2 = 26,
136 IDX_OFFSET_CH1 = 27,
137 IDX_OFFSET_CH2 = 28,
138 IDX_DUTYCYCLE_CH1 = 29,
139 IDX_DUTYCYCLE_CH2 = 30,
140 IDX_PHASE_CHANNELS = 31,
141 IDX_ACTION = 32,
142 IDX_MODE = 33,
143 IDX_INPUT_COUPLING = 36,
144 IDX_MEASURE_GATE = 37,
145 IDX_MEASURE_MODE = 38,
146 IDX_COUNTER_RESET = 39,
147 IDX_SWEEP_STARTFREQ = 40,
148 IDX_SWEEP_ENDFREQ = 41,
149 IDX_SWEEP_TIME = 42,
150 IDX_SWEEP_DIRECTION = 43,
151 IDX_SWEEP_MODE = 44,
152 IDX_PULSE_WIDTH = 45,
153 IDX_PULSE_PERIOD = 46,
154 IDX_PULSE_OFFSET = 47,
155 IDX_PULSE_AMPLITUDE = 48,
156 IDX_BURST_COUNT = 49,
157 IDX_BURST_MODE = 50,
158 IDX_SYSTEM_SOUND = 51,
159 IDX_SYSTEM_BRIGHTNESS = 52,
160 IDX_SYSTEM_LANGUAGE = 53,
161 IDX_SYSTEM_SYNC = 54, /* "Tracking" channels? */
162 IDX_SYSTEM_ARBMAX = 55,
163 IDX_PROFILE_SAVE = 70,
164 IDX_PROFILE_LOAD = 71,
165 IDX_PROFILE_CLEAR = 72,
166 IDX_COUNTER_VALUE = 80,
167 IDX_MEAS_VALUE_FREQLOW = 81,
168 IDX_MEAS_VALUE_FREQHI = 82,
169 IDX_MEAS_VALUE_WIDTHHI = 83,
170 IDX_MEAS_VALUE_WIDTHLOW = 84,
171 IDX_MEAS_VALUE_PERIOD = 85,
172 IDX_MEAS_VALUE_DUTYCYCLE = 86,
173 IDX_MEAS_VALUE_U1 = 87,
174 IDX_MEAS_VALUE_U2 = 88,
175 IDX_MEAS_VALUE_U3 = 89,
176};
177
178/* Firmware's codes for waveform selection. */
179enum waveform_index_t {
180 /* 17 pre-defined waveforms. */
181 WAVE_SINE = 0,
182 WAVE_SQUARE = 1,
183 WAVE_PULSE = 2,
184 WAVE_TRIANGLE = 3,
185 WAVE_PARTIAL_SINE = 4,
186 WAVE_CMOS = 5,
187 WAVE_DC = 6,
188 WAVE_HALF_WAVE = 7,
189 WAVE_FULL_WAVE = 8,
190 WAVE_POS_LADDER = 9,
191 WAVE_NEG_LADDER = 10,
192 WAVE_NOISE = 11,
193 WAVE_EXP_RISE = 12,
194 WAVE_EXP_DECAY = 13,
195 WAVE_MULTI_TONE = 14,
196 WAVE_SINC = 15,
197 WAVE_LORENZ = 16,
198 WAVES_COUNT_BUILTIN,
199 /* Up to 60 arbitrary waveforms. */
200 WAVES_ARB_BASE = 100,
201 WAVE_ARB01 = WAVES_ARB_BASE + 1,
202 /* ... */
203 WAVE_ARB60 = WAVES_ARB_BASE + 60,
204 WAVES_PAST_LAST_ARB,
205};
206#define WAVES_COUNT_ARBITRARY (WAVES_PAST_LAST_ARB - WAVE_ARB01)
207
208static const char *waveform_names[] = {
209 [WAVE_SINE] = "sine",
210 [WAVE_SQUARE] = "square",
211 [WAVE_PULSE] = "pulse",
212 [WAVE_TRIANGLE] = "triangle",
213 [WAVE_PARTIAL_SINE] = "partial-sine",
214 [WAVE_CMOS] = "cmos",
215 [WAVE_DC] = "dc",
216 [WAVE_HALF_WAVE] = "half-wave",
217 [WAVE_FULL_WAVE] = "full-wave",
218 [WAVE_POS_LADDER] = "pos-ladder",
219 [WAVE_NEG_LADDER] = "neg-ladder",
220 [WAVE_NOISE] = "noise",
221 [WAVE_EXP_RISE] = "exp-rise",
222 [WAVE_EXP_DECAY] = "exp-decay",
223 [WAVE_MULTI_TONE] = "multi-tone",
224 [WAVE_SINC] = "sinc",
225 [WAVE_LORENZ] = "lorenz",
226};
227#define WAVEFORM_ARB_NAME_FMT "arb-%02zu"
228
229/*
230 * Writes a text line to the serial port. Normalizes end-of-line
231 * including trailing period.
232 */
233static int serial_send_textline(const struct sr_dev_inst *sdi,
234 GString *s, unsigned int delay_ms)
235{
236 struct sr_serial_dev_inst *conn;
237 const char *rdptr;
238 size_t padlen, rdlen, wrlen;
239 int ret;
240
241 if (!sdi)
242 return SR_ERR_ARG;
243 conn = sdi->conn;
244 if (!conn)
245 return SR_ERR_ARG;
246 if (!s)
247 return SR_ERR_ARG;
248
249 /* Trim surrounding whitespace. Normalize end-of-line. */
250 padlen = 4;
251 while (padlen--)
252 g_string_append_c(s, '\0');
253 rdptr = sr_text_trim_spaces(s->str);
254 rdlen = strlen(rdptr);
255 if (rdlen && rdptr[rdlen - 1] == '.')
256 rdlen--;
257 g_string_set_size(s, rdlen);
258 g_string_append_c(s, '.');
259 sr_spew("serial TX data: --> %s", rdptr);
260 g_string_append_c(s, '\r');
261 g_string_append_c(s, '\n');
262 rdlen = strlen(rdptr);
263
264 /* Handle chunked writes, check for transmission errors. */
265 while (rdlen) {
266 ret = serial_write_blocking(conn, rdptr, rdlen, 0);
267 if (ret < 0)
268 return SR_ERR_IO;
269 wrlen = (size_t)ret;
270 if (wrlen > rdlen)
271 wrlen = rdlen;
272 rdptr += wrlen;
273 rdlen -= wrlen;
274 }
275
276 if (delay_ms)
277 g_usleep(delay_ms * 1000);
278
279 return SR_OK;
280}
281
282/*
283 * Reads a text line from the serial port. Assumes that only a single
284 * response text line is in flight (does not handle the case of more
285 * receive data following after the first EOL). Transparently deals
286 * with trailing period and end-of-line, so callers need not bother.
287 *
288 * Checks plausibility when the caller specifies conditions to check.
289 * Optionally returns references (and lengths) to the response's RHS.
290 * That's fine because data resides in a caller provided buffer.
291 */
292static int serial_recv_textline(const struct sr_dev_inst *sdi,
293 GString *s, unsigned int delay_ms, unsigned int timeout_ms,
294 gboolean *is_ok, char wants_insn, size_t wants_index,
295 char **rhs_start, size_t *rhs_length)
296{
297 struct sr_serial_dev_inst *ser;
298 char *rdptr;
299 size_t rdlen, got;
300 int ret;
301 guint64 now_us, deadline_us;
302 gboolean has_timedout;
303 char *eol_pos, *endptr;
304 char got_insn;
305 unsigned long got_index;
306
307 if (is_ok)
308 *is_ok = FALSE;
309 if (rhs_start)
310 *rhs_start = NULL;
311 if (rhs_length)
312 *rhs_length = 0;
313
314 if (!sdi)
315 return SR_ERR_ARG;
316 ser = sdi->conn;
317 if (!ser)
318 return SR_ERR_ARG;
319
320 g_string_set_size(s, MAX_RSP_LENGTH);
321 g_string_truncate(s, 0);
322
323 /* Arrange for overall receive timeout when caller specified. */
324 now_us = deadline_us = 0;
325 if (timeout_ms) {
326 now_us = g_get_monotonic_time();
327 deadline_us = now_us;
328 deadline_us += timeout_ms * 1000;
329 }
330
331 rdptr = s->str;
332 rdlen = s->allocated_len - 1 - s->len;
333 while (rdlen) {
334 /* Get another chunk of receive data. Check for EOL. */
335 ret = serial_read_blocking(ser, rdptr, rdlen, delay_ms);
336 if (ret < 0)
337 return SR_ERR_IO;
338 got = (size_t)ret;
339 if (got > rdlen)
340 got = rdlen;
341 rdptr[got] = '\0';
342 eol_pos = strchr(rdptr, '\n');
343 rdptr += got;
344 rdlen -= got;
345 /* Check timeout expiration upon empty reception. */
346 has_timedout = FALSE;
347 if (timeout_ms && !got) {
348 now_us = g_get_monotonic_time();
349 if (now_us >= deadline_us)
350 has_timedout = TRUE;
351 }
352 if (!eol_pos) {
353 if (has_timedout)
354 break;
355 continue;
356 }
357
358 /* Normalize the received text line. */
359 *eol_pos++ = '\0';
360 rdptr = s->str;
361 (void)sr_text_trim_spaces(rdptr);
362 rdlen = strlen(rdptr);
363 sr_spew("serial RX data: <-- %s", rdptr);
364 if (rdlen && rdptr[rdlen - 1] == '.')
365 rdptr[--rdlen] = '\0';
366
367 /* Check conditions as requested by the caller. */
368 if (is_ok || wants_insn || rhs_start) {
369 if (*rdptr != ':') {
370 sr_dbg("serial read, colon missing");
371 return SR_ERR_DATA;
372 }
373 rdptr++;
374 rdlen--;
375 }
376 /*
377 * The check for 'ok' is terminal. Does not combine with
378 * responses which carry payload data on their RHS.
379 */
380 if (is_ok) {
381 *is_ok = strcmp(rdptr, "ok") == 0;
382 sr_dbg("serial read, 'ok' check %d", *is_ok);
383 return *is_ok ? SR_OK : SR_ERR_DATA;
384 }
385 /*
386 * Conditional strict checks for caller's expected fields.
387 * Unconditional weaker checks for general structure.
388 */
389 if (wants_insn && *rdptr != wants_insn) {
390 sr_dbg("serial read, unexpected insn");
391 return SR_ERR_DATA;
392 }
393 got_insn = *rdptr++;
394 switch (got_insn) {
395 case INSN_WRITE_PARA:
396 case INSN_READ_PARA:
397 case INSN_WRITE_WAVE:
398 case INSN_READ_WAVE:
399 /* EMPTY */
400 break;
401 default:
402 sr_dbg("serial read, unknown insn %c", got_insn);
403 return SR_ERR_DATA;
404 }
405 endptr = NULL;
406 ret = sr_atoul_base(rdptr, &got_index, &endptr, 10);
407 if (ret != SR_OK || !endptr)
408 return SR_ERR_DATA;
409 if (wants_index && got_index != wants_index) {
410 sr_dbg("serial read, unexpected index %zu", got_index);
411 return SR_ERR_DATA;
412 }
413 rdptr = endptr;
414 if (rhs_start || rhs_length) {
415 if (*rdptr != '=') {
416 sr_dbg("serial read, equals sign missing");
417 return SR_ERR_DATA;
418 }
419 }
420 if (*rdptr)
421 rdptr++;
422
423 /* Response is considered plausible here. */
424 if (rhs_start)
425 *rhs_start = rdptr;
426 if (rhs_length)
427 *rhs_length = strlen(rdptr);
428 return SR_OK;
429 }
430
431 sr_dbg("serial read, no EOL seen");
432 return SR_ERR_DATA;
433}
434
435/* Formatting helpers for request construction. */
436
437static void append_insn_read_para(GString *s, char insn, size_t idx)
438{
439 g_string_append_printf(s, ":%c%02zu=0", insn, idx);
440}
441
442static void append_insn_write_para_va(GString *s, char insn, size_t idx,
443 const char *fmt, va_list args) ATTR_FMT_PRINTF(4, 0);
444static void append_insn_write_para_va(GString *s, char insn, size_t idx,
445 const char *fmt, va_list args)
446{
447 g_string_append_printf(s, ":%c%02zu=", insn, idx);
448 g_string_append_vprintf(s, fmt, args);
449}
450
451static void append_insn_write_para_dots(GString *s, char insn, size_t idx,
452 const char *fmt, ...) ATTR_FMT_PRINTF(4, 5);
453static void append_insn_write_para_dots(GString *s, char insn, size_t idx,
454 const char *fmt, ...)
455{
456 va_list args;
457
458 va_start(args, fmt);
459 append_insn_write_para_va(s, insn, idx, fmt, args);
460 va_end(args);
461}
462
463/*
464 * Turn comma separators into whitespace. Simplifies the interpretation
465 * of multi-value response payloads. Also replaces any trailing period
466 * in case callers kept one in the receive buffer.
467 */
468static void replace_separators(char *s)
469{
470
471 while (s && *s) {
472 if (s[0] == ',') {
473 *s++ = ' ';
474 continue;
475 }
476 if (s[0] == '.' && s[1] == '\0') {
477 *s++ = ' ';
478 continue;
479 }
480 s++;
481 }
482}
483
484/*
485 * Convenience to interpret responses' values. Also concentrates the
486 * involved magic and simplifies diagnostics. It's essential to apply
487 * implicit multipliers, and to properly combine multiple fields into
488 * the resulting parameter's value (think scaling and offsetting).
489 */
490
491static const double scales_freq[] = {
492 1, 1, 1, 1e-3, 1e-6,
493};
494
495static int parse_freq_text(char *s, double *value)
496{
497 char *word;
498 int ret;
499 double dvalue;
500 unsigned long scale;
501
502 replace_separators(s);
503
504 /* First word is a mantissa, in centi-Hertz. :-O */
505 word = sr_text_next_word(s, &s);
506 ret = sr_atod(word, &dvalue);
507 if (ret != SR_OK)
508 return ret;
509
510 /* Next word is an encoded scaling factor. */
511 word = sr_text_next_word(s, &s);
512 ret = sr_atoul_base(word, &scale, NULL, 10);
513 if (ret != SR_OK)
514 return ret;
515 sr_spew("parse freq, mant %lf, scale %ld", dvalue, scale);
516 if (scale >= ARRAY_SIZE(scales_freq))
517 return SR_ERR_DATA;
518
519 /* Do scale the mantissa's value. */
520 dvalue /= 100.0;
521 dvalue /= scales_freq[scale];
522 sr_spew("parse freq, value %lf", dvalue);
523
524 if (value)
525 *value = dvalue;
526 return SR_OK;
527}
528
529static int parse_volt_text(char *s, double *value)
530{
531 int ret;
532 double dvalue;
533
534 /* Single value, in units of mV. */
535 ret = sr_atod(s, &dvalue);
536 if (ret != SR_OK)
537 return ret;
538 sr_spew("parse volt, mant %lf", dvalue);
539 dvalue /= 1000.0;
540 sr_spew("parse volt, value %lf", dvalue);
541
542 if (value)
543 *value = dvalue;
544 return SR_OK;
545}
546
547static int parse_bias_text(char *s, double *value)
548{
549 int ret;
550 double dvalue;
551
552 /*
553 * Single value, in units of 10mV with a 10V offset. Capped to
554 * the +9.99V..-9.99V range. The Joy-IT PDF is a little weird
555 * suggesting that ":w27=9999." translates to 9.99 volts.
556 */
557 ret = sr_atod(s, &dvalue);
558 if (ret != SR_OK)
559 return ret;
560 sr_spew("parse bias, mant %lf", dvalue);
561 dvalue /= 100.0;
562 dvalue -= 10.0;
563 if (dvalue >= 9.99)
564 dvalue = 9.99;
565 if (dvalue <= -9.99)
566 dvalue = -9.99;
567 sr_spew("parse bias, value %lf", dvalue);
568
569 if (value)
570 *value = dvalue;
571 return SR_OK;
572}
573
574static int parse_duty_text(char *s, double *value)
575{
576 int ret;
577 double dvalue;
578
579 /*
580 * Single value, in units of 0.1% (permille).
581 * Scale to the 0.0..1.0 range.
582 */
583 ret = sr_atod(s, &dvalue);
584 if (ret != SR_OK)
585 return ret;
586 sr_spew("parse duty, mant %lf", dvalue);
587 dvalue /= 1000.0;
588 sr_spew("parse duty, value %lf", dvalue);
589
590 if (value)
591 *value = dvalue;
592 return SR_OK;
593}
594
595static int parse_phase_text(char *s, double *value)
596{
597 int ret;
598 double dvalue;
599
600 /* Single value, in units of deci-degrees. */
601 ret = sr_atod(s, &dvalue);
602 if (ret != SR_OK)
603 return ret;
604 sr_spew("parse phase, mant %lf", dvalue);
605 dvalue /= 10.0;
606 sr_spew("parse phase, value %lf", dvalue);
607
608 if (value)
609 *value = dvalue;
610 return SR_OK;
611}
612
613/*
614 * Convenience to generate request presentations. Also concentrates the
615 * involved magic and simplifies diagnostics. It's essential to apply
616 * implicit multipliers, and to properly create all request fields that
617 * communicate a value to the device's firmware (think scale and offset).
618 */
619
620static void write_freq_text(GString *s, double freq)
621{
622 unsigned long scale_idx;
623 const char *text_pos;
624
625 sr_spew("write freq, value %lf", freq);
626 text_pos = &s->str[s->len];
627
628 /*
629 * First word is mantissa in centi-Hertz. Second word is a
630 * scaling factor code. Keep scaling simple, always scale
631 * by a factor of 1.0.
632 */
633 scale_idx = 0;
634 freq *= scales_freq[scale_idx];
635 freq *= 100.0;
636
637 g_string_append_printf(s, "%.0lf,%lu", freq, scale_idx);
638 sr_spew("write freq, text %s", text_pos);
639}
640
641static void write_volt_text(GString *s, double volt)
642{
643 const char *text_pos;
644
645 sr_spew("write volt, value %lf", volt);
646 text_pos = &s->str[s->len];
647
648 /*
649 * Single value in units of 1mV.
650 * Limit input values to the 0..+20 range. This writer is only
651 * used by the amplitude setter.
652 */
653 if (volt > 20.0)
654 volt = 20.0;
655 if (volt < 0.0)
656 volt = 0.0;
657 volt *= 1000.0;
658 g_string_append_printf(s, "%.0lf", volt);
659 sr_spew("write volt, text %s", text_pos);
660}
661
662static void write_bias_text(GString *s, double volt)
663{
664 const char *text_pos;
665
666 sr_spew("write bias, value %lf", volt);
667 text_pos = &s->str[s->len];
668
669 /*
670 * Single value in units of 10mV with a 10V offset. Capped to
671 * the +9.99..-9.99 range.
672 */
673 if (volt > 9.99)
674 volt = 9.99;
675 if (volt < -9.99)
676 volt = -9.99;
677 volt += 10.0;
678 volt *= 100.0;
679
680 g_string_append_printf(s, "%.0lf", volt);
681 sr_spew("write bias, text %s", text_pos);
682}
683
684static void write_duty_text(GString *s, double duty)
685{
686 const char *text_pos;
687
688 sr_spew("write duty, value %lf", duty);
689 text_pos = &s->str[s->len];
690
691 /*
692 * Single value in units of 0.1% (permille). Capped to the
693 * 0.0..1.0 range.
694 */
695 if (duty < 0.0)
696 duty = 0.0;
697 if (duty > 1.0)
698 duty = 1.0;
699 duty *= 1000.0;
700
701 g_string_append_printf(s, "%.0lf", duty);
702 sr_spew("write duty, text %s", text_pos);
703}
704
705static void write_phase_text(GString *s, double phase)
706{
707 const char *text_pos;
708
709 sr_spew("write phase, value %lf", phase);
710 text_pos = &s->str[s->len];
711
712 /*
713 * Single value in units of deci-degrees.
714 * Kept to the 0..360 range by means of a modulo operation.
715 */
716 phase = fmod(phase, 360.0);
717 phase *= 10.0;
718
719 g_string_append_printf(s, "%.0lf", phase);
720 sr_spew("write phase, text %s", text_pos);
721}
722
723/*
724 * Convenience communication wrapper. Re-uses a buffer in devc, which
725 * simplifies resource handling in error paths. Sends a parameter-less
726 * read-request. Then receives a response which can carry values.
727 */
728static int quick_send_read_then_recv(const struct sr_dev_inst *sdi,
729 char insn, size_t idx,
730 unsigned int read_timeout_ms,
731 char **rhs_start, size_t *rhs_length)
732{
733 struct dev_context *devc;
734 GString *s;
735 int ret;
736
737 if (!sdi)
738 return SR_ERR_ARG;
739 devc = sdi->priv;
740 if (!devc)
741 return SR_ERR_ARG;
742 if (!devc->quick_req)
743 devc->quick_req = g_string_sized_new(MAX_RSP_LENGTH);
744 s = devc->quick_req;
745
746 g_string_truncate(s, 0);
747 append_insn_read_para(s, insn, idx);
748 ret = serial_send_textline(sdi, s, DELAY_AFTER_WRITE);
749 if (ret != SR_OK)
750 return ret;
751
752 ret = serial_recv_textline(sdi, s,
753 TIMEOUT_READ_CHUNK, read_timeout_ms,
754 NULL, insn, idx, rhs_start, rhs_length);
755 if (ret != SR_OK)
756 return ret;
757
758 return SR_OK;
759}
760
761/*
762 * Convenience communication wrapper, re-uses a buffer in devc. Sends a
763 * write-request with parameters. Then receives an "ok" style response.
764 * Had to put the request details after the response related parameters
765 * because of the va_list API.
766 */
767static int quick_send_write_then_recv_ok(const struct sr_dev_inst *sdi,
768 unsigned int read_timeout_ms, gboolean *is_ok,
769 char insn, size_t idx, const char *fmt, ...) ATTR_FMT_PRINTF(6, 7);
770static int quick_send_write_then_recv_ok(const struct sr_dev_inst *sdi,
771 unsigned int read_timeout_ms, gboolean *is_ok,
772 char insn, size_t idx, const char *fmt, ...)
773{
774 struct dev_context *devc;
775 GString *s;
776 va_list args;
777 int ret;
778 gboolean ok;
779
780 if (!sdi)
781 return SR_ERR_ARG;
782 devc = sdi->priv;
783 if (!devc)
784 return SR_ERR_ARG;
785 if (!devc->quick_req)
786 devc->quick_req = g_string_sized_new(MAX_RSP_LENGTH);
787 s = devc->quick_req;
788
789 g_string_truncate(s, 0);
790 va_start(args, fmt);
791 append_insn_write_para_va(s, insn, idx, fmt, args);
792 va_end(args);
793 ret = serial_send_textline(sdi, s, DELAY_AFTER_WRITE);
794 if (ret != SR_OK)
795 return ret;
796
797 ret = serial_recv_textline(sdi, s,
798 TIMEOUT_READ_CHUNK, read_timeout_ms,
799 &ok, '\0', 0, NULL, NULL);
800 if (is_ok)
801 *is_ok = ok;
802 if (ret != SR_OK)
803 return ret;
804
805 return SR_OK;
806}
807
808/*
809 * High level getters/setters for device properties.
810 * To be used by the api.c config get/set infrastructure.
811 */
812
813SR_PRIV int jds6600_get_chans_enable(const struct sr_dev_inst *sdi)
814{
815 struct dev_context *devc;
816 int ret;
817 char *rdptr, *word, *endptr;
818 struct devc_dev *device;
819 struct devc_chan *chans;
820 size_t idx;
821 unsigned long on;
822
823 devc = sdi->priv;
824 if (!devc)
825 return SR_ERR_ARG;
826
827 /* Transmit the request, receive the response. */
828 ret = quick_send_read_then_recv(sdi,
829 INSN_READ_PARA, IDX_CHANNELS_ENABLE,
830 0, &rdptr, NULL);
831 if (ret != SR_OK)
832 return ret;
833 sr_dbg("get enabled, response text: %s", rdptr);
834
835 /* Interpret the response (multiple values, boolean). */
836 replace_separators(rdptr);
837 device = &devc->device;
838 chans = devc->channel_config;
839 for (idx = 0; idx < device->channel_count_gen; idx++) {
840 word = sr_text_next_word(rdptr, &rdptr);
841 if (!word || !*word)
842 return SR_ERR_DATA;
843 endptr = NULL;
844 ret = sr_atoul_base(word, &on, &endptr, 10);
845 if (ret != SR_OK || !endptr || *endptr)
846 return SR_ERR_DATA;
847 chans[idx].enabled = on;
848 }
849
850 return SR_OK;
851}
852
853SR_PRIV int jds6600_get_waveform(const struct sr_dev_inst *sdi, size_t ch_idx)
854{
855 struct dev_context *devc;
856 int ret;
857 char *rdptr, *endptr;
858 struct devc_wave *waves;
859 struct devc_chan *chan;
860 unsigned long code;
861 size_t idx;
862
863 if (!sdi)
864 return SR_ERR_ARG;
865 devc = sdi->priv;
866 if (!devc)
867 return SR_ERR_ARG;
868 waves = &devc->waveforms;
869 if (ch_idx >= ARRAY_SIZE(devc->channel_config))
870 return SR_ERR_ARG;
871 chan = &devc->channel_config[ch_idx];
872
873 /* Transmit the request, receive the response. */
874 ret = quick_send_read_then_recv(sdi,
875 INSN_READ_PARA, IDX_WAVEFORM_CH1 + ch_idx,
876 0, &rdptr, NULL);
877 if (ret != SR_OK)
878 return ret;
879 sr_dbg("get waveform, response text: %s", rdptr);
880
881 /*
882 * Interpret the response (integer value, waveform code).
883 * Lookup the firmware's code for that waveform in the
884 * list of user perceivable names for waveforms.
885 */
886 endptr = NULL;
887 ret = sr_atoul_base(rdptr, &code, &endptr, 10);
888 if (ret != SR_OK)
889 return SR_ERR_DATA;
890 for (idx = 0; idx < waves->names_count; idx++) {
891 if (code != waves->fw_codes[idx])
892 continue;
893 chan->waveform_code = code;
894 chan->waveform_index = idx;
895 sr_dbg("get waveform, code %lu, idx %zu, name %s",
896 code, idx, waves->names[idx]);
897 return SR_OK;
898 }
899
900 return SR_ERR_DATA;
901}
902
903#if WITH_ARBWAVE_DOWNLOAD
904/*
905 * Development HACK. Get a waveform from the device. Uncertain where to
906 * dump it though. Have yet to identify a sigrok API for waveforms.
907 */
908static int jds6600_get_arb_waveform(const struct sr_dev_inst *sdi, size_t idx)
909{
910 struct dev_context *devc;
911 struct devc_wave *waves;
912 int ret;
913 char *rdptr, *word, *endptr;
914 size_t sample_count;
915 unsigned long value;
916
917 if (!sdi)
918 return SR_ERR_ARG;
919 devc = sdi->priv;
920 if (!devc)
921 return SR_ERR_ARG;
922 waves = &devc->waveforms;
923
924 if (idx >= waves->arbitrary_count)
925 return SR_ERR_ARG;
926
927 /* Transmit the request, receive the response. */
928 ret = quick_send_read_then_recv(sdi,
929 INSN_READ_WAVE, idx,
930 0, &rdptr, NULL);
931 if (ret != SR_OK)
932 return ret;
933 sr_dbg("get arb wave, response text: %s", rdptr);
934
935 /* Extract the sequence of samples for the waveform. */
936 replace_separators(rdptr);
937 sample_count = 0;
938 while (rdptr && *rdptr) {
939 word = sr_text_next_word(rdptr, &rdptr);
940 if (!word)
941 break;
942 endptr = NULL;
943 ret = sr_atoul_base(word, &value, &endptr, 10);
944 if (ret != SR_OK || !endptr || *endptr) {
945 sr_dbg("get arb wave, conv error: %s", word);
946 return SR_ERR_DATA;
947 }
948 sample_count++;
949 }
950 sr_dbg("get arb wave, samples count: %zu", sample_count);
951
952 return SR_OK;
953}
954#endif
955
956SR_PRIV int jds6600_get_frequency(const struct sr_dev_inst *sdi, size_t ch_idx)
957{
958 struct dev_context *devc;
959 struct devc_chan *chan;
960 int ret;
961 char *rdptr;
962 double freq;
963
964 devc = sdi->priv;
965 if (!devc)
966 return SR_ERR_ARG;
967 if (ch_idx >= ARRAY_SIZE(devc->channel_config))
968 return SR_ERR_ARG;
969 chan = &devc->channel_config[ch_idx];
970
971 /* Transmit the request, receive the response. */
972 ret = quick_send_read_then_recv(sdi,
973 INSN_READ_PARA, IDX_FREQUENCY_CH1 + ch_idx,
974 0, &rdptr, NULL);
975 if (ret != SR_OK)
976 return ret;
977 sr_dbg("get frequency, response text: %s", rdptr);
978
979 /* Interpret the response (value and scale, frequency). */
980 ret = parse_freq_text(rdptr, &freq);
981 if (ret != SR_OK)
982 return SR_ERR_DATA;
983 sr_dbg("get frequency, value %lf", freq);
984 chan->output_frequency = freq;
985 return SR_OK;
986}
987
988SR_PRIV int jds6600_get_amplitude(const struct sr_dev_inst *sdi, size_t ch_idx)
989{
990 struct dev_context *devc;
991 struct devc_chan *chan;
992 int ret;
993 char *rdptr;
994 double amp;
995
996 devc = sdi->priv;
997 if (!devc)
998 return SR_ERR_ARG;
999 if (ch_idx >= ARRAY_SIZE(devc->channel_config))
1000 return SR_ERR_ARG;
1001 chan = &devc->channel_config[ch_idx];
1002
1003 /* Transmit the request, receive the response. */
1004 ret = quick_send_read_then_recv(sdi,
1005 INSN_READ_PARA, IDX_AMPLITUDE_CH1 + ch_idx,
1006 0, &rdptr, NULL);
1007 if (ret != SR_OK)
1008 return ret;
1009 sr_dbg("get amplitude, response text: %s", rdptr);
1010
1011 /* Interpret the response (single value, a voltage). */
1012 ret = parse_volt_text(rdptr, &amp);
1013 if (ret != SR_OK)
1014 return SR_ERR_DATA;
1015 sr_dbg("get amplitude, value %lf", amp);
1016 chan->amplitude = amp;
1017 return SR_OK;
1018}
1019
1020SR_PRIV int jds6600_get_offset(const struct sr_dev_inst *sdi, size_t ch_idx)
1021{
1022 struct dev_context *devc;
1023 struct devc_chan *chan;
1024 int ret;
1025 char *rdptr;
1026 double off;
1027
1028 devc = sdi->priv;
1029 if (!devc)
1030 return SR_ERR_ARG;
1031 if (ch_idx >= ARRAY_SIZE(devc->channel_config))
1032 return SR_ERR_ARG;
1033 chan = &devc->channel_config[ch_idx];
1034
1035 /* Transmit the request, receive the response. */
1036 ret = quick_send_read_then_recv(sdi,
1037 INSN_READ_PARA, IDX_OFFSET_CH1 + ch_idx,
1038 0, &rdptr, NULL);
1039 if (ret != SR_OK)
1040 return ret;
1041 sr_dbg("get offset, response text: %s", rdptr);
1042
1043 /* Interpret the response (single value, an offset). */
1044 ret = parse_bias_text(rdptr, &off);
1045 if (ret != SR_OK)
1046 return SR_ERR_DATA;
1047 sr_dbg("get offset, value %lf", off);
1048 chan->offset = off;
1049 return SR_OK;
1050}
1051
1052SR_PRIV int jds6600_get_dutycycle(const struct sr_dev_inst *sdi, size_t ch_idx)
b1fa9aac 1053{
b1fa9aac 1054 struct dev_context *devc;
18baeeed
GS
1055 struct devc_chan *chan;
1056 int ret;
1057 char *rdptr;
1058 double duty;
b1fa9aac 1059
18baeeed
GS
1060 devc = sdi->priv;
1061 if (!devc)
1062 return SR_ERR_ARG;
1063 if (ch_idx >= ARRAY_SIZE(devc->channel_config))
1064 return SR_ERR_ARG;
1065 chan = &devc->channel_config[ch_idx];
1066
1067 /* Transmit the request, receive the response. */
1068 ret = quick_send_read_then_recv(sdi,
1069 INSN_READ_PARA, IDX_DUTYCYCLE_CH1 + ch_idx,
1070 0, &rdptr, NULL);
1071 if (ret != SR_OK)
1072 return ret;
1073 sr_dbg("get duty cycle, response text: %s", rdptr);
1074
1075 /* Interpret the response (single value, a percentage). */
1076 ret = parse_duty_text(rdptr, &duty);
1077 if (ret != SR_OK)
1078 return SR_ERR_DATA;
1079 sr_dbg("get duty cycle, value %lf", duty);
1080 chan->dutycycle = duty;
1081 return SR_OK;
1082}
1083
1084SR_PRIV int jds6600_get_phase_chans(const struct sr_dev_inst *sdi)
1085{
1086 struct dev_context *devc;
1087 int ret;
1088 char *rdptr;
1089 double phase;
1090
1091 devc = sdi->priv;
1092 if (!devc)
1093 return SR_ERR_ARG;
1094
1095 /* Transmit the request, receive the response. */
1096 ret = quick_send_read_then_recv(sdi,
1097 INSN_READ_PARA, IDX_PHASE_CHANNELS,
1098 0, &rdptr, NULL);
1099 if (ret != SR_OK)
1100 return ret;
1101 sr_dbg("get phase, response text: %s", rdptr);
1102
1103 /* Interpret the response (single value, an angle). */
1104 ret = parse_phase_text(rdptr, &phase);
1105 if (ret != SR_OK)
1106 return SR_ERR_DATA;
1107 sr_dbg("get phase, value %lf", phase);
1108 devc->channels_phase = phase;
1109 return SR_OK;
1110}
1111
1112SR_PRIV int jds6600_set_chans_enable(const struct sr_dev_inst *sdi)
1113{
1114 struct dev_context *devc;
1115 struct devc_chan *chans;
1116 GString *en_text;
1117 size_t idx;
1118 int ret;
b1fa9aac 1119
b1fa9aac 1120 if (!sdi)
18baeeed
GS
1121 return SR_ERR_ARG;
1122 devc = sdi->priv;
1123 if (!devc)
1124 return SR_ERR_ARG;
1125
1126 /* Transmit the request, receive an "ok" style response. */
1127 chans = devc->channel_config;
1128 en_text = g_string_sized_new(20);
1129 for (idx = 0; idx < devc->device.channel_count_gen; idx++) {
1130 if (en_text->len)
1131 g_string_append_c(en_text, ',');
1132 g_string_append_c(en_text, chans[idx].enabled ? '1' : '0');
1133 }
1134 sr_dbg("set enabled, request text: %s", en_text->str);
1135 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1136 INSN_WRITE_PARA, IDX_CHANNELS_ENABLE, "%s", en_text->str);
1137 g_string_free(en_text, 20);
1138 if (ret != SR_OK)
1139 return ret;
1140
1141 return SR_OK;
1142}
b1fa9aac 1143
18baeeed
GS
1144SR_PRIV int jds6600_set_waveform(const struct sr_dev_inst *sdi, size_t ch_idx)
1145{
1146 struct dev_context *devc;
1147 struct devc_chan *chan;
1148 int ret;
1149
1150 if (!sdi)
1151 return SR_ERR_ARG;
b1fa9aac
GS
1152 devc = sdi->priv;
1153 if (!devc)
18baeeed
GS
1154 return SR_ERR_ARG;
1155 if (ch_idx >= devc->device.channel_count_gen)
1156 return SR_ERR_ARG;
1157 chan = &devc->channel_config[ch_idx];
1158
1159 /* Transmit the request, receive an "ok" style response. */
1160 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1161 INSN_WRITE_PARA, IDX_WAVEFORM_CH1 + ch_idx,
1162 "%" PRIu32, chan->waveform_code);
1163 if (ret != SR_OK)
1164 return ret;
1165
1166 return SR_OK;
1167}
1168
1169#if WITH_ARBWAVE_DOWNLOAD
1170/*
1171 * Development HACK. Send a waveform to the device. Uncertain where
1172 * to get it from though. Just generate some stupid pattern that's
1173 * seen on the LCD later.
1174 *
1175 * Local experiments suggest that writing another waveform after having
1176 * written one earlier results in the next waveform to become mangled.
1177 * It appears to start with an all-bits-set pattern for a remarkable
1178 * number of samples, before the actually written pattern is seen. Some
1179 * delay after reception of the ":ok" response may be required to avoid
1180 * this corruption.
1181 */
b1fa9aac 1182
18baeeed
GS
1183/* Stupid creation of one sample value. Gets waveform index and sample count. */
1184static uint16_t make_sample(size_t wave, size_t curr, size_t total)
1185{
1186 uint16_t max_value, high_value, low_value;
1187 size_t ival, high_width;
1188 gboolean is_high;
1189
1190 /* Get the waveform's amplitudes. */
1191 max_value = 4096;
1192 high_value = max_value / (wave + 3);
1193 high_value = max_value - high_value;
1194 low_value = max_value - high_value;
1195
1196 /* Get pulses' total interval, high and low half-periods. */
1197 ival = (total - 10) / wave;
1198 high_width = ival / 2;
1199
1200 /* Check location in the current period. */
1201 curr %= ival;
1202 is_high = curr <= high_width;
1203 return is_high ? high_value : low_value;
1204}
1205
1206/* Creation and download of the sequence of samples. */
1207static int jds6600_set_arb_waveform(const struct sr_dev_inst *sdi, size_t idx)
1208{
1209 struct dev_context *devc;
1210 struct devc_wave *waves;
1211 GString *wave_text;
1212 size_t samples_total, samples_curr;
1213 uint16_t value;
1214 gboolean ok;
1215 int ret;
1216
1217 if (!sdi)
1218 return SR_ERR_ARG;
1219 devc = sdi->priv;
1220 if (!devc)
1221 return SR_ERR_ARG;
1222 waves = &devc->waveforms;
1223
1224 if (idx >= waves->arbitrary_count)
1225 return SR_ERR_ARG;
1226
1227 /* Construct a pattern that depends on the waveform index. */
1228 wave_text = g_string_sized_new(MAX_RSP_LENGTH);
1229 samples_total = 2048;
1230 samples_curr = 0;
1231 for (samples_curr = 0; samples_curr < samples_total; samples_curr++) {
1232 value = make_sample(idx, samples_curr, samples_total);
1233 if (samples_curr)
1234 g_string_append_c(wave_text, ',');
1235 g_string_append_printf(wave_text, "%" PRIu16, value);
b1fa9aac 1236 }
18baeeed
GS
1237 sr_dbg("set arb wave, request text: %s", wave_text->str);
1238
1239 /* Transmit the request, receive an "ok" style response. */
1240 ret = quick_send_write_then_recv_ok(sdi, 0, &ok,
1241 INSN_WRITE_WAVE, idx, "%s", wave_text->str);
1242 if (ret != SR_OK)
1243 return ret;
1244 sr_dbg("set arb wave, response ok: %d", ok);
1245
1246 if (DELAY_AFTER_FLASH)
1247 g_usleep(DELAY_AFTER_FLASH * 1000);
1248
1249 return SR_OK;
1250}
1251#endif
1252
1253SR_PRIV int jds6600_set_frequency(const struct sr_dev_inst *sdi, size_t ch_idx)
1254{
1255 struct dev_context *devc;
1256 struct devc_chan *chan;
1257 double freq;
1258 GString *freq_text;
1259 int ret;
1260
1261 if (!sdi)
1262 return SR_ERR_ARG;
1263 devc = sdi->priv;
1264 if (!devc)
1265 return SR_ERR_ARG;
1266 if (ch_idx >= devc->device.channel_count_gen)
1267 return SR_ERR_ARG;
1268 chan = &devc->channel_config[ch_idx];
1269
1270 /* Limit input values to the range supported by the model. */
1271 freq = chan->output_frequency;
1272 if (freq < 0.01)
1273 freq = 0.01;
1274 if (freq > devc->device.max_output_frequency)
1275 freq = devc->device.max_output_frequency;
1276
1277 /* Transmit the request, receive an "ok" style response. */
1278 freq_text = g_string_sized_new(32);
1279 write_freq_text(freq_text, freq);
1280 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1281 INSN_WRITE_PARA, IDX_FREQUENCY_CH1 + ch_idx,
1282 "%s", freq_text->str);
1283 g_string_free(freq_text, TRUE);
1284 if (ret != SR_OK)
1285 return ret;
1286
1287 return SR_OK;
1288}
1289
1290SR_PRIV int jds6600_set_amplitude(const struct sr_dev_inst *sdi, size_t ch_idx)
1291{
1292 struct dev_context *devc;
1293 struct devc_chan *chan;
1294 GString *volt_text;
1295 int ret;
1296
1297 if (!sdi)
1298 return SR_ERR_ARG;
1299 devc = sdi->priv;
1300 if (!devc)
1301 return SR_ERR_ARG;
1302 if (ch_idx >= devc->device.channel_count_gen)
1303 return SR_ERR_ARG;
1304 chan = &devc->channel_config[ch_idx];
1305
1306 /* Transmit the request, receive an "ok" style response. */
1307 volt_text = g_string_sized_new(32);
1308 write_volt_text(volt_text, chan->amplitude);
1309 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1310 INSN_WRITE_PARA, IDX_AMPLITUDE_CH1 + ch_idx,
1311 "%s", volt_text->str);
1312 g_string_free(volt_text, TRUE);
1313 if (ret != SR_OK)
1314 return ret;
1315
1316 return SR_OK;
1317}
1318
1319SR_PRIV int jds6600_set_offset(const struct sr_dev_inst *sdi, size_t ch_idx)
1320{
1321 struct dev_context *devc;
1322 struct devc_chan *chan;
1323 GString *volt_text;
1324 int ret;
1325
1326 if (!sdi)
1327 return SR_ERR_ARG;
1328 devc = sdi->priv;
1329 if (!devc)
1330 return SR_ERR_ARG;
1331 if (ch_idx >= devc->device.channel_count_gen)
1332 return SR_ERR_ARG;
1333 chan = &devc->channel_config[ch_idx];
1334
1335 /* Transmit the request, receive an "ok" style response. */
1336 volt_text = g_string_sized_new(32);
1337 write_bias_text(volt_text, chan->offset);
1338 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1339 INSN_WRITE_PARA, IDX_OFFSET_CH1 + ch_idx,
1340 "%s", volt_text->str);
1341 g_string_free(volt_text, TRUE);
1342 if (ret != SR_OK)
1343 return ret;
1344
1345 return SR_OK;
1346}
1347
1348SR_PRIV int jds6600_set_dutycycle(const struct sr_dev_inst *sdi, size_t ch_idx)
1349{
1350 struct dev_context *devc;
1351 struct devc_chan *chan;
1352 GString *duty_text;
1353 int ret;
1354
1355 if (!sdi)
1356 return SR_ERR_ARG;
1357 devc = sdi->priv;
1358 if (!devc)
1359 return SR_ERR_ARG;
1360 if (ch_idx >= devc->device.channel_count_gen)
1361 return SR_ERR_ARG;
1362 chan = &devc->channel_config[ch_idx];
1363
1364 /* Transmit the request, receive an "ok" style response. */
1365 duty_text = g_string_sized_new(32);
1366 write_duty_text(duty_text, chan->dutycycle);
1367 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1368 INSN_WRITE_PARA, IDX_DUTYCYCLE_CH1 + ch_idx,
1369 "%s", duty_text->str);
1370 g_string_free(duty_text, TRUE);
1371 if (ret != SR_OK)
1372 return ret;
1373
1374 return SR_OK;
1375}
1376
1377SR_PRIV int jds6600_set_phase_chans(const struct sr_dev_inst *sdi)
1378{
1379 struct dev_context *devc;
1380 GString *phase_text;
1381 int ret;
1382
1383 if (!sdi)
1384 return SR_ERR_ARG;
1385 devc = sdi->priv;
1386 if (!devc)
1387 return SR_ERR_ARG;
1388
1389 /* Transmit the request, receive an "ok" style response. */
1390 phase_text = g_string_sized_new(32);
1391 write_phase_text(phase_text, devc->channels_phase);
1392 ret = quick_send_write_then_recv_ok(sdi, 0, NULL,
1393 INSN_WRITE_PARA, IDX_PHASE_CHANNELS,
1394 "%s", phase_text->str);
1395 g_string_free(phase_text, TRUE);
1396 if (ret != SR_OK)
1397 return ret;
1398
1399 return SR_OK;
1400}
1401
1402/*
1403 * High level helpers for the scan/probe phase. Identify the attached
1404 * device and synchronize to its current state and its capabilities.
1405 */
1406
1407SR_PRIV int jds6600_identify(struct sr_dev_inst *sdi)
1408{
1409 struct dev_context *devc;
1410 int ret;
1411 char *rdptr, *endptr;
1412 unsigned long devtype;
1413
1414 (void)append_insn_write_para_dots;
1415
1416 if (!sdi)
1417 return SR_ERR_ARG;
1418 devc = sdi->priv;
1419 if (!devc)
1420 return SR_ERR_ARG;
1421
1422 /* Transmit "read device type" request, receive the response. */
1423 ret = quick_send_read_then_recv(sdi,
1424 INSN_READ_PARA, IDX_DEVICE_TYPE,
1425 TIMEOUT_IDENTIFY, &rdptr, NULL);
1426 if (ret != SR_OK)
1427 return ret;
1428 sr_dbg("identify, device type '%s'", rdptr);
1429
1430 /* Interpret the response (integer value, max freq). */
1431 endptr = NULL;
1432 ret = sr_atoul_base(rdptr, &devtype, &endptr, 10);
1433 if (ret != SR_OK || !endptr)
1434 return SR_ERR_DATA;
1435 devc->device.device_type = devtype;
1436
1437 /* Transmit "read serial number" request. receive response. */
1438 ret = quick_send_read_then_recv(sdi,
1439 INSN_READ_PARA, IDX_SERIAL_NUMBER,
1440 0, &rdptr, NULL);
1441 if (ret != SR_OK)
1442 return ret;
1443 sr_dbg("identify, serial number '%s'", rdptr);
1444
1445 /* Keep the response (in string format, some serial number). */
1446 devc->device.serial_number = g_strdup(rdptr);
1447
1448 return SR_OK;
1449}
1450
1451SR_PRIV int jds6600_setup_devc(struct sr_dev_inst *sdi)
1452{
1453 struct dev_context *devc;
1454 size_t alloc_count, assign_idx, idx;
1455 struct devc_dev *device;
1456 struct devc_wave *waves;
1457 enum waveform_index_t code;
1458 char *name;
1459 int ret;
1460
1461 if (!sdi)
1462 return SR_ERR_ARG;
1463 devc = sdi->priv;
1464 if (!devc)
1465 return SR_ERR_ARG;
1466
1467 /*
1468 * Derive maximum output frequency from detected device type.
1469 * Open coded generator channel count.
1470 */
1471 device = &devc->device;
1472 if (!device->device_type)
1473 return SR_ERR_DATA;
1474 device->max_output_frequency = device->device_type;
1475 device->max_output_frequency *= SR_MHZ(1);
1476 device->channel_count_gen = MAX_GEN_CHANNELS;
1477
1478 /* Construct the list of waveform names and their codes. */
1479 waves = &devc->waveforms;
1480 waves->builtin_count = WAVES_COUNT_BUILTIN;
1481 waves->arbitrary_count = WAVES_COUNT_ARBITRARY;
1482 alloc_count = waves->builtin_count;
1483 alloc_count += waves->arbitrary_count;
1484 waves->names_count = alloc_count;
1485 waves->fw_codes = g_malloc0(alloc_count * sizeof(waves->fw_codes[0]));
1486 alloc_count++;
1487 waves->names = g_malloc0(alloc_count * sizeof(waves->names[0]));
1488 if (!waves->names || !waves->fw_codes)
1489 return SR_ERR_MALLOC;
1490 assign_idx = 0;
1491 for (idx = 0; idx < waves->builtin_count; idx++) {
1492 code = idx;
1493 name = g_strdup(waveform_names[idx]);
1494 waves->fw_codes[assign_idx] = code;
1495 waves->names[assign_idx] = name;
1496 assign_idx++;
1497 }
1498 for (idx = 0; idx < waves->arbitrary_count; idx++) {
1499 code = WAVE_ARB01 + idx;
1500 name = g_strdup_printf(WAVEFORM_ARB_NAME_FMT, idx + 1);
1501 waves->fw_codes[assign_idx] = code;
1502 waves->names[assign_idx] = name;
1503 assign_idx++;
1504 }
1505 waves->names[assign_idx] = NULL;
1506
1507 /*
1508 * Populate internal channel configuration details from the
1509 * device's current state. Emit a series of queries which
1510 * update internal knowledge.
1511 */
1512 ret = SR_OK;
1513 ret |= jds6600_get_chans_enable(sdi);
1514 for (idx = 0; idx < device->channel_count_gen; idx++) {
1515 ret |= jds6600_get_waveform(sdi, idx);
1516 ret |= jds6600_get_frequency(sdi, idx);
1517 ret |= jds6600_get_amplitude(sdi, idx);
1518 ret |= jds6600_get_offset(sdi, idx);
1519 ret |= jds6600_get_dutycycle(sdi, idx);
1520 }
1521 ret |= jds6600_get_phase_chans(sdi);
1522 ret |= jds6600_get_chans_enable(sdi);
1523 if (ret != SR_OK)
1524 return SR_ERR_DATA;
1525
1526#if WITH_ARBWAVE_DOWNLOAD
1527 /*
1528 * Development HACK, to see how waveform upload works.
1529 * How to forward the data to the application? Or the
1530 * sigrok session actually? Provide these as acquisition
1531 * results?
1532 */
1533 ret |= jds6600_get_arb_waveform(sdi, 13);
1534 if (ret != SR_OK)
1535 return SR_ERR_DATA;
1536 ret |= jds6600_set_arb_waveform(sdi, 12);
1537 ret |= jds6600_set_arb_waveform(sdi, 13);
1538 if (ret != SR_OK)
1539 return SR_ERR_DATA;
1540#endif
b1fa9aac 1541
18baeeed 1542 return SR_OK;
b1fa9aac 1543}