From 5f50d6da1bc5cc5b48fdc6d4f1775313e97fb1d2 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 27 Nov 2023 19:12:11 +0100 Subject: [PATCH 01/16] hantek-dso: eliminate the "forced trigger" option value Commit c93f113879a0 introduced a hack on top of an unfortunate choice. It seems counter intuitive to open code a default trigger source on an arbitrary channel, and have users override it with the "forced" value to _not_ use a trigger. The normal approach would be to specify a trigger when a trigger should be used, and to not specify a trigger when no trigger should be used. Eliminate the "forced" choice in the trigger_sources[] list. Start with a not-set value. Accept when a value is specified (a "genuine" choice). Don't bother adding support to "un-set" the previously specified choice. This leaves the intuitive support for trigger specs that shall be used, and only uses triggers when they were specified. Does not provide means to "un-set" an earlier specified trigger config as the implementation did before the 2023-09 change, which would be the 2021-02 status. If the approach implemented here should be considered undesirable, then a "none" option value should be introduced, something that much better communicates to users what's happening and what the consequence of a config choice would be. This commit also adjusts the "ugh" code path which differed from the "capture empty" code path. Fixes a resource leak in the config set path. The "set trigger source" and "set trigger and samplerate" commands don't agree on the phrase for the trigger source in the wire format. But have been doing that before the forced trigger introduction, behaviour remains unchanged here. --- src/hardware/hantek-dso/api.c | 15 ++++++++++----- src/hardware/hantek-dso/protocol.c | 18 +++++++++++------- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/hardware/hantek-dso/api.c b/src/hardware/hantek-dso/api.c index d10c58d1..bfad5f71 100644 --- a/src/hardware/hantek-dso/api.c +++ b/src/hardware/hantek-dso/api.c @@ -168,7 +168,7 @@ static const uint64_t vdivs[][2] = { }; static const char *trigger_sources[] = { - "CH1", "CH2", "EXT", "forced" + "CH1", "CH2", "EXT", }; static const char *trigger_slopes[] = { @@ -218,7 +218,7 @@ static struct sr_dev_inst *dso_dev_new(const struct dso_profile *prof) devc->voffset_trigger = DEFAULT_VERT_TRIGGERPOS; devc->framesize = DEFAULT_FRAMESIZE; devc->triggerslope = SLOPE_POSITIVE; - devc->triggersource = g_strdup(DEFAULT_TRIGGER_SOURCE); + devc->triggersource = NULL; devc->capture_ratio = DEFAULT_CAPTURE_RATIO; sdi->priv = devc; @@ -465,6 +465,8 @@ static int config_get(uint32_t key, GVariant **data, *data = g_variant_new_uint64(devc->framesize); break; case SR_CONF_TRIGGER_SOURCE: + if (!devc->triggersource) + return SR_ERR_NA; *data = g_variant_new_string(devc->triggersource); break; case SR_CONF_TRIGGER_SLOPE: @@ -555,6 +557,7 @@ static int config_set(uint32_t key, GVariant *data, case SR_CONF_TRIGGER_SOURCE: if ((idx = std_str_idx(data, ARRAY_AND_SIZE(trigger_sources))) < 0) return SR_ERR_ARG; + g_free(devc->triggersource); devc->triggersource = g_strdup(trigger_sources[idx]); break; default: @@ -836,8 +839,10 @@ static int handle_event(int fd, int revents, void *cb_data) return TRUE; if (dso_enable_trigger(sdi) != SR_OK) return TRUE; -// if (dso_force_trigger(sdi) != SR_OK) -// return TRUE; + if (!devc->triggersource) { + if (dso_force_trigger(sdi) != SR_OK) + return TRUE; + } sr_dbg("Successfully requested next chunk."); devc->dev_state = CAPTURE; return TRUE; @@ -858,7 +863,7 @@ static int handle_event(int fd, int revents, void *cb_data) break; if (dso_enable_trigger(sdi) != SR_OK) break; - if (!strcmp("forced", devc->triggersource)) { + if (!devc->triggersource) { if (dso_force_trigger(sdi) != SR_OK) break; } diff --git a/src/hardware/hantek-dso/protocol.c b/src/hardware/hantek-dso/protocol.c index 408f6112..34a3935b 100644 --- a/src/hardware/hantek-dso/protocol.c +++ b/src/hardware/hantek-dso/protocol.c @@ -275,12 +275,14 @@ static int dso2250_set_trigger_samplerate(const struct sr_dev_inst *sdi) memset(cmdstring, 0, sizeof(cmdstring)); /* Command */ cmdstring[0] = CMD_2250_SET_TRIGGERSOURCE; - sr_dbg("Trigger source %s.", devc->triggersource); - if (!strcmp("CH2", devc->triggersource)) + sr_dbg("Trigger source %s.", devc->triggersource ? : ""); + if (!devc->triggersource) + tmp = 0; + else if (!strcmp("CH2", devc->triggersource)) tmp = 3; else if (!strcmp("CH1", devc->triggersource)) tmp = 2; - else if (!strcmp("EXT", devc->triggersource) || !strcmp("forced", devc->triggersource)) + else if (!strcmp("EXT", devc->triggersource)) tmp = 0; else { sr_err("Invalid trigger source: '%s'.", devc->triggersource); @@ -421,12 +423,14 @@ SR_PRIV int dso_set_trigger_samplerate(const struct sr_dev_inst *sdi) cmdstring[0] = CMD_SET_TRIGGER_SAMPLERATE; /* Trigger source */ - sr_dbg("Trigger source %s.", devc->triggersource); - if (!strcmp("CH2", devc->triggersource)) + sr_dbg("Trigger source %s.", devc->triggersource ? : ""); + if (!devc->triggersource) + tmp = 2; + else if (!strcmp("CH2", devc->triggersource)) tmp = 0; else if (!strcmp("CH1", devc->triggersource)) tmp = 1; - else if (!strcmp("EXT", devc->triggersource) || !strcmp("forced", devc->triggersource)) + else if (!strcmp("EXT", devc->triggersource)) tmp = 2; else { sr_err("Invalid trigger source: '%s'.", devc->triggersource); @@ -668,7 +672,7 @@ static int dso_set_relays(const struct sr_dev_inst *sdi) if (devc->coupling[1] != COUPLING_AC) relays[6] = ~relays[6]; - if (!strcmp(devc->triggersource, "EXT")) + if (devc->triggersource && strcmp(devc->triggersource, "EXT") == 0) relays[7] = ~relays[7]; if (sr_log_loglevel_get() >= SR_LOG_DBG) { -- 2.30.2 From c3ada48afce7626a980c89e66d592a4242362c57 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Thu, 21 Dec 2023 21:20:55 +0100 Subject: [PATCH 02/16] strutil: support special case in power of two calculation The sr_next_power_of_two() helper routine rejected input value 0 (an index), considered this case invalid. It is not, requires 1 bit to hold the value. Return a "power of two" value of 1 for that input, callers expect that result. --- src/strutil.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/strutil.c b/src/strutil.c index 841a682a..2136bd49 100644 --- a/src/strutil.c +++ b/src/strutil.c @@ -1844,8 +1844,18 @@ SR_API int sr_next_power_of_two(size_t value, size_t *bits, size_t *power) if (power) *power = 0; - if (!value) - return SR_ERR_ARG; + /* + * Handle the special case of input value 0 (needs 1 bit + * and results in "power of two" value 1) here. It is not + * covered by the generic logic below. + */ + if (!value) { + if (bits) + *bits = 1; + if (power) + *power = 1; + return SR_OK; + } need_bits = 0; check_mask = 0; -- 2.30.2 From 87e738be5134dbd48e724075fab88589f3bf7f71 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Thu, 21 Dec 2023 21:22:43 +0100 Subject: [PATCH 03/16] tests: adjust test coverage for power of two and input value 0 An input value 0 for the sr_next_power_of_two() routine is not invalid any longer. Remove the test case that is expected to fail. Add a regular case to cover that code path instead. --- tests/strutil.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/strutil.c b/tests/strutil.c index 3cf132f0..3e43dbdc 100644 --- a/tests/strutil.c +++ b/tests/strutil.c @@ -578,6 +578,7 @@ static const struct power_case_t { size_t want_bits; size_t want_power; } power_cases[] = { + { 0, 1, 1, }, { 1, 1, 2, }, { 2, 2, 4, }, { 3, 2, 4, }, @@ -597,9 +598,6 @@ START_TEST(test_calc_power_of_two) const struct power_case_t *tcase; int ret; - ret = sr_next_power_of_two(0, NULL, NULL); - fail_unless(ret != SR_OK, "invalid value, did not fail"); - for (case_idx = 0; case_idx < ARRAY_SIZE(power_cases); case_idx++) { tcase = &power_cases[case_idx]; ret = sr_next_power_of_two(tcase->value, &bits, &power); -- 2.30.2 From 66041863d601b55ee39a95a455b9211da564ec2a Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Thu, 21 Dec 2023 21:24:33 +0100 Subject: [PATCH 04/16] greatfet: feed the session with constant width sample data Rename identifiers to tell the sigrok session feed's width and the width of sample data in device firmware communication apart. Always feed the session with sample data of a width which corresponds to the device's channels count. Some output modules and applications may not be prepared to handle different cases. --- src/hardware/greatfet/api.c | 3 +- src/hardware/greatfet/protocol.c | 69 ++++++++++++++++---------------- src/hardware/greatfet/protocol.h | 3 +- 3 files changed, 39 insertions(+), 36 deletions(-) diff --git a/src/hardware/greatfet/api.c b/src/hardware/greatfet/api.c index 49d6730d..db05c3d8 100644 --- a/src/hardware/greatfet/api.c +++ b/src/hardware/greatfet/api.c @@ -307,6 +307,7 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) ch_off++; cg->channels = g_slist_append(cg->channels, ch); } + devc->feed_unit_size = (ch_max + 8 - 1) / 8; sr_sw_limits_init(&devc->sw_limits); devc->samplerate = DEFAULT_SAMPLERATE; @@ -510,7 +511,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) if (!acq->feed_queue) { acq->feed_queue = feed_queue_logic_alloc(sdi, - BUFFER_SIZE, acq->unit_size); + BUFFER_SIZE, devc->feed_unit_size); if (!acq->feed_queue) { sr_err("Cannot allocate session feed buffer."); return SR_ERR_MALLOC; diff --git a/src/hardware/greatfet/protocol.c b/src/hardware/greatfet/protocol.c index c39b1fce..4b1d1d96 100644 --- a/src/hardware/greatfet/protocol.c +++ b/src/hardware/greatfet/protocol.c @@ -588,7 +588,7 @@ static int greatfet_logic_config(const struct sr_dev_inst *sdi) g_free(print_bw); bw = acq->capture_samplerate * 8 / acq->points_per_byte; if (!acq->use_upper_pins) - bw *= acq->unit_size; + bw *= acq->wire_unit_size; print_bw = sr_si_string_u64(bw, "bps"); sr_info("Resulting USB bandwidth: %s.", print_bw); g_free(print_bw); @@ -708,17 +708,15 @@ static int greatfet_calc_capture_chans(const struct sr_dev_inst *sdi) if (!fw_ch_count) return SR_ERR_ARG; if (fw_ch_count > 8) { - acq->unit_size = sizeof(uint16_t); + acq->wire_unit_size = sizeof(uint16_t); acq->points_per_byte = 1; } else { - acq->unit_size = sizeof(uint8_t); - if (acq->use_upper_pins) - acq->unit_size = sizeof(uint16_t); + acq->wire_unit_size = sizeof(uint8_t); acq->points_per_byte = 8 / fw_ch_count; } acq->channel_shift = fw_ch_count % 8; sr_dbg("unit %zu, dense %d -> shift %zu, points %zu", - acq->unit_size, !!acq->channel_shift, + acq->wire_unit_size, !!acq->channel_shift, acq->channel_shift, acq->points_per_byte); return SR_OK; @@ -1229,14 +1227,20 @@ SR_PRIV void greatfet_release_resources(const struct sr_dev_inst *sdi) /* * Process received sample date. There are two essential modes: - * - The straight forward case. The device provides 8 bits per sample - * point. Forward each byte as is to the sigrok session. It matches - * the sizeof(uint8_t) feed queue allocation parameter. + * - The straight forward case. The device provides 16 bits per sample + * point. Forward raw received data as is to the sigrok session. The + * device's endianess matches the session's LE expectation. And the + * data matches the device's announced total channel count. * - The compact presentation where a smaller number of channels is * active, and their data spans only part of a byte per sample point. * Multiple samples' data is sharing bytes, and bytes will carry data * that was taken at different times. This requires some untangling - * before forwarding byte sized sample data to the sigrok session. + * before forwarding sample data to the sigrok session which is of + * the expected width (unit size) and carries one sample per item. + * - The cases where one sample point's data occupies full bytes, but + * the firmware only communicates one byte per sample point, are seen + * as a special case of the above bit packing. The "complex case" + * logic covers the "bytes extension" as well. * * Implementation details: * - Samples taken first are found in the least significant bits of a @@ -1264,12 +1268,11 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi, struct feed_queue_logic *q; uint64_t samples_remain; gboolean exceeded; - gboolean full_bytes, lower_empty; size_t samples_rcvd; - uint8_t raw_mask; + uint8_t raw_mask, raw_data; size_t points_per_byte, points_count; - uint8_t raw_data, wr_data; - uint8_t accum[16]; + uint16_t wr_data; + uint8_t accum[8 * sizeof(wr_data)]; const uint8_t *rdptr; uint8_t *wrptr; int ret; @@ -1296,24 +1299,17 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi, return SR_OK; /* - * Check for the simple case first. Where bytes carry samples - * of exactly one sample point. Pass memory in verbatim form. + * Check for the simple case first. Where the firmware provides + * sample data for all logic channels supported by the device. + * Pass sample memory as received from the device in verbatim + * form to the session feed. * - * This approach applies to two cases: Captures of the first 8 - * channels, and captures for 16 channels where both banks are - * involved (the device firmware provides all 16 bits of data - * for any given sample point). The 16bit case happens to work - * because sample data received from the device and logic data - * in sigrok sessions both use the little endian format. - * - * The "upper pins" case must be handled below because the - * device will not provide data for the lower pin bank, but the - * samples (all-zero values) must be sent to the sigrok session. + * This happens to work because sample data received from the + * device and logic data in sigrok sessions both are in little + * endian format. */ - full_bytes = !acq->channel_shift; - lower_empty = acq->use_upper_pins; - if (full_bytes && !lower_empty) { - samples_rcvd = dlen / acq->unit_size; + if (acq->wire_unit_size == devc->feed_unit_size) { + samples_rcvd = dlen / acq->wire_unit_size; if (samples_remain && samples_rcvd > samples_remain) samples_rcvd = samples_remain; ret = feed_queue_logic_submit_many(q, data, samples_rcvd); @@ -1322,11 +1318,17 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi, sr_sw_limits_update_samples_read(&devc->sw_limits, samples_rcvd); return SR_OK; } + if (sizeof(wr_data) != devc->feed_unit_size) { + sr_err("Unhandled unit size mismatch. Flawed implementation?"); + return SR_ERR_BUG; + } /* * Handle the complex cases where one byte carries values that * were taken at multiple sample points, or where the firmware - * does not communicate the lower pin bank's data (upper pins). + * does not communicate all pin banks to the host (upper pins + * or lower pins only on the wire). + * * This involves manipulation between reception and forwarding. * It helps that the firmware provides sample data in units of * power-of-two bit counts per sample point. This eliminates @@ -1363,9 +1365,8 @@ static int greatfet_process_receive_data(const struct sr_dev_inst *sdi, while (points_count--) { wr_data = raw_data & raw_mask; if (acq->use_upper_pins) - write_u16le_inc(&wrptr, wr_data << 8); - else - write_u8_inc(&wrptr, wr_data); + wr_data <<= 8; + write_u16le_inc(&wrptr, wr_data); raw_data >>= acq->channel_shift; } points_count = points_per_byte; diff --git a/src/hardware/greatfet/protocol.h b/src/hardware/greatfet/protocol.h index 8fe7e1d8..fe344a75 100644 --- a/src/hardware/greatfet/protocol.h +++ b/src/hardware/greatfet/protocol.h @@ -37,11 +37,12 @@ struct dev_context { char *serial_number; size_t channel_count; char **channel_names; + size_t feed_unit_size; struct sr_sw_limits sw_limits; uint64_t samplerate; struct dev_acquisition_t { uint64_t bandwidth_threshold; - size_t unit_size; + size_t wire_unit_size; struct feed_queue_logic *feed_queue; size_t capture_channels; gboolean use_upper_pins; -- 2.30.2 From 1ebdf6406682edb25cd4929638c24391bec8e5f6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 20 Apr 2023 19:21:13 +0200 Subject: [PATCH 05/16] hwdriver: Add SR_CONF_OVER_CURRENT_PROTECTION_DELAY This config key allows to specify the delay before the over-current protection triggers. Signed-off-by: Marc Schink --- include/libsigrok/libsigrok.h | 8 ++++++++ src/hwdriver.c | 2 ++ 2 files changed, 10 insertions(+) diff --git a/include/libsigrok/libsigrok.h b/include/libsigrok/libsigrok.h index 58216c2c..6c5dea08 100644 --- a/include/libsigrok/libsigrok.h +++ b/include/libsigrok/libsigrok.h @@ -1129,6 +1129,14 @@ enum sr_configkey { */ SR_CONF_RESISTANCE_TARGET, + /** + * Over-current protection (OCP) delay + * @arg type: double (time) + * @arg get: get current delay + * @arg set: set new delay + */ + SR_CONF_OVER_CURRENT_PROTECTION_DELAY, + /* Update sr_key_info_config[] (hwdriver.c) upon changes! */ /*--- Special stuff -------------------------------------------------*/ diff --git a/src/hwdriver.c b/src/hwdriver.c index 7b497e07..068a215a 100644 --- a/src/hwdriver.c +++ b/src/hwdriver.c @@ -214,6 +214,8 @@ static struct sr_key_info sr_key_info_config[] = { "Power Target", NULL}, {SR_CONF_RESISTANCE_TARGET, SR_T_FLOAT, "resistance_target", "Resistance Target", NULL}, + {SR_CONF_OVER_CURRENT_PROTECTION_DELAY, SR_T_FLOAT, "ocp_delay", + "Over-current protection delay", NULL}, /* Special stuff */ {SR_CONF_SESSIONFILE, SR_T_STRING, "sessionfile", -- 2.30.2 From aec7d8551d588f9b1af33733a0d642d2eb0e3199 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 20 Apr 2023 19:25:58 +0200 Subject: [PATCH 06/16] scpi-pps: Add support for SR_CONF_OVER_CURRENT_PROTECTION_DELAY Prepare the driver for the 'over-current protection delay' feature. For now, this feature is disabled for all currently supported devices. Signed-off-by: Marc Schink --- src/hardware/scpi-pps/api.c | 13 +++++ src/hardware/scpi-pps/profiles.c | 89 ++++++++++++++++---------------- src/hardware/scpi-pps/protocol.h | 3 ++ 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/hardware/scpi-pps/api.c b/src/hardware/scpi-pps/api.c index bd11f082..116a5d46 100644 --- a/src/hardware/scpi-pps/api.c +++ b/src/hardware/scpi-pps/api.c @@ -437,6 +437,10 @@ static int config_get(uint32_t key, GVariant **data, gvtype = G_VARIANT_TYPE_DOUBLE; cmd = SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD; break; + case SR_CONF_OVER_CURRENT_PROTECTION_DELAY: + gvtype = G_VARIANT_TYPE_DOUBLE; + cmd = SCPI_CMD_GET_OVER_CURRENT_PROTECTION_DELAY; + break; case SR_CONF_OVER_TEMPERATURE_PROTECTION: if (devc->device->dialect == SCPI_DIALECT_HMP) { /* OTP is always enabled. */ @@ -698,6 +702,12 @@ static int config_set(uint32_t key, GVariant *data, channel_group_cmd, channel_group_name, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, d); break; + case SR_CONF_OVER_CURRENT_PROTECTION_DELAY: + d = g_variant_get_double(data); + ret = sr_scpi_cmd(sdi, devc->device->commands, + channel_group_cmd, channel_group_name, + SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DELAY, d); + break; case SR_CONF_OVER_TEMPERATURE_PROTECTION: if (g_variant_get_boolean(data)) ret = sr_scpi_cmd(sdi, devc->device->commands, @@ -794,6 +804,9 @@ static int config_list(uint32_t key, GVariant **data, case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD: *data = std_gvar_min_max_step_array(ch_spec->ocp); break; + case SR_CONF_OVER_CURRENT_PROTECTION_DELAY: + *data = std_gvar_min_max_step_array(ch_spec->ocp_delay); + break; default: return SR_ERR_NA; } diff --git a/src/hardware/scpi-pps/profiles.c b/src/hardware/scpi-pps/profiles.c index 358e2701..9d561af3 100644 --- a/src/hardware/scpi-pps/profiles.c +++ b/src/hardware/scpi-pps/profiles.c @@ -29,6 +29,7 @@ #define FREQ_DC_ONLY {0, 0, 0, 0, 0} #define NO_OVP_LIMITS {0, 0, 0, 0, 0} #define NO_OCP_LIMITS {0, 0, 0, 0, 0} +#define NO_OCP_DELAY {0, 0, 0, 0, 0} /* Agilent/Keysight N5700A series */ static const uint32_t agilent_n5700a_devopts[] = { @@ -52,11 +53,11 @@ static const struct channel_group_spec agilent_n5700a_cg[] = { }; static const struct channel_spec agilent_n5767a_ch[] = { - { "1", { 0, 60, 0.0072, 3, 4 }, { 0, 25, 0.003, 3, 4 }, { 0, 1500 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 60, 0.0072, 3, 4 }, { 0, 25, 0.003, 3, 4 }, { 0, 1500 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec agilent_n5763a_ch[] = { - { "1", { 0, 12.5, 0.0015, 3, 4 }, { 0, 120, 0.0144, 3, 4 }, { 0, 1500 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 12.5, 0.0015, 3, 4 }, { 0, 120, 0.0144, 3, 4 }, { 0, 1500 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; /* @@ -103,9 +104,9 @@ static const uint32_t bk_9130_devopts_cg[] = { }; static const struct channel_spec bk_9130_ch[] = { - { "1", { 0, 30, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 90, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 30, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 90, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, 5, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 15, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 30, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 90, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 30, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 90, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, 5, 0.001, 3, 3 }, { 0, 3, 0.001, 3, 3 }, { 0, 15, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec bk_9130_cg[] = { @@ -152,7 +153,7 @@ static const uint32_t chroma_61604_devopts_cg[] = { }; static const struct channel_spec chroma_61604_ch[] = { - { "1", { 0, 300, 0.1, 1, 1 }, { 0, 16, 0.1, 2, 2 }, { 0, 2000, 0, 1, 1 }, { 1.0, 1000.0, 0.01 }, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 300, 0.1, 1, 1 }, { 0, 16, 0.1, 2, 2 }, { 0, 2000, 0, 1, 1 }, { 1.0, 1000.0, 0.01 }, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec chroma_61604_cg[] = { @@ -468,11 +469,11 @@ static const uint32_t rigol_dp700_devopts_cg[] = { }; static const struct channel_spec rigol_dp711_ch[] = { - { "1", { 0, 30, 0.01, 3, 3 }, { 0, 5, 0.01, 3, 3 }, { 0, 150, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 33, 0.01}, { 0.01, 5.5, 0.01 } }, + { "1", { 0, 30, 0.01, 3, 3 }, { 0, 5, 0.01, 3, 3 }, { 0, 150, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 33, 0.01}, { 0.01, 5.5, 0.01 }, NO_OCP_DELAY }, }; static const struct channel_spec rigol_dp712_ch[] = { - { "1", { 0, 50, 0.01, 3, 3 }, { 0, 3, 0.01, 3, 3 }, { 0, 150, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 55, 0.01}, { 0.01, 3.3, 0.01 } }, + { "1", { 0, 50, 0.01, 3, 3 }, { 0, 3, 0.01, 3, 3 }, { 0, 150, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 55, 0.01}, { 0.01, 3.3, 0.01 }, NO_OCP_DELAY }, }; static const struct channel_group_spec rigol_dp700_cg[] = { @@ -537,20 +538,20 @@ static const uint32_t rigol_dp800_devopts_cg[] = { }; static const struct channel_spec rigol_dp821a_ch[] = { - { "1", { 0, 60, 0.001, 3, 3 }, { 0, 1, 0.0001, 4, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 8, 0.001, 3, 3 }, { 0, 10, 0.001, 3, 3 }, { 0, 80, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 60, 0.001, 3, 3 }, { 0, 1, 0.0001, 4, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 8, 0.001, 3, 3 }, { 0, 10, 0.001, 3, 3 }, { 0, 80, 0, 3, 3 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec rigol_dp831_ch[] = { - { "1", { 0, 8, 0.001, 3, 4 }, { 0, 5, 0.0003, 3, 4 }, { 0, 40, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 30, 0.001, 3, 4 }, { 0, 2, 0.0001, 3, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, -30, 0.001, 3, 4 }, { 0, 2, 0.0001, 3, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 8, 0.001, 3, 4 }, { 0, 5, 0.0003, 3, 4 }, { 0, 40, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 30, 0.001, 3, 4 }, { 0, 2, 0.0001, 3, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, -30, 0.001, 3, 4 }, { 0, 2, 0.0001, 3, 4 }, { 0, 60, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec rigol_dp832_ch[] = { - { "1", { 0, 30, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 30, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, 5, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 30, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 30, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, 5, 0.001, 3, 4 }, { 0, 3, 0.001, 3, 4 }, { 0, 90, 0, 3, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec rigol_dp820_cg[] = { @@ -622,15 +623,15 @@ static const uint32_t hp_6630a_devopts_cg[] = { }; static const struct channel_spec hp_6632a_ch[] = { - { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00125, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS }, + { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00125, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6633a_ch[] = { - { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 2.0475, 0.0005, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS }, + { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 2.0475, 0.0005, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6634a_ch[] = { - { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 1.0238, 0.00025, 4, 5 }, { 0, 104.81664 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS }, + { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 1.0238, 0.00025, 4, 5 }, { 0, 104.81664 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec hp_6630a_cg[] = { @@ -764,43 +765,43 @@ static const uint32_t hp_6630b_devopts_cg[] = { }; static const struct channel_spec hp_6611c_ch[] = { - { "1", { 0, 8.19, 0.002, 3, 4 }, { 0, 5.1188, 0.00125, 4, 5 }, { 0, 41.92297 }, FREQ_DC_ONLY, { 0, 12, 0.06 }, NO_OCP_LIMITS }, + { "1", { 0, 8.19, 0.002, 3, 4 }, { 0, 5.1188, 0.00125, 4, 5 }, { 0, 41.92297 }, FREQ_DC_ONLY, { 0, 12, 0.06 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6612c_ch[] = { - { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 2.0475, 0.0005, 4, 5 }, { 0, 41.92256 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS }, + { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 2.0475, 0.0005, 4, 5 }, { 0, 41.92256 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6613c_ch[] = { - { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 1.0238, 0.00025, 4, 5 }, { 0, 52.40627 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS }, + { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 1.0238, 0.00025, 4, 5 }, { 0, 52.40627 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6614c_ch[] = { - { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 0.5118, 0.000125, 4, 5 }, { 0, 52.39808 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS }, + { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 0.5118, 0.000125, 4, 5 }, { 0, 52.39808 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6631b_ch[] = { - { "1", { 0, 8.19, 0.002, 3, 4 }, { 0, 10.237, 0.00263, 4, 5 }, { 0, 83.84103 }, FREQ_DC_ONLY, { 0, 12, 0.06 }, NO_OCP_LIMITS }, + { "1", { 0, 8.19, 0.002, 3, 4 }, { 0, 10.237, 0.00263, 4, 5 }, { 0, 83.84103 }, FREQ_DC_ONLY, { 0, 12, 0.06 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6632b_ch[] = { - { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00132, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS }, + { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00132, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_66312a_ch[] = { - { "1", { 0, 20.475, 0.0001, 4, 5 }, { 0, 2.0475, 0.0001, 4, 5 }, { 0, 41.92256 }, FREQ_DC_ONLY, { 0, 22, 0.01 }, NO_OCP_LIMITS }, + { "1", { 0, 20.475, 0.0001, 4, 5 }, { 0, 2.0475, 0.0001, 4, 5 }, { 0, 41.92256 }, FREQ_DC_ONLY, { 0, 22, 0.01 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_66332a_ch[] = { - { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00132, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS }, + { "1", { 0, 20.475, 0.005, 3, 4 }, { 0, 5.1188, 0.00132, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 22, 0.1 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6633b_ch[] = { - { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 2.0475, 0.000526, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS }, + { "1", { 0, 51.188, 0.0125, 3, 4 }, { 0, 2.0475, 0.000526, 4, 5 }, { 0, 104.80743 }, FREQ_DC_ONLY, { 0, 55, 0.25 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec hp_6634b_ch[] = { - { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 1.0238, 0.000263, 4, 5 }, { 0, 104.81664 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS }, + { "1", { 0, 102.38, 0.025, 3, 4 }, { 0, 1.0238, 0.000263, 4, 5 }, { 0, 104.81664 }, FREQ_DC_ONLY, { 0, 110, 0.5 }, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec hp_6630b_cg[] = { @@ -1025,11 +1026,11 @@ static const uint32_t owon_p4000_devopts_cg[] = { }; static const struct channel_spec owon_p4603_ch[] = { - { "1", { 0.01, 60, 0.001, 3, 3 }, { 0.001, 3, 0.001, 3, 3 }, { 0, 180, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 61, 0.001}, { 0.001, 3.1, 0.001} }, + { "1", { 0.01, 60, 0.001, 3, 3 }, { 0.001, 3, 0.001, 3, 3 }, { 0, 180, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 61, 0.001}, { 0.001, 3.1, 0.001}, NO_OCP_DELAY }, }; static const struct channel_spec owon_p4305_ch[] = { - { "1", { 0.01, 30, 0.001, 3, 3 }, { 0.001, 5, 0.001, 3, 3 }, { 0, 180, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 31, 0.001}, { 0.001, 3.1, 0.001} }, + { "1", { 0.01, 30, 0.001, 3, 3 }, { 0.001, 5, 0.001, 3, 3 }, { 0, 180, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 31, 0.001}, { 0.001, 3.1, 0.001}, NO_OCP_DELAY }, }; static const struct channel_group_spec owon_p4000_cg[] = { @@ -1057,7 +1058,7 @@ static const struct scpi_command owon_p4000_cmd[] = { /* Owon SPE series*/ static const struct channel_spec owon_spe6103_ch[] = { - { "1", { 0.01, 60, 0.01, 3, 3 }, { 0.001, 10, 0.001, 3, 3 }, { 0, 300, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 61, 0.01}, { 0.001, 10.1, 0.001} }, + { "1", { 0.01, 60, 0.01, 3, 3 }, { 0.001, 10, 0.001, 3, 3 }, { 0, 300, 0, 3, 3 }, FREQ_DC_ONLY, { 0.01, 61, 0.01}, { 0.001, 10.1, 0.001}, NO_OCP_DELAY }, }; static const struct scpi_command owon_spe6103_cmd[] = { @@ -1250,9 +1251,9 @@ static const uint32_t rs_hmc8043_devopts_cg[] = { }; static const struct channel_spec rs_hmc8043_ch[] = { - { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec rs_hmc8043_cg[] = { @@ -1301,21 +1302,21 @@ static const uint32_t rs_hmp4040_devopts_cg[] = { }; static const struct channel_spec rs_hmp2020_ch[] = { - { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec rs_hmp2030_ch[] = { - { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 5.01, 0.0001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_spec rs_hmp4040_ch[] = { - { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, - { "4", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS }, + { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "4", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 10.01, 0.0002, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, }; static const struct channel_group_spec rs_hmp4040_cg[] = { diff --git a/src/hardware/scpi-pps/protocol.h b/src/hardware/scpi-pps/protocol.h index 279977f1..b75feb2e 100644 --- a/src/hardware/scpi-pps/protocol.h +++ b/src/hardware/scpi-pps/protocol.h @@ -66,6 +66,8 @@ enum pps_scpi_cmds { SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, + SCPI_CMD_GET_OVER_CURRENT_PROTECTION_DELAY, + SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DELAY, }; /* Defines the SCPI dialect */ @@ -121,6 +123,7 @@ struct channel_spec { double frequency[5]; double ovp[5]; double ocp[5]; + double ocp_delay[5]; }; struct channel_group_spec { -- 2.30.2 From 9d2c239134407edbbe68f802a883f61d03475c02 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 20 Apr 2023 19:28:19 +0200 Subject: [PATCH 07/16] scpi-pps: Add OCP support for R&S HMC8043 Signed-off-by: Marc Schink --- src/hardware/scpi-pps/profiles.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/hardware/scpi-pps/profiles.c b/src/hardware/scpi-pps/profiles.c index 9d561af3..01ce6fb6 100644 --- a/src/hardware/scpi-pps/profiles.c +++ b/src/hardware/scpi-pps/profiles.c @@ -1243,6 +1243,9 @@ static const uint32_t rs_hmc8043_devopts_cg[] = { SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED | SR_CONF_GET | SR_CONF_SET, SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE | SR_CONF_GET, SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET, + SR_CONF_OVER_CURRENT_PROTECTION_ENABLED | SR_CONF_GET | SR_CONF_SET, + SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE | SR_CONF_GET, + SR_CONF_OVER_CURRENT_PROTECTION_DELAY | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_VOLTAGE | SR_CONF_GET, SR_CONF_VOLTAGE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, SR_CONF_CURRENT | SR_CONF_GET, @@ -1251,15 +1254,15 @@ static const uint32_t rs_hmc8043_devopts_cg[] = { }; static const struct channel_spec rs_hmc8043_ch[] = { - { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, - { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, - { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, NO_OCP_DELAY }, + { "1", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, { 0.01, 10, 0.001, 3, 4} }, + { "2", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, { 0.01, 10, 0.001, 3, 4} }, + { "3", { 0, 32.050, 0.001, 3, 4 }, { 0.001, 3, 0.001, 3, 4 }, { 0, 0, 0, 0, 4 }, FREQ_DC_ONLY, NO_OVP_LIMITS, NO_OCP_LIMITS, { 0.01, 10, 0.001, 3, 4} }, }; static const struct channel_group_spec rs_hmc8043_cg[] = { - { "1", CH_IDX(0), PPS_OVP, SR_MQFLAG_DC }, - { "2", CH_IDX(1), PPS_OVP, SR_MQFLAG_DC }, - { "3", CH_IDX(2), PPS_OVP, SR_MQFLAG_DC }, + { "1", CH_IDX(0), PPS_OVP | PPS_OCP, SR_MQFLAG_DC }, + { "2", CH_IDX(1), PPS_OVP | PPS_OCP, SR_MQFLAG_DC }, + { "3", CH_IDX(2), PPS_OVP | PPS_OCP, SR_MQFLAG_DC }, }; static const struct scpi_command rs_hmc8043_cmd[] = { @@ -1279,6 +1282,12 @@ static const struct scpi_command rs_hmc8043_cmd[] = { { SCPI_CMD_GET_OVER_VOLTAGE_PROTECTION_ENABLED, "VOLT:PROT:STAT?" }, { SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE, "VOLT:PROT:STAT ON" }, { SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_DISABLE, "VOLT:PROT:STAT OFF" }, + { SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, "FUSE:TRIP?" }, + { SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ENABLED, "FUSE:STAT?" }, + { SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE, "FUSE:STAT ON" }, + { SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE, "FUSE:STAT OFF" }, + { SCPI_CMD_GET_OVER_CURRENT_PROTECTION_DELAY, "FUSE:DEL?" }, + { SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DELAY, "FUSE:DEL %.03f" }, ALL_ZERO }; -- 2.30.2 From 3ed4b109b5975b82dbf3e9f276c4e54a266634db Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 12 Apr 2023 07:13:55 +0200 Subject: [PATCH 08/16] scpi-pps: Add support for R&S HMC8042 Signed-off-by: Marc Schink --- src/hardware/scpi-pps/profiles.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/hardware/scpi-pps/profiles.c b/src/hardware/scpi-pps/profiles.c index 01ce6fb6..2b759e5d 100644 --- a/src/hardware/scpi-pps/profiles.c +++ b/src/hardware/scpi-pps/profiles.c @@ -1742,6 +1742,18 @@ SR_PRIV const struct scpi_pps pps_profiles[] = { .update_status = NULL, }, + /* Rohde & Schwarz HMC8042 */ + { "Rohde&Schwarz", "HMC8042", SCPI_DIALECT_UNKNOWN, 0, + ARRAY_AND_SIZE(rs_hmc8043_devopts), + ARRAY_AND_SIZE(rs_hmc8043_devopts_cg), + rs_hmc8043_ch, 2, + rs_hmc8043_cg, 2, + rs_hmc8043_cmd, + .probe_channels = NULL, + .init_acquisition = NULL, + .update_status = NULL, + }, + /* Rohde & Schwarz HMC8043 */ { "Rohde&Schwarz", "HMC8043", SCPI_DIALECT_UNKNOWN, 0, ARRAY_AND_SIZE(rs_hmc8043_devopts), -- 2.30.2 From b4148df0d192eb065bc9afec580f2c11dd269dc0 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 5 Dec 2022 14:12:26 +0100 Subject: [PATCH 09/16] contrib: Add udev rule for R&S HMC804x series (USBTMC) Signed-off-by: Marc Schink --- contrib/60-libsigrok.rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/60-libsigrok.rules b/contrib/60-libsigrok.rules index 0217b994..b6ac3ba0 100644 --- a/contrib/60-libsigrok.rules +++ b/contrib/60-libsigrok.rules @@ -254,6 +254,9 @@ ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0117", ENV{ID_SIGROK}="1" ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", ENV{ID_SIGROK}="1" ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0119", ENV{ID_SIGROK}="1" +# Rohde&Schwarz HMC series power supply (previously branded Hameg) VCP/USBTMC mode +ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0135", ENV{ID_SIGROK}="1" + # Sainsmart DDS120 / Rocktech BM102, renumerates as 1d50:608e "sigrok fx2lafw", Serial: Sainsmart DDS120 ATTRS{idVendor}=="8102", ATTRS{idProduct}=="8102", ENV{ID_SIGROK}="1" -- 2.30.2 From f1b22e5627dc4cd060ff0c7a3a09f685903e3a26 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 26 Apr 2023 10:50:49 +0200 Subject: [PATCH 10/16] scpi/serial: Add USB VID/PID for R&S HMC808x series Signed-off-by: Marc Schink --- src/scpi/scpi_serial.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/scpi/scpi_serial.c b/src/scpi/scpi_serial.c index 067838ad..92d2c531 100644 --- a/src/scpi/scpi_serial.c +++ b/src/scpi/scpi_serial.c @@ -46,6 +46,7 @@ static const struct { { 0x0aad, 0x0117, "115200/8n1" }, /* R&S HMO series, previously branded as Hameg HMO */ { 0x0aad, 0x0118, "115200/8n1" }, /* R&S HMO series, previously branded as Hameg HMO */ { 0x0aad, 0x0119, "115200/8n1" }, /* R&S HMO series, previously branded as Hameg HMO */ + { 0x0aad, 0x0135, "115200/8n1" }, /* R&S HMC series, previously branded as Hameg HMC */ { 0x2184, 0x0030, "115200/8n1" }, /* GW-Instek GDM-8341 (VCP, SiLabs CP210x) */ { 0x2184, 0x0058, "115200/8n1" }, /* GW-Instek GDM-9061 (USBCDC mode) */ }; -- 2.30.2 From e4cfebe081013a6338e29dcf337755671aec3eb0 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Fri, 29 Dec 2023 12:17:31 +0100 Subject: [PATCH 11/16] output/srzip: rename variable for archive unit size The srzip output module needs to deal with two unit sizes. One that got derived from the device's or input's logic channels' total count, and will end up being used in the ZIP archive. And one which is seen when the session feed provides sample data. Rename the identifier to reflect this distinction. See a word diff for the essence of the change. Also rephrase the zip_append_queue() invocation for improved readability. Use line breaks to illustrate parameter sets which are related, and separate them from other parameters which are unrelated. --- src/output/srzip.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/output/srzip.c b/src/output/srzip.c index e3b57e3e..88dbc7a1 100644 --- a/src/output/srzip.c +++ b/src/output/srzip.c @@ -38,7 +38,7 @@ struct out_context { size_t analog_ch_count; gint *analog_index_map; struct logic_buff { - size_t unit_size; + size_t zip_unit_size; size_t alloc_size; uint8_t *samples; size_t fill_size; @@ -204,14 +204,14 @@ static int zip_create(const struct sr_output *o) * during execution. This simplifies other locations. */ alloc_size = CHUNK_SIZE; - outc->logic_buff.unit_size = logic_channels; - outc->logic_buff.unit_size += 8 - 1; - outc->logic_buff.unit_size /= 8; + outc->logic_buff.zip_unit_size = logic_channels; + outc->logic_buff.zip_unit_size += 8 - 1; + outc->logic_buff.zip_unit_size /= 8; outc->logic_buff.samples = g_try_malloc0(alloc_size); if (!outc->logic_buff.samples) return SR_ERR_MALLOC; - if (outc->logic_buff.unit_size) - alloc_size /= outc->logic_buff.unit_size; + if (outc->logic_buff.zip_unit_size) + alloc_size /= outc->logic_buff.zip_unit_size; outc->logic_buff.alloc_size = alloc_size; outc->logic_buff.fill_size = 0; @@ -396,7 +396,8 @@ static int zip_append(const struct sr_output *o, * @returns SR_OK et al error codes. */ static int zip_append_queue(const struct sr_output *o, - const uint8_t *buf, size_t unitsize, size_t length, gboolean flush) + const uint8_t *buf, size_t unitsize, size_t length, + gboolean flush) { struct out_context *outc; struct logic_buff *buff; @@ -407,7 +408,7 @@ static int zip_append_queue(const struct sr_output *o, outc = o->priv; buff = &outc->logic_buff; - if (length && unitsize != buff->unit_size) { + if (length && unitsize != buff->zip_unit_size) { sr_warn("Unexpected unit size, discarding logic data."); return SR_ERR_ARG; } @@ -417,21 +418,21 @@ static int zip_append_queue(const struct sr_output *o, * Flush to the ZIP archive when the buffer space is exhausted. */ rdptr = buf; - send_size = buff->unit_size ? length / buff->unit_size : 0; + send_size = buff->zip_unit_size ? length / buff->zip_unit_size : 0; while (send_size) { remain = buff->alloc_size - buff->fill_size; if (remain) { - wrptr = &buff->samples[buff->fill_size * buff->unit_size]; + wrptr = &buff->samples[buff->fill_size * buff->zip_unit_size]; copy_size = MIN(send_size, remain); send_size -= copy_size; buff->fill_size += copy_size; - memcpy(wrptr, rdptr, copy_size * buff->unit_size); - rdptr += copy_size * buff->unit_size; + memcpy(wrptr, rdptr, copy_size * buff->zip_unit_size); + rdptr += copy_size * buff->zip_unit_size; remain -= copy_size; } if (send_size && !remain) { - ret = zip_append(o, buff->samples, buff->unit_size, - buff->fill_size * buff->unit_size); + ret = zip_append(o, buff->samples, buff->zip_unit_size, + buff->fill_size * buff->zip_unit_size); if (ret != SR_OK) return ret; buff->fill_size = 0; @@ -441,8 +442,8 @@ static int zip_append_queue(const struct sr_output *o, /* Flush to the ZIP archive if the caller wants us to. */ if (flush && buff->fill_size) { - ret = zip_append(o, buff->samples, buff->unit_size, - buff->fill_size * buff->unit_size); + ret = zip_append(o, buff->samples, buff->zip_unit_size, + buff->fill_size * buff->zip_unit_size); if (ret != SR_OK) return ret; buff->fill_size = 0; @@ -665,8 +666,9 @@ static int receive(const struct sr_output *o, const struct sr_datafeed_packet *p outc->zip_created = TRUE; } logic = packet->payload; - ret = zip_append_queue(o, logic->data, - logic->unitsize, logic->length, FALSE); + ret = zip_append_queue(o, + logic->data, logic->unitsize, logic->length, + FALSE); if (ret != SR_OK) return ret; break; -- 2.30.2 From 7bf35e65be1aa8596de01712b0034c604af261ee Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Fri, 29 Dec 2023 12:24:06 +0100 Subject: [PATCH 12/16] output/srzip: rename variables for samples counts The srzip output module deals with a number of samples that are of a given width (unit size). Rename variables to better tell item counts from byte counts. See a word diff for review. --- src/output/srzip.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/output/srzip.c b/src/output/srzip.c index 88dbc7a1..76a2d5f2 100644 --- a/src/output/srzip.c +++ b/src/output/srzip.c @@ -401,7 +401,7 @@ static int zip_append_queue(const struct sr_output *o, { struct out_context *outc; struct logic_buff *buff; - size_t send_size, remain, copy_size; + size_t send_count, remain, copy_count; const uint8_t *rdptr; uint8_t *wrptr; int ret; @@ -418,19 +418,19 @@ static int zip_append_queue(const struct sr_output *o, * Flush to the ZIP archive when the buffer space is exhausted. */ rdptr = buf; - send_size = buff->zip_unit_size ? length / buff->zip_unit_size : 0; - while (send_size) { + send_count = buff->zip_unit_size ? length / buff->zip_unit_size : 0; + while (send_count) { remain = buff->alloc_size - buff->fill_size; if (remain) { wrptr = &buff->samples[buff->fill_size * buff->zip_unit_size]; - copy_size = MIN(send_size, remain); - send_size -= copy_size; - buff->fill_size += copy_size; - memcpy(wrptr, rdptr, copy_size * buff->zip_unit_size); - rdptr += copy_size * buff->zip_unit_size; - remain -= copy_size; + copy_count = MIN(send_count, remain); + send_count -= copy_count; + buff->fill_size += copy_count; + memcpy(wrptr, rdptr, copy_count * buff->zip_unit_size); + rdptr += copy_count * buff->zip_unit_size; + remain -= copy_count; } - if (send_size && !remain) { + if (send_count && !remain) { ret = zip_append(o, buff->samples, buff->zip_unit_size, buff->fill_size * buff->zip_unit_size); if (ret != SR_OK) -- 2.30.2 From 5c52d96a3bd14aa7870e9d506ed40b3e4e8e73a6 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Fri, 29 Dec 2023 12:32:45 +0100 Subject: [PATCH 13/16] output/srzip: accept arbitrary input and output unit sizes Commit c03aaf342c3f introduced a check and refused to store sample data when the feed would not exactly match an expected width that was derived from the device's or input's total count of logic channels. Earlier versions assumed the match but never checked (immediately forwarded session feed content to the ZIP archive). Existing applications may not be prepared to process the resulting archive where meta data and samples disagree on essential properties. The fatal condition aborted execution, which was perceived as a regression. A message was added later to communicate that the condition was hit, but its WARN severity was misleading, and its meaning still was obscure to users. This commit extends the reception of sample data in the session feed and its accumulation in the local buffer before ZIP archive appends. Any combination of input and output unit sizes are accepted. It's perfectly legal for sources to not communicate data for disabled channels, as well as to communicate wider data images than strictly necessary to simplify their support for a variety of input formats or device models. Details are available to users at higher log levels (INFO). Default levels only communicate fatal conditions (which should be implementation flaws now exclusively). The issue reproduces especially well with input formats that are rather flexible, or device drivers which support a range of devices with many configurations or models of differing capabilities. The issue was most recently reported for the OLS driver and an Arduino SUMP firmware. Given how many input modules and device drivers can feed into a few output modules, it's assumed that addressing the general issue in a common location is preferrable over local adjustment of individual input modules or device drivers. Adjusting both places doesn't harm either, increases overall robustness. The implementation results in a negligable runtime overhead for the regular case of matching unit sizes (a few integer checks). And an acceptable overhead when the session feed is wider than the srzip archive's unit size (multiple memcpy() calls where previously was only one which would have been incorrect without the consistency check). The code path which needs to apply padding to the output is most expensive, but the implementation is only as expensive as it needs to be. The added cost only occurs in the case of mismatches, which were not handled at all before this change. The combination of extensive diagnostics and internal consistency checks shall increase robustness and help during future maintenance. Reported-By: Pavel Fedin --- src/output/srzip.c | 62 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/src/output/srzip.c b/src/output/srzip.c index 76a2d5f2..c1e2e438 100644 --- a/src/output/srzip.c +++ b/src/output/srzip.c @@ -396,21 +396,61 @@ static int zip_append(const struct sr_output *o, * @returns SR_OK et al error codes. */ static int zip_append_queue(const struct sr_output *o, - const uint8_t *buf, size_t unitsize, size_t length, + const uint8_t *buf, size_t feed_unitsize, size_t length, gboolean flush) { + static gboolean sizes_seen; + struct out_context *outc; struct logic_buff *buff; + size_t sample_copy_size, sample_skip_size, sample_pad_size; size_t send_count, remain, copy_count; const uint8_t *rdptr; uint8_t *wrptr; int ret; + /* + * Check input parameters. Prepare to either grab data as is, + * or to adjust between differing input and output unit sizes. + * Diagnostics is rate limited for improved usability, assumes + * that session feeds are consistent across calls. Processing + * would cope with inconsistent calls though when required. + */ outc = o->priv; buff = &outc->logic_buff; - if (length && unitsize != buff->zip_unit_size) { - sr_warn("Unexpected unit size, discarding logic data."); - return SR_ERR_ARG; + if (length) { + if (!sizes_seen) { + sr_info("output unit size %zu, feed unit size %zu.", + buff->zip_unit_size, feed_unitsize); + } + if (feed_unitsize > buff->zip_unit_size) { + if (!sizes_seen) + sr_info("Large unit size, discarding excess logic data."); + sample_copy_size = buff->zip_unit_size; + sample_skip_size = feed_unitsize - buff->zip_unit_size; + sample_pad_size = 0; + } else if (feed_unitsize < buff->zip_unit_size) { + if (!sizes_seen) + sr_info("Small unit size, padding logic data."); + sample_copy_size = feed_unitsize; + sample_skip_size = 0; + sample_pad_size = buff->zip_unit_size - feed_unitsize; + } else { + if (!sizes_seen) + sr_dbg("Matching unit size, passing logic data as is."); + sample_copy_size = buff->zip_unit_size; + sample_skip_size = 0; + sample_pad_size = 0; + } + if (sample_copy_size + sample_skip_size != feed_unitsize) { + sr_err("Inconsistent input unit size. Implementation flaw?"); + return SR_ERR_BUG; + } + if (sample_copy_size + sample_pad_size != buff->zip_unit_size) { + sr_err("Inconsistent output unit size. Implementation flaw?"); + return SR_ERR_BUG; + } + sizes_seen = TRUE; } /* @@ -418,16 +458,24 @@ static int zip_append_queue(const struct sr_output *o, * Flush to the ZIP archive when the buffer space is exhausted. */ rdptr = buf; - send_count = buff->zip_unit_size ? length / buff->zip_unit_size : 0; + send_count = feed_unitsize ? length / feed_unitsize : 0; while (send_count) { remain = buff->alloc_size - buff->fill_size; if (remain) { wrptr = &buff->samples[buff->fill_size * buff->zip_unit_size]; copy_count = MIN(send_count, remain); + if (sample_skip_size || sample_pad_size) + copy_count = 1; send_count -= copy_count; buff->fill_size += copy_count; - memcpy(wrptr, rdptr, copy_count * buff->zip_unit_size); - rdptr += copy_count * buff->zip_unit_size; + memcpy(wrptr, rdptr, copy_count * sample_copy_size); + if (sample_pad_size) { + wrptr += sample_copy_size; + memset(wrptr, 0, sample_pad_size); + } + rdptr += copy_count * sample_copy_size; + if (sample_skip_size) + rdptr += sample_skip_size; remain -= copy_count; } if (send_count && !remain) { -- 2.30.2 From da175133ede9385cb4555f1e326333100abb35a2 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Fri, 29 Dec 2023 12:39:05 +0100 Subject: [PATCH 14/16] output/srzip: reduce text line length, remove "dead code" Move an instruction to reduce its text line length. Also happens to put the calculation of remaining buffer space and the current write position in closer proximity, improving maintainability in the process. Remove an assignment after appending to the archive and before iterating the input samples loop again. Eliminates code that never took effect. The value gets determined at the loop body's start anyway. --- src/output/srzip.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/output/srzip.c b/src/output/srzip.c index c1e2e438..3be0bccb 100644 --- a/src/output/srzip.c +++ b/src/output/srzip.c @@ -461,8 +461,8 @@ static int zip_append_queue(const struct sr_output *o, send_count = feed_unitsize ? length / feed_unitsize : 0; while (send_count) { remain = buff->alloc_size - buff->fill_size; + wrptr = &buff->samples[buff->fill_size * buff->zip_unit_size]; if (remain) { - wrptr = &buff->samples[buff->fill_size * buff->zip_unit_size]; copy_count = MIN(send_count, remain); if (sample_skip_size || sample_pad_size) copy_count = 1; @@ -484,7 +484,6 @@ static int zip_append_queue(const struct sr_output *o, if (ret != SR_OK) return ret; buff->fill_size = 0; - remain = buff->alloc_size - buff->fill_size; } } -- 2.30.2 From 0fd3ed06a75d57178330b854a29bd119996b1a08 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 1 Jan 2024 14:26:25 +0100 Subject: [PATCH 15/16] input/protocoldata: silence build warnings, adjust printf formats Properly use %zu for size_t, and %PRIu64 for uint64_t data types. This silences build warnings which previously went unnoticed because their occurance depends on the target platform. --- src/input/protocoldata.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/input/protocoldata.c b/src/input/protocoldata.c index 148048ea..905e33e4 100644 --- a/src/input/protocoldata.c +++ b/src/input/protocoldata.c @@ -607,7 +607,7 @@ static int assign_bit_widths(struct context *inc) bit_times_total += bit_time_int; sr_spew("Bit %zu, width %" PRIu64 ".", idx, bit_time_int); } - sr_dbg("Maximum waveform width: %zu slots, %.2f / %zu samples.", + sr_dbg("Maximum waveform width: %zu slots, %.2f / %" PRIu64 " samples.", inc->max_frame_bits, bit_edge, bit_times_total); return SR_OK; @@ -879,7 +879,7 @@ static int uart_check_opts(struct context *inc) total_bits += fmt_opts->stopbit_count; total_bits += fmt_opts->half_stopbit ? 1 : 0; total_bits += UART_ADD_IDLEBITS; - sr_dbg("UART frame: total bits %lu.", total_bits); + sr_dbg("UART frame: total bits %zu.", total_bits); if (total_bits > UART_MAX_WAVELEN) return SR_ERR_DATA; inc->max_frame_bits = total_bits; @@ -1550,7 +1550,7 @@ static int spi_check_opts(struct context *inc) total_bits += 2 * fmt_opts->databit_count; total_bits += 3; - sr_dbg("SPI frame: total bits %lu.", total_bits); + sr_dbg("SPI frame: total bits %zu.", total_bits); if (total_bits > SPI_MAX_WAVELEN) return SR_ERR_DATA; inc->max_frame_bits = total_bits; @@ -2170,7 +2170,7 @@ static int i2c_check_opts(struct context *inc) total_bits *= I2C_BITTIME_QUANTA; total_bits += I2C_ADD_IDLESLOTS; - sr_dbg("I2C frame: total bits %lu.", total_bits); + sr_dbg("I2C frame: total bits %zu.", total_bits); if (total_bits > I2C_MAX_WAVELEN) return SR_ERR_DATA; inc->max_frame_bits = total_bits; -- 2.30.2 From b503d24cdf56abf8c0d66d438ccac28969f01670 Mon Sep 17 00:00:00 2001 From: Gerhard Sittig Date: Mon, 1 Jan 2024 14:37:50 +0100 Subject: [PATCH 16/16] output/csv: use intermediate time_t var, silence compiler warning There are platforms where timeval and time_t disagree on the width of the data type of the field which holds seconds. Passing a pointer to an unexpected type results in warnings (and probably unreliable execution). Assign the value which is gotten from a timeval to an intermediate time_t variable, so that the ctime() invocation becomes portable. --- src/output/csv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/output/csv.c b/src/output/csv.c index 848595f9..c4801ef7 100644 --- a/src/output/csv.c +++ b/src/output/csv.c @@ -252,11 +252,13 @@ static GString *gen_header(const struct sr_output *o, /* Some metadata */ if (ctx->header && !ctx->did_header) { /* save_gnuplot knows how many lines we print. */ + time_t secs; + secs = hdr->starttime.tv_sec; g_string_append_printf(header, "%s CSV generated by %s %s\n%s from %s on %s", ctx->comment, PACKAGE_NAME, sr_package_version_string_get(), ctx->comment, - ctx->title, ctime(&hdr->starttime.tv_sec)); + ctx->title, ctime(&secs)); /* Columns / channels */ channels = o->sdi ? o->sdi->channels : NULL; -- 2.30.2