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