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