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