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