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