From f91fb2a2b3664de43b27eab46bc9cd42cc022492 Mon Sep 17 00:00:00 2001 From: Frederic Borry Date: Thu, 27 Jun 2024 00:30:05 +0200 Subject: [PATCH 1/9] Added support for SDS2000X HD models based on the work of gralco (Eric Kuzmenko) in this PR : github.com/sigrokproject/libsigrok/pull/176/ Created a new protocol version "E11" matching the latest Siglent SDS Scope programming guide. Reduced the read-wait time from 7sec to 50ms for better performance (achived by looping on read sample logic to consume the data has it arrives). Tested with SDS2504X HD model connected via Ethernet cable. --- .gitignore | 1 + src/hardware/siglent-sds/api.c | 36 +- src/hardware/siglent-sds/protocol.c | 488 ++++++++++++++++++++++------ src/hardware/siglent-sds/protocol.h | 9 +- 4 files changed, 427 insertions(+), 107 deletions(-) diff --git a/.gitignore b/.gitignore index 235d51c2c..e183f1804 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,4 @@ stamp-h? /tests/*.log /tests/*.trs /tests/main +.vscode/ diff --git a/src/hardware/siglent-sds/api.c b/src/hardware/siglent-sds/api.c index 76955e6da..73bd15e77 100644 --- a/src/hardware/siglent-sds/api.c +++ b/src/hardware/siglent-sds/api.c @@ -171,6 +171,8 @@ enum series { SDS1000XP, SDS1000XE, SDS2000X, + SDS2000XP, + SDS2000XHD, }; /* short name, full name */ @@ -183,19 +185,23 @@ static const struct siglent_sds_vendor supported_vendors[] = { * number of vertical divs, live waveform samples, memory buffer samples */ static const struct siglent_sds_series supported_series[] = { [SDS1000CML] = {VENDOR(SIGLENT), "SDS1000CML", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, [SDS1000CNL] = {VENDOR(SIGLENT), "SDS1000CNL", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, [SDS1000DL] = {VENDOR(SIGLENT), "SDS1000DL", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, [SDS1000X] = {VENDOR(SIGLENT), "SDS1000X", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, [SDS1000XP] = {VENDOR(SIGLENT), "SDS1000X+", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, [SDS1000XE] = {VENDOR(SIGLENT), "SDS1000XE", ESERIES, - { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, [SDS2000X] = {VENDOR(SIGLENT), "SDS2000X", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, + [SDS2000XP] = {VENDOR(SIGLENT), "SDS2000X+", E11, + { 100, 1 }, { 500, 100000 }, 10, 8, 30, 14000363}, + [SDS2000XHD] = {VENDOR(SIGLENT), "SDS2000XHD", E11, + { 100, 1 }, { 500, 100000 }, 10, 8, 30, 14000363}, }; #define SERIES(x) &supported_series[x] @@ -227,6 +233,15 @@ static const struct siglent_sds_model supported_models[] = { { SERIES(SDS2000X), "SDS2204X", { 2, 1000000000 }, 4, FALSE, 0 }, { SERIES(SDS2000X), "SDS2302X", { 2, 1000000000 }, 2, FALSE, 0 }, { SERIES(SDS2000X), "SDS2304X", { 2, 1000000000 }, 4, FALSE, 0 }, + { SERIES(SDS2000XP), "SDS2102X Plus", { 1, 1000000000 }, 2, TRUE, 16 }, + { SERIES(SDS2000XP), "SDS2104X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XP), "SDS2204X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XP), "SDS2354X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XP), "SDS2504X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XHD), "SDS2104X HD", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XHD), "SDS2204X HD", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XHD), "SDS2354X HD", { 1, 1000000000 }, 4, TRUE, 16 }, + { SERIES(SDS2000XHD), "SDS2504X HD", { 1, 1000000000 }, 4, TRUE, 16 }, }; static struct sr_dev_driver siglent_sds_driver_info; @@ -770,6 +785,7 @@ static int config_list(uint32_t key, GVariant **data, break; case SPO_MODEL: case ESERIES: + case E11: *data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources)); break; } @@ -860,7 +876,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) siglent_sds_get_dev_cfg_horizontal(sdi); switch (devc->model->series->protocol) { case SPO_MODEL: - if (siglent_sds_config_set(sdi, "WFSU SP,0,TYPE,1") != SR_OK) + case E11: + if (siglent_sds_config_set(sdi, "WFSU SP,0,NP,0,FP,0") != SR_OK) return SR_ERR; if (devc->average_enabled) { if (siglent_sds_config_set(sdi, "ACQW AVERAGE,%i", devc->average_samples) != SR_OK) @@ -881,7 +898,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) break; } - sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 7000, + int tiemout = (devc->model->series->protocol == E11) ? 50 : 7000; + sr_scpi_source_add(sdi->session, scpi, G_IO_IN, tiemout, siglent_sds_receive, (void *) sdi); std_session_send_df_header(sdi); diff --git a/src/hardware/siglent-sds/protocol.c b/src/hardware/siglent-sds/protocol.c index d59e52cbc..7f4d389c4 100644 --- a/src/hardware/siglent-sds/protocol.c +++ b/src/hardware/siglent-sds/protocol.c @@ -159,6 +159,7 @@ SR_PRIV int siglent_sds_capture_start(const struct sr_dev_inst *sdi) switch (devc->model->series->protocol) { case SPO_MODEL: + case E11: if (devc->data_source == DATA_SOURCE_SCREEN) { char *buf; int out; @@ -167,13 +168,22 @@ SR_PRIV int siglent_sds_capture_start(const struct sr_dev_inst *sdi) devc->num_frames + 1, devc->limit_frames); if (siglent_sds_config_set(sdi, "ARM") != SR_OK) return SR_ERR; + if (devc->model->series->protocol == E11) { + /* This pause is necessary for large memory depths. */ + struct sr_channel *ch = devc->channel_entry->data; + if (ch->type == SR_CHANNEL_ANALOG) { + float wait = devc->memory_depth_analog / 100; + sr_spew("Waiting %.f ms for the instrument to enter ARM mode.", wait / 1000); + g_usleep(wait); + } + } if (sr_scpi_get_string(sdi->conn, ":INR?", &buf) != SR_OK) return SR_ERR; sr_atoi(buf, &out); g_free(buf); - if (out == DEVICE_STATE_TRIG_RDY) { + if (out == DEVICE_STATE_TRIG_RDY || ((devc->model->series->protocol == E11) && (out == DEVICE_STATE_STOPPED))) { siglent_sds_set_wait_event(devc, WAIT_TRIGGER); - } else if (out == DEVICE_STATE_DATA_TRIG_RDY) { + } else if (out == DEVICE_STATE_DATA_TRIG_RDY || ((devc->model->series->protocol == E11) && (out == DEVICE_STATE_DATA_ACQ))) { sr_spew("Device triggered."); siglent_sds_set_wait_event(devc, WAIT_BLOCK); return SR_OK; @@ -288,6 +298,19 @@ SR_PRIV int siglent_sds_channel_start(const struct sr_dev_inst *sdi) return SR_ERR; siglent_sds_set_wait_event(devc, WAIT_NONE); break; + case E11: + if (ch->type == SR_CHANNEL_LOGIC) { + if (sr_scpi_send(sdi->conn, "WAV:SOUR D%d", ch->index) != SR_OK) + return SR_ERR; + } + else { + if (sr_scpi_send(sdi->conn, "WAV:SOUR C%d", ch->index + 1) != SR_OK) + return SR_ERR; + } + if (sr_scpi_send(sdi->conn, "WAV:PRE?") != SR_OK) + return SR_ERR; + siglent_sds_set_wait_event(devc, WAIT_NONE); + break; case ESERIES: if (ch->type == SR_CHANNEL_ANALOG) { if (sr_scpi_send(sdi->conn, "C%d:WF? ALL", @@ -304,6 +327,7 @@ SR_PRIV int siglent_sds_channel_start(const struct sr_dev_inst *sdi) devc->num_channel_bytes = 0; devc->num_header_bytes = 0; devc->num_block_bytes = 0; + devc->num_bytes_current_block = 0; return SR_OK; } @@ -315,12 +339,13 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) struct dev_context *devc = sdi->priv; char *buf = (char *)devc->buffer; int ret, desc_length; - int block_offset = 15; /* Offset for descriptor block. */ + int block_offset = (devc->model->series->protocol == E11) ? 11 : 15; /* Offset for descriptor block. */ long data_length = 0; /* Read header from device. */ - ret = sr_scpi_read_data(scpi, buf, SIGLENT_HEADER_SIZE); - if (ret < SIGLENT_HEADER_SIZE) { + int header_size = (devc->model->series->protocol == E11) ? (SIGLENT_DIG_HEADER_SIZE+block_offset+1 /*+1 for 0x0A footer */) : SIGLENT_HEADER_SIZE; ; /* Size of the header, defined in wave_desc_length. */ + ret = sr_scpi_read_data(scpi, buf, header_size); + if (ret < header_size) { sr_err("Read error while reading data header."); return SR_ERR; } @@ -332,7 +357,7 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) memcpy(&desc_length, buf + 36, 4); /* Descriptor block length */ memcpy(&data_length, buf + 60, 4); /* Data block length */ - devc->block_header_size = desc_length + 15; + devc->block_header_size = desc_length + block_offset; devc->num_samples = data_length; sr_dbg("Received data block header: '%s' -> block length %d.", buf, ret); @@ -340,100 +365,255 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) return ret; } +static int siglent_sds_get_digital_e11(struct sr_dev_inst *sdi, struct sr_channel *ch, uint8_t samplerate_ratio, GArray *data_low_channels, GArray *data_high_channels, gboolean* low_channels, gboolean* high_channels) +{ + uint8_t tmp_value; /* Holding temp value from data */ + GSList *l; + GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ + GArray *buffdata; + gboolean first_pass = TRUE; + struct sr_scpi_dev_inst *scpi = sdi->conn; + struct dev_context *devc = sdi->priv; + int len = 0; + int channel_index = 0; + uint64_t samples_index; + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + samples_index = 0; + if (ch->type == SR_CHANNEL_LOGIC) { + if (ch->enabled) { + do { + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + if (sr_scpi_send(sdi->conn, "WAV:SOUR D%d", ch->index) != SR_OK) + return SR_ERR; + if (sr_scpi_send(sdi->conn, "WAV:STARt %d", devc->num_block_bytes) != SR_OK) + return SR_ERR; + if (sr_scpi_send(sdi->conn, "WAV:DATA?") != SR_OK) + return SR_ERR; + // TODO factorize consume header + /* Read header size : The header is of form “#9000001000” which nine ASCII integers are used to give the number of the waveform data points (1000 pts). */ + sr_scpi_read_data(scpi, (char *)devc->buffer, 2); + int headerSize = devc->buffer[1]-'0'; + /* Conume header */ + sr_scpi_read_data(scpi, (char *)devc->buffer, headerSize); + do { + len = sr_scpi_read_data(scpi, (char *)(devc->buffer + devc->num_bytes_current_block), devc->num_samples-devc->num_bytes_current_block); + if (len == -1 || len == 0) { + sr_err("Read error, aborting capture."); + std_session_send_df_frame_end(sdi); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; + } + devc->num_block_bytes += len; + devc->num_bytes_current_block += len; + // sr_dbg("Read %" PRIu64 " bytes, %" PRIu64 " remaining.",devc->num_bytes_current_block, devc->num_samples - devc->num_bytes_current_block); + } while (devc->num_bytes_current_block < devc->num_samples); + /* Consume 0x0A 0x0A message footer */ + uint16_t footer; + sr_scpi_read_data(scpi, (char *)&footer, 2); + + if (first_pass) + buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_bytes_current_block); + g_array_append_vals(buffdata, (char *)(devc->buffer), devc->num_bytes_current_block); + + devc->num_block_read++; + devc->num_bytes_current_block = 0; + + if (first_pass) + tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_block_bytes*samplerate_ratio); /* New temp buffer. */ + first_pass = FALSE; + sr_err("Iterate on samples : number = %" PRIu64".",devc->num_block_bytes); + for (uint64_t cur_sample_index = 0; cur_sample_index < (unsigned)devc->num_block_bytes; cur_sample_index++) { + char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); + for (int ii = 0; ii < 8; ii++, sample >>= 1) { + if (ch->index < 8) { + channel_index = ch->index; + if (data_low_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + (*low_channels) = TRUE; /* We have at least one enabled low channel. */ + } else { + /* Get previous stored sample from low channel buffer. */ + tmp_value = g_array_index(data_low_channels, uint8_t, samples_index*samplerate_ratio); + } + } else { + channel_index = ch->index - 8; + if (data_high_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + (*high_channels) = TRUE; /* We have at least one enabled high channel. */ + } else { + /* Get previous stored sample from high channel buffer. */ + tmp_value = g_array_index(data_high_channels, uint8_t, samples_index*samplerate_ratio); + } + } + /* Check if the current scope sample bit is set. */ + if (sample & 0x1) { + tmp_value |= (1UL << channel_index); /* Set current scope sample bit based on channel index. */ + } + + + g_array_append_val(tmp_samplebuf, tmp_value); + + /* SDS2000X+: Since the LA sample rate is a fraction of the sample rate of the analog channels, + * there needs to be repeated "fake" samples inserted after each "real" sample + * in order to make the output match the timebase of an enabled analog channel. + * The scaling by a factor of 2.5 and 5 appears to be necessary due to an artifact + * where the instrument will present half of the entire sample quantity from the screen + * within a single block (625000 bytes, or 5000000 bits / samples). Which means there + * are some legitimate points missing that are filled with "fake" ones at larger timebases. */ + for (int i = 0; i < samplerate_ratio-1; i++, ii++) + g_array_append_val(tmp_samplebuf, tmp_value); + + samples_index++; + } + } + } while (devc->num_block_bytes < devc->num_samples); + + /* Clear the buffers to prepare for the new samples */ + if (ch->index < 8) { + g_free(g_array_steal(data_low_channels,NULL)); + } else { + g_free(g_array_steal(data_high_channels,NULL)); + } + + /* Storing the converted temp values from the the scope into the buffers. */ + for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { + uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); + if (ch->index < 8) + g_array_append_val(data_low_channels, value); + else + g_array_append_val(data_high_channels, value); + } + devc->num_block_bytes = 0; + g_free(g_array_steal(tmp_samplebuf, NULL)); + g_free(g_array_steal(buffdata, NULL)); + } + } + } + return len; +} + static int siglent_sds_get_digital(const struct sr_dev_inst *sdi, struct sr_channel *ch) { struct sr_scpi_dev_inst *scpi = sdi->conn; struct dev_context *devc = sdi->priv; - GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ char *buf = (char *)devc->buffer; /* Buffer from scope */ - uint8_t tmp_value; /* Holding temp value from data */ - GArray *data_low_channels, *data_high_channels, *buffdata; - GSList *l; + GArray *data_low_channels, *data_high_channels; gboolean low_channels; /* Lower channels enabled */ gboolean high_channels; /* Higher channels enabled */ - int len, channel_index; + int len; uint64_t samples_index; + uint8_t samplerate_ratio = 1; + + if (devc->model->series->protocol == E11) { + /* Read Pre header */ + siglent_sds_read_header(sdi); + char *cmd; + float fvalue; + float digital_samplerate; + cmd = g_strdup_printf("DIG:SRAT?"); + int res = sr_scpi_get_float(sdi->conn, cmd, &fvalue); + g_free(cmd); + if (res != SR_OK) { + return SR_ERR; + } + digital_samplerate = (long)fvalue; + samplerate_ratio = devc->samplerate / (digital_samplerate / 8); + devc->memory_depth_digital = devc->memory_depth_digital / samplerate_ratio; + sr_dbg("Digital configuration : memory depth = %" PRIu64 ", sammple rate = %f, digital sample rate = %f, sample ratio = %d.", + devc->memory_depth_digital,devc->samplerate,digital_samplerate,samplerate_ratio); + } + len = 0; - channel_index = 0; low_channels = FALSE; high_channels = FALSE; data_low_channels = g_array_new(FALSE, TRUE, sizeof(uint8_t)); data_high_channels = g_array_new(FALSE, TRUE, sizeof(uint8_t)); - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - samples_index = 0; - if (ch->type != SR_CHANNEL_LOGIC) - continue; - if (!ch->enabled) - continue; - if (sr_scpi_send(sdi->conn, "D%d:WF? DAT2", ch->index) != SR_OK) - return SR_ERR; - if (sr_scpi_read_begin(scpi) != SR_OK) - return TRUE; - len = sr_scpi_read_data(scpi, buf, -1); - if (len < 0) - return TRUE; - len -= 15; - buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); - buf += 15; /* Skipping the data header. */ - g_array_append_vals(buffdata, buf, len); - tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); /* New temp buffer. */ - for (uint64_t cur_sample_index = 0; cur_sample_index < devc->memory_depth_digital; cur_sample_index++) { - char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); - for (int ii = 0; ii < 8; ii++, sample >>= 1) { - if (ch->index < 8) { - channel_index = ch->index; - if (data_low_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - low_channels = TRUE; /* We have at least one enabled low channel. */ - } else { - /* Get previous stored sample from low channel buffer. */ - tmp_value = g_array_index(data_low_channels, uint8_t, samples_index); - } - } else { - channel_index = ch->index - 8; - if (data_high_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - high_channels = TRUE; /* We have at least one enabled high channel. */ + if(devc->model->series->protocol == E11) { + len = siglent_sds_get_digital_e11(sdi,ch,samplerate_ratio,data_low_channels,data_high_channels,&low_channels,&high_channels); + } + else { + uint8_t tmp_value; /* Holding temp value from data */ + GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ + GSList *l; + GArray *buffdata; + int channel_index = 0; + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + samples_index = 0; + if (ch->type != SR_CHANNEL_LOGIC) + continue; + if (!ch->enabled) + continue; + if (sr_scpi_send(sdi->conn, "D%d:WF? DAT2", ch->index) != SR_OK) + return SR_ERR; + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + len = sr_scpi_read_data(scpi, buf, -1); + if (len < 0) + return TRUE; + len -= 15; + buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); + buf += 15; /* Skipping the data header. */ + g_array_append_vals(buffdata, buf, len); + tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); /* New temp buffer. */ + for (uint64_t cur_sample_index = 0; cur_sample_index < devc->memory_depth_digital; cur_sample_index++) { + char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); + for (int ii = 0; ii < 8; ii++, sample >>= 1) { + if (ch->index < 8) { + channel_index = ch->index; + if (data_low_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + low_channels = TRUE; /* We have at least one enabled low channel. */ + } else { + /* Get previous stored sample from low channel buffer. */ + tmp_value = g_array_index(data_low_channels, uint8_t, samples_index); + } } else { - /* Get previous stored sample from high channel buffer. */ - tmp_value = g_array_index(data_high_channels, uint8_t, samples_index); + channel_index = ch->index - 8; + if (data_high_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + high_channels = TRUE; /* We have at least one enabled high channel. */ + } else { + /* Get previous stored sample from high channel buffer. */ + tmp_value = g_array_index(data_high_channels, uint8_t, samples_index); + } } + /* Check if the current scope sample bit is set. */ + if (sample & 0x1) + tmp_value |= 1UL << channel_index; /* Set current scope sample bit based on channel index. */ + g_array_append_val(tmp_samplebuf, tmp_value); + samples_index++; } - /* Check if the current scope sample bit is set. */ - if (sample & 0x1) - tmp_value |= 1UL << channel_index; /* Set current scope sample bit based on channel index. */ - g_array_append_val(tmp_samplebuf, tmp_value); - samples_index++; } - } - /* Clear the buffers to prepare for the new samples */ - if (ch->index < 8) { - g_array_free(data_low_channels, TRUE); - data_low_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - } else { - g_array_free(data_high_channels, TRUE); - data_high_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - } + /* Clear the buffers to prepare for the new samples */ + if (ch->index < 8) { + g_array_free(data_low_channels, TRUE); + data_low_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } else { + g_array_free(data_high_channels, TRUE); + data_high_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } - /* Storing the converted temp values from the the scope into the buffers. */ - for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { - uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); - if (ch->index < 8) - g_array_append_val(data_low_channels, value); - else - g_array_append_val(data_high_channels, value); + /* Storing the converted temp values from the the scope into the buffers. */ + for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { + uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); + if (ch->index < 8) + g_array_append_val(data_low_channels, value); + else + g_array_append_val(data_high_channels, value); + } + g_array_free(tmp_samplebuf, TRUE); + g_array_free(buffdata, TRUE); } - g_array_free(tmp_samplebuf, TRUE); - g_array_free(buffdata, TRUE); } /* Combining the lower and higher channel buffers into one buffer for sigrok. */ devc->dig_buffer = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - for (uint64_t index = 0; index < devc->memory_depth_digital; index++) { + for (uint64_t index = 0; index < devc->memory_depth_digital * samplerate_ratio; index++) { uint8_t value; if (low_channels) { value = g_array_index(data_low_channels, uint8_t, index); @@ -534,6 +714,10 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) sr_dbg("Waiting %.f0 ms for device to prepare the output buffers", wait / 1000); g_usleep(wait); break; + case E11: + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + break; } sr_dbg("New block with header expected."); @@ -547,7 +731,9 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) sdi->driver->dev_acquisition_stop(sdi); return TRUE; } - devc->num_block_bytes = len; + if(devc->model->series->protocol != E11) { + devc->num_block_bytes = len; + } devc->num_block_read = 0; if (len == -1) { @@ -563,20 +749,44 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) /* We received all data as one block. */ /* Offset the data block buffer past the IEEE header and description header. */ devc->buffer += devc->block_header_size; - len = devc->num_samples; + devc->num_bytes_current_block = devc->num_samples; } else { - sr_dbg("Requesting: %" PRIu64 " bytes.", devc->num_samples - devc->num_block_bytes); - len = sr_scpi_read_data(scpi, (char *)devc->buffer, devc->num_samples-devc->num_block_bytes); - if (len == -1) { - sr_err("Read error, aborting capture."); - std_session_send_df_frame_end(sdi); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; + sr_dbg("Requesting: %" PRIu64 " bytes for %" PRIu64 " samples.", devc->num_samples - devc->num_block_bytes,devc->num_samples); + /* SDS2000X+ sends 10MB or 5MB blocks, as found by "WAV:MAXPoint?". */ + /* It needs to have the next starting point specified to continue. */ + if (devc->model->series->protocol == E11 && (devc->num_block_bytes == 0)) { + /*if (sr_scpi_send(sdi->conn, "WAV:SOUR C%d", ch->index + 1) != SR_OK) + return SR_ERR;*/ + /* TODO handle multiple blocks for E11 prtocol => use ACQuire:POINts? and WAVeform:MAXPoint? commands to get total points and points per block */ + if (sr_scpi_send(sdi->conn, "WAV:STARt %d", devc->num_block_bytes) != SR_OK) + return SR_ERR; + if (sr_scpi_send(sdi->conn, "WAV:DATA?") != SR_OK) + return SR_ERR; + /* Read header size : The header is of form “#9000001000” which nine ASCII integers are used to give the number of the waveform data points (1000 pts). */ + sr_scpi_read_data(scpi, (char *)devc->buffer, 2); + int headerSize = devc->buffer[1]-'0'; + /* Conume header */ + sr_scpi_read_data(scpi, (char *)devc->buffer, headerSize); + } + do { + len = sr_scpi_read_data(scpi, (char *)(devc->buffer + devc->num_bytes_current_block), devc->num_samples-devc->num_bytes_current_block); + if (len == -1 || len == 0) { + sr_err("Read error, aborting capture."); + std_session_send_df_frame_end(sdi); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; + } + devc->num_block_bytes += len; + devc->num_bytes_current_block += len; + sr_dbg("Read %" PRIu64 " bytes, %" PRIu64 " remaining.",devc->num_bytes_current_block, devc->num_samples - devc->num_bytes_current_block); + } while (devc->model->series->protocol == E11 && (devc->num_bytes_current_block < devc->num_samples)); + if(devc->model->series->protocol == E11) { + /* Consume 0x0A 0x0A message footer */ + uint16_t footer; + sr_scpi_read_data(scpi, (char *)&footer, 2); } - devc->num_block_read++; - devc->num_block_bytes += len; } - sr_dbg("Received block: %i, %d bytes.", devc->num_block_read, len); + sr_dbg("Received block: %i, %d bytes.", devc->num_block_read, devc->num_bytes_current_block); if (ch->type == SR_CHANNEL_ANALOG) { float vdiv = devc->vdiv[ch->index]; float offset = devc->vert_offset[ch->index]; @@ -585,11 +795,11 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) float voltage, vdivlog; int digits; - data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); - g_array_append_vals(data, devc->buffer, len); + data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_bytes_current_block); + g_array_append_vals(data, devc->buffer, devc->num_bytes_current_block); float_data = g_array_new(FALSE, FALSE, sizeof(float)); - for (i = 0; i < len; i++) { - voltage = (float)g_array_index(data, int8_t, i) / 25; + for (i = 0; i < devc->num_bytes_current_block; i++) { + voltage = (float)g_array_index(data, int8_t, i) / devc->model->series->code_per_div; voltage = ((vdiv * voltage) - offset); g_array_append_val(float_data, voltage); } @@ -608,17 +818,23 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) g_slist_free(analog.meaning->channels); g_array_free(data, TRUE); } + devc->num_block_read++; + devc->num_bytes_current_block = 0; len = 0; - if (devc->num_samples == (devc->num_block_bytes - SIGLENT_HEADER_SIZE)) { + uint64_t bytes_to_read = devc->num_samples - ((devc->model->series->protocol == E11) ? (devc->num_block_bytes) : (devc->num_block_bytes - SIGLENT_HEADER_SIZE)); + sr_dbg("Total samples: %" PRIu64 "; bytes already read %" PRIu64 "; bytes left to read: %" PRIu64 " bytes.",devc->num_samples, devc->num_block_bytes, bytes_to_read); + if (bytes_to_read <= 0) { sr_dbg("Transfer has been completed."); devc->num_header_bytes = 0; devc->num_block_bytes = 0; read_complete = TRUE; if (!sr_scpi_read_complete(scpi)) { - sr_err("Read should have been completed."); - std_session_send_df_frame_end(sdi); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; + sr_err("Reading CH%d should have been completed.", ch->index + 1); + if (!devc->channel_entry->next) { + std_session_send_df_frame_end(sdi); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; + } } devc->num_block_read = 0; } else { @@ -741,7 +957,7 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) } /* Timebase. */ - if (sr_scpi_get_float(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) + if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) return SR_ERR; sr_dbg("Current timebase: %g.", devc->timebase); @@ -915,6 +1131,12 @@ SR_PRIV int siglent_sds_get_dev_cfg_horizontal(const struct sr_dev_inst *sdi) } samplerate_scope = fvalue * 10000; } else { + sample_points_string[strlen(sample_points_string)] = '\0'; + if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { + sr_dbg("Invalid float converted from scope response."); + g_free(sample_points_string); + return SR_ERR; + } samplerate_scope = fvalue; } g_free(sample_points_string); @@ -933,10 +1155,82 @@ SR_PRIV int siglent_sds_get_dev_cfg_horizontal(const struct sr_dev_inst *sdi) } g_free(cmd); break; + case E11: { + double previous_timebase = devc->timebase; + /* Get the timebase. */ + if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) + return SR_ERR; + cmd = g_strdup_printf("SANU? C1"); + + /* SDS2000X+: If capturing from the display when the channels or timebase changed + * then quickly trigger and stop to get the correct memory depth. + * This is done due to the number of sample points not being updated after + * the after a channel is enabled/disabled or the timebase changes. */ + if (devc->data_source == DATA_SOURCE_SCREEN && + (devc->channels_switched || devc->timebase != previous_timebase)) { + if (sr_scpi_send(sdi->conn, "TRIG_MODE SINGLE") != SR_OK) + return SR_ERR; + res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); + if (devc->la_enabled) { + cmd = g_strdup_printf("SANU? D0"); + if (sr_scpi_get_float(sdi->conn, cmd, &fvalue) != SR_OK) + return SR_ERR; + devc->memory_depth_digital = (long)fvalue; + } + if (sr_scpi_send(sdi->conn, ":TRIG:STOP") != SR_OK) + return SR_ERR; + devc->channels_switched = FALSE; + } + else { + res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); + if (devc->la_enabled) { + cmd = g_strdup_printf("SANU? D0"); + if (sr_scpi_get_float(sdi->conn, cmd, &fvalue) != SR_OK) + return SR_ERR; + devc->memory_depth_digital = (long)fvalue; + } + } + g_free(cmd); + // TODO : refacto this part with SPO/NON-SPO models + samplerate_scope = 0; + fvalue = 0; + if (res != SR_OK) { + g_free(sample_points_string); + return SR_ERR; + } + if (g_strstr_len(sample_points_string, -1, "Mpts") != NULL) { + sample_points_string[strlen(sample_points_string) - 4] = '\0'; + if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { + sr_dbg("Invalid float converted from scope response."); + g_free(sample_points_string); + return SR_ERR; + } + samplerate_scope = fvalue * 1000000; + } else if (g_strstr_len(sample_points_string, -1, "Kpts") != NULL) { + sample_points_string[strlen(sample_points_string) - 4] = '\0'; + if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { + sr_dbg("Invalid float converted from scope response."); + g_free(sample_points_string); + return SR_ERR; + } + samplerate_scope = fvalue * 10000; + } else { + sample_points_string[strlen(sample_points_string)] = '\0'; + if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { + sr_dbg("Invalid float converted from scope response."); + g_free(sample_points_string); + return SR_ERR; + } + samplerate_scope = fvalue; + } + g_free(sample_points_string); + devc->memory_depth_analog = samplerate_scope; + break; + } }; /* Get the timebase. */ - if (sr_scpi_get_float(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) + if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) return SR_ERR; sr_dbg("Current timebase: %g.", devc->timebase); diff --git a/src/hardware/siglent-sds/protocol.h b/src/hardware/siglent-sds/protocol.h index 89abaf640..a38c9f7e0 100644 --- a/src/hardware/siglent-sds/protocol.h +++ b/src/hardware/siglent-sds/protocol.h @@ -49,6 +49,9 @@ enum protocol_version { SPO_MODEL, NON_SPO_MODEL, ESERIES, + // Refers to E11 Siglent Programming Guide : + // https://www.siglenteu.com/wp-content/uploads/dlm_uploads/2024/03/ProgrammingGuide_EN11F.pdf + E11, }; enum data_source { @@ -69,6 +72,7 @@ struct siglent_sds_series { uint64_t min_vdiv[2]; int num_horizontal_divs; int num_vertical_divs; + int code_per_div; int buffer_samples; }; @@ -120,7 +124,8 @@ struct dev_context { gboolean analog_channels[MAX_ANALOG_CHANNELS]; gboolean digital_channels[MAX_DIGITAL_CHANNELS]; gboolean la_enabled; - float timebase; + gboolean channels_switched; + double timebase; float attenuation[MAX_ANALOG_CHANNELS]; float vdiv[MAX_ANALOG_CHANNELS]; int vert_reference[MAX_ANALOG_CHANNELS]; @@ -143,6 +148,8 @@ struct dev_context { uint64_t num_header_bytes; /* Number of data blocks bytes already read. */ uint64_t num_block_bytes; + /* Number of data bytes already read in the current block. */ + uint64_t num_bytes_current_block; /* Number of data blocks read. */ int num_block_read; /* What to wait for in *_receive. */ From ac86ac6928242796952b8f147f1d2ba1640167dd Mon Sep 17 00:00:00 2001 From: Frederic Borry Date: Mon, 22 Jul 2024 12:14:32 +0200 Subject: [PATCH 2/9] Added support for DHO 800/900 models Based on the work of Diana Ellefson (OrionOth) : https://github.com/sigrokproject/libsigrok/pull/229 and RemiNV : https://github.com/sigrokproject/libsigrok/commit/3430e8ececf579205c782eb173b3cf425712b858 --- contrib/60-libsigrok.rules | 6 ++ src/hardware/rigol-ds/api.c | 112 ++++++++++++++++++++++++++----- src/hardware/rigol-ds/protocol.c | 77 ++++++++++++++++----- src/hardware/rigol-ds/protocol.h | 1 + 4 files changed, 163 insertions(+), 33 deletions(-) diff --git a/contrib/60-libsigrok.rules b/contrib/60-libsigrok.rules index b6ac3ba04..29e545d42 100644 --- a/contrib/60-libsigrok.rules +++ b/contrib/60-libsigrok.rules @@ -249,6 +249,12 @@ ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0e11", ENV{ID_SIGROK}="1" # Rigol MSO5000 series ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0515", ENV{ID_SIGROK}="1" +# Rigol DHO800 series +ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044d", ENV{ID_SIGROK}="1" + +# Rigol DHO800 and DHO900 series +ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044c", ENV{ID_SIGROK}="1" + # Rohde&Schwarz HMO series mixed-signal oscilloscope (previously branded Hameg) VCP/USBTMC mode ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0117", ENV{ID_SIGROK}="1" ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", ENV{ID_SIGROK}="1" diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index 6703d1cea..b1f6e1570 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -105,6 +105,7 @@ static const uint64_t timebases[][2] = { static const uint64_t vdivs[][2] = { /* microvolts */ + { 200, 1000000 }, { 500, 1000000 }, /* millivolts */ { 1, 1000 }, @@ -185,6 +186,8 @@ enum series { DS4000, MSO5000, MSO7000A, + DHO800, + DHO900, }; /* short name, full name */ @@ -217,6 +220,10 @@ static const struct rigol_ds_series supported_series[] = { {1000, 1}, {500, 1000000}, 10, 1000, 0}, [MSO7000A] = {VENDOR(AGILENT), "MSO7000A", PROTOCOL_V4, FORMAT_IEEE488_2, {50, 1}, {2, 1000}, 10, 1000, 8000000}, + [DHO800] = {VENDOR(RIGOL), "DHO800", PROTOCOL_V6, FORMAT_IEEE488_2, + {500, 1}, {500, 1000000}, 10, 1000, 0}, + [DHO900] = {VENDOR(RIGOL), "DHO900", PROTOCOL_V6, FORMAT_IEEE488_2, + {500, 1}, {200, 1000000}, 10, 1000, 0}, }; #define SERIES(x) &supported_series[x] @@ -291,6 +298,14 @@ static const struct rigol_ds_model supported_models[] = { {SERIES(MSO5000), "MSO5354", {1, 1000000000}, CH_INFO(4, true), std_cmd}, /* TODO: Digital channels are not yet supported on MSO7000A. */ {SERIES(MSO7000A), "MSO7034A", {2, 1000000000}, CH_INFO(4, false), mso7000a_cmd}, + {SERIES(DHO800), "DHO802", {5, 1000000000}, CH_INFO(2, false), std_cmd}, + {SERIES(DHO800), "DHO804", {5, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO800), "DHO812", {5, 1000000000}, CH_INFO(2, false), std_cmd}, + {SERIES(DHO800), "DHO814", {5, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO900), "DHO914", {2, 1000000000}, CH_INFO(4, true), std_cmd}, + {SERIES(DHO900), "DHO914S", {2, 1000000000}, CH_INFO(4, true), std_cmd}, + {SERIES(DHO900), "DHO924", {2, 1000000000}, CH_INFO(4, true), std_cmd}, + {SERIES(DHO900), "DHO924S", {2, 1000000000}, CH_INFO(4, true), std_cmd}, }; static struct sr_dev_driver rigol_ds_driver_info; @@ -913,20 +928,45 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) some_digital = TRUE; /* Turn on LA module if currently off. */ if (!devc->la_enabled) { - if (rigol_ds_config_set(sdi, protocol >= PROTOCOL_V3 ? - ":LA:STAT ON" : ":LA:DISP ON") != SR_OK) + switch (protocol) { + case PROTOCOL_V1: + case PROTOCOL_V2: + cmd = ":LA:DISP ON"; + break; + case PROTOCOL_V3: + case PROTOCOL_V4: + case PROTOCOL_V5: + cmd = ":LA:STAT ON"; + break; + case PROTOCOL_V6: + default: + cmd = ":LA:ENAB ON"; + break; + } + if (rigol_ds_config_set(sdi, cmd) != SR_OK) return SR_ERR; devc->la_enabled = TRUE; } } if (ch->enabled != devc->digital_channels[ch->index]) { /* Enabled channel is currently disabled, or vice versa. */ - if (protocol >= PROTOCOL_V5) - cmd = ":LA:DISP D%d,%s"; - else if (protocol >= PROTOCOL_V3) - cmd = ":LA:DIG%d:DISP %s"; - else - cmd = ":DIG%d:TURN %s"; + switch (protocol) { + case PROTOCOL_V1: + case PROTOCOL_V2: + cmd = ":DIG%d:TURN %s"; + break; + case PROTOCOL_V3: + case PROTOCOL_V4: + cmd = ":LA:DIG%d:DISP %s"; + break; + case PROTOCOL_V5: + cmd = ":LA:DISP D%d,%s"; + break; + case PROTOCOL_V6: + default: + cmd = ":LA:DIG:ENAB D%d,%s"; + break; + } if (rigol_ds_config_set(sdi, cmd, ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) @@ -940,10 +980,29 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return SR_ERR; /* Turn off LA module if on and no digital channels selected. */ - if (devc->la_enabled && !some_digital) - if (rigol_ds_config_set(sdi, - devc->model->series->protocol >= PROTOCOL_V3 ? - ":LA:STAT OFF" : ":LA:DISP OFF") != SR_OK) + if (devc->la_enabled && !some_digital) { + switch (protocol) { + case PROTOCOL_V1: + case PROTOCOL_V2: + cmd = ":LA:DISP OFF"; + break; + case PROTOCOL_V3: + case PROTOCOL_V4: + case PROTOCOL_V5: + cmd = ":LA:STAT OFF"; + break; + case PROTOCOL_V6: + default: + cmd = ":LA:ENAB OFF"; + break; + } + if (rigol_ds_config_set(sdi, cmd) != SR_OK) + return SR_ERR; + } + + /* For DHO scopes, trigger must be in stop mode to start memory or segmented acquisition */ + if((protocol == PROTOCOL_V6)&&((devc->data_source == DATA_SOURCE_SEGMENTED)||(devc->data_source == DATA_SOURCE_MEMORY))) + if (rigol_ds_config_set(sdi, ":STOP") != SR_OK) return SR_ERR; /* Set memory mode. */ @@ -969,10 +1028,28 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc->num_frames_segmented = frames; break; } + case PROTOCOL_V6: + /* DHO scopes need to be in UltraAcquire mode for segmented acquisoton */ + /* This command is not working as for firmware version v00.01.02.00.02 of 2023/12/28 + the scope has to be put manually in UltraAcquire mode for segmented acquisition to work */ + //if (rigol_ds_config_set(sdi, ":ACQ:TYPE ULTR") != SR_OK) + // return SR_ERR; */ + + int frames = 0; + //if (sr_scpi_get_int(sdi->conn, ":REC:FRAM?", &frames) != SR_OK) + if (sr_scpi_get_int(sdi->conn, ":ACQ:ULTR:MAXF?", &frames) != SR_OK) + return SR_ERR; + if (frames <= 0) { + sr_err("No segmented data available"); + return SR_ERR; + } + devc->num_frames_segmented = frames; + /* Continue with REC:CURR command */ + // fall through case PROTOCOL_V5: /* The frame limit has to be read on the fly, just set up * reading of the first frame */ - if (rigol_ds_config_set(sdi, "REC:CURR 1") != SR_OK) + if (rigol_ds_config_set(sdi, ":REC:CURR 1") != SR_OK) return SR_ERR; break; default: @@ -984,7 +1061,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc->analog_frame_size = analog_frame_size(sdi); devc->digital_frame_size = digital_frame_size(sdi); - switch (devc->model->series->protocol) { + switch (protocol) { case PROTOCOL_V2: if (rigol_ds_config_set(sdi, ":ACQ:MEMD LONG") != SR_OK) return SR_ERR; @@ -1021,7 +1098,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) (devc->timebase * devc->model->series->num_horizontal_divs); } else { float xinc; - if (devc->model->series->protocol < PROTOCOL_V3) { + if (protocol < PROTOCOL_V3) { sr_err("Cannot get samplerate (below V3)."); return SR_ERR; } @@ -1037,8 +1114,9 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc->sample_rate = 1. / xinc; } - if (rigol_ds_capture_start(sdi) != SR_OK) - return SR_ERR; + ret = rigol_ds_capture_start(sdi); + if (ret != SR_OK) + return ret; /* Start of first frame. */ std_session_send_df_frame_begin(sdi); diff --git a/src/hardware/rigol-ds/protocol.c b/src/hardware/rigol-ds/protocol.c index 05aaf113f..f82ec4140 100644 --- a/src/hardware/rigol-ds/protocol.c +++ b/src/hardware/rigol-ds/protocol.c @@ -324,10 +324,13 @@ SR_PRIV int rigol_ds_config_set(const struct sr_dev_inst *sdi, const char *forma return SR_ERR; if (devc->model->series->protocol == PROTOCOL_V2) { - /* The DS1000 series needs this stupid delay, *OPC? doesn't work. */ + /* The DS1000 series needs this stupid delay, *OPC? doesn't work.*/ sr_spew("delay %dms", 100); g_usleep(100 * 1000); return SR_OK; + } else if (devc->model->series->protocol == PROTOCOL_V6) { + /* Same goes for DHO series but they can handle faster response...*/ + return SR_OK; } else { return sr_scpi_get_opc(sdi->conn); } @@ -385,6 +388,7 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi) case PROTOCOL_V3: case PROTOCOL_V4: case PROTOCOL_V5: + case PROTOCOL_V6: if (first_frame && rigol_ds_config_set(sdi, ":WAV:FORM BYTE") != SR_OK) return SR_ERR; if (devc->data_source == DATA_SOURCE_LIVE) { @@ -417,13 +421,23 @@ SR_PRIV int rigol_ds_capture_start(const struct sr_dev_inst *sdi) buffer_samples = devc->model->series->buffer_samples; if (first_frame && buffer_samples == 0) { - /* The DS4000 series does not have a fixed memory depth, it + /* The DS4000 and DHO series does not have a fixed memory depth, it * can be chosen from the menu and also varies with number * of active channels. Retrieve the actual number with the * ACQ:MDEP command. */ sr_scpi_get_int(sdi->conn, "ACQ:MDEP?", &buffer_samples); + /* TODO : what about digital channels ? */ devc->analog_frame_size = devc->digital_frame_size = buffer_samples; + + /* For some reason, as for DHO firmware version v00.01.02.00.02 of 2023/12/28, + * segmented acquisition does not work over multiple data blocks : DATA? command on a frame + * portion results in a header, declaring an empty content, of the form '#9000000000'. */ + if(devc->data_source == DATA_SOURCE_SEGMENTED && devc->analog_frame_size > ACQ_BLOCK_SIZE) { + sr_err("Data source 'Segmented' not supported for memory depth > %d points.",ACQ_BLOCK_SIZE); + return SR_ERR_NA; + } + } else if (first_frame) { @@ -499,6 +513,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) break; case PROTOCOL_V4: case PROTOCOL_V5: + case PROTOCOL_V6: if (ch->type == SR_CHANNEL_ANALOG) { if (rigol_ds_config_set(sdi, ":WAV:SOUR CHAN%d", ch->index + 1) != SR_OK) @@ -514,7 +529,7 @@ SR_PRIV int rigol_ds_channel_start(const struct sr_dev_inst *sdi) ":WAV:MODE NORM" :":WAV:MODE RAW") != SR_OK) return SR_ERR; - if (devc->data_source != DATA_SOURCE_LIVE) { + if ((devc->data_source != DATA_SOURCE_LIVE) && (devc->model->series->protocol != PROTOCOL_V6)) { if (rigol_ds_config_set(sdi, ":WAV:RES") != SR_OK) return SR_ERR; } @@ -669,17 +684,17 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) if (devc->num_block_bytes == 0) { if (devc->model->series->protocol >= PROTOCOL_V4) { - if (first_frame && rigol_ds_config_set(sdi, ":WAV:START %d", + if ((first_frame || (devc->model->series->protocol == PROTOCOL_V6)) && rigol_ds_config_set(sdi, ":WAV:START %d", devc->num_channel_bytes + 1) != SR_OK) return TRUE; - if (first_frame && rigol_ds_config_set(sdi, ":WAV:STOP %d", + if ((first_frame || (devc->model->series->protocol == PROTOCOL_V6)) && rigol_ds_config_set(sdi, ":WAV:STOP %d", MIN(devc->num_channel_bytes + ACQ_BLOCK_SIZE, devc->analog_frame_size)) != SR_OK) return TRUE; } if (devc->model->series->protocol >= PROTOCOL_V3) { - if (rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK) + if ((devc->model->series->protocol != PROTOCOL_V6) && rigol_ds_config_set(sdi, ":WAV:BEG") != SR_OK) return TRUE; if (sr_scpi_send(sdi->conn, ":WAV:DATA?") != SR_OK) return TRUE; @@ -846,6 +861,13 @@ SR_PRIV int rigol_ds_receive(int fd, int revents, void *cb_data) /* Get the next frame, starting with the first channel. */ devc->channel_entry = devc->enabled_channels; + if (devc->data_source == DATA_SOURCE_SEGMENTED && + devc->model->series->protocol == PROTOCOL_V6) { + /* Move to next frame in segmented mode*/ + if (rigol_ds_config_set(sdi, ":REC:CURR %d", devc->num_frames + 1) != SR_OK) + return SR_ERR; + } + rigol_ds_capture_start(sdi); /* Start of next frame. */ @@ -882,20 +904,43 @@ SR_PRIV int rigol_ds_get_dev_cfg(const struct sr_dev_inst *sdi) /* Digital channel state. */ if (devc->model->has_digital) { - if (sr_scpi_get_bool(sdi->conn, - devc->model->series->protocol >= PROTOCOL_V3 ? - ":LA:STAT?" : ":LA:DISP?", - &devc->la_enabled) != SR_OK) + switch (devc->model->series->protocol) { + case PROTOCOL_V1: + case PROTOCOL_V2: + cmd = ":LA:DISP?"; + break; + case PROTOCOL_V3: + case PROTOCOL_V4: + case PROTOCOL_V5: + cmd = ":LA:STAT?"; + break; + case PROTOCOL_V6: + default: + cmd = ":LA:ENAB?"; + break; + } + if (sr_scpi_get_bool(sdi->conn, cmd, &devc->la_enabled) != SR_OK) return SR_ERR; sr_dbg("Logic analyzer %s, current digital channel state:", devc->la_enabled ? "enabled" : "disabled"); for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) { - if (devc->model->series->protocol >= PROTOCOL_V5) - cmd = g_strdup_printf(":LA:DISP? D%d", i); - else if (devc->model->series->protocol >= PROTOCOL_V3) - cmd = g_strdup_printf(":LA:DIG%d:DISP?", i); - else - cmd = g_strdup_printf(":DIG%d:TURN?", i); + switch (devc->model->series->protocol) { + case PROTOCOL_V1: + case PROTOCOL_V2: + cmd = g_strdup_printf(":DIG%d:TURN?", i); + break; + case PROTOCOL_V3: + case PROTOCOL_V4: + cmd = g_strdup_printf(":LA:DIG%d:DISP?", i); + break; + case PROTOCOL_V5: + cmd = g_strdup_printf(":LA:DISP? D%d", i); + break; + case PROTOCOL_V6: + default: + cmd = g_strdup_printf(":LA:DIG:ENAB? D%d", i); + break; + } res = sr_scpi_get_bool(sdi->conn, cmd, &devc->digital_channels[i]); g_free(cmd); if (res != SR_OK) diff --git a/src/hardware/rigol-ds/protocol.h b/src/hardware/rigol-ds/protocol.h index e2efffa22..dbfbf1464 100644 --- a/src/hardware/rigol-ds/protocol.h +++ b/src/hardware/rigol-ds/protocol.h @@ -43,6 +43,7 @@ enum protocol_version { PROTOCOL_V3, /* DS2000, DSO1000 */ PROTOCOL_V4, /* DS1000Z */ PROTOCOL_V5, /* MSO5000 */ + PROTOCOL_V6, /* DHO800, DHO900 */ }; enum data_format { From 5118d4f691c4d8acbe72798ce4c50f35b9f28011 Mon Sep 17 00:00:00 2001 From: Frederic Borry Date: Sun, 28 Jul 2024 01:47:28 +0200 Subject: [PATCH 3/9] Fixed compilation issue on Mac OS --- src/hardware/rigol-ds/api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index b1f6e1570..e00c797a3 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -1029,6 +1029,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) break; } case PROTOCOL_V6: + { /* DHO scopes need to be in UltraAcquire mode for segmented acquisoton */ /* This command is not working as for firmware version v00.01.02.00.02 of 2023/12/28 the scope has to be put manually in UltraAcquire mode for segmented acquisition to work */ @@ -1046,6 +1047,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) devc->num_frames_segmented = frames; /* Continue with REC:CURR command */ // fall through + } case PROTOCOL_V5: /* The frame limit has to be read on the fly, just set up * reading of the first frame */ From da13e8389b0b750581351aed909bbbc81110670c Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 5 Aug 2024 14:04:50 +0200 Subject: [PATCH 4/9] Added support for DHO1000/DHO4000 series --- src/hardware/rigol-ds/api.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index e00c797a3..604d94df8 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -188,6 +188,8 @@ enum series { MSO7000A, DHO800, DHO900, + DHO1000, + DHO4000, }; /* short name, full name */ @@ -224,6 +226,10 @@ static const struct rigol_ds_series supported_series[] = { {500, 1}, {500, 1000000}, 10, 1000, 0}, [DHO900] = {VENDOR(RIGOL), "DHO900", PROTOCOL_V6, FORMAT_IEEE488_2, {500, 1}, {200, 1000000}, 10, 1000, 0}, + [DHO1000] = {VENDOR(RIGOL), "DHO1000", PROTOCOL_V6, FORMAT_IEEE488_2, + {500, 1}, {500, 1000000}, 10, 1000, 0}, + [DHO4000] = {VENDOR(RIGOL), "DHO4000", PROTOCOL_V6, FORMAT_IEEE488_2, + {500, 1}, {100, 1000000}, 10, 1000, 0}, }; #define SERIES(x) &supported_series[x] @@ -306,6 +312,15 @@ static const struct rigol_ds_model supported_models[] = { {SERIES(DHO900), "DHO914S", {2, 1000000000}, CH_INFO(4, true), std_cmd}, {SERIES(DHO900), "DHO924", {2, 1000000000}, CH_INFO(4, true), std_cmd}, {SERIES(DHO900), "DHO924S", {2, 1000000000}, CH_INFO(4, true), std_cmd}, + {SERIES(DHO1000), "DHO1072", {2, 1000000000}, CH_INFO(2, false), std_cmd}, + {SERIES(DHO1000), "DHO1074", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO1000), "DHO1102", {2, 1000000000}, CH_INFO(2, false), std_cmd}, + {SERIES(DHO1000), "DHO1104", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO1000), "DHO1202", {2, 1000000000}, CH_INFO(2, false), std_cmd}, + {SERIES(DHO1000), "DHO1204", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO1074", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO1104", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO1204", {2, 1000000000}, CH_INFO(4, false), std_cmd}, }; static struct sr_dev_driver rigol_ds_driver_info; @@ -1046,8 +1061,8 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) } devc->num_frames_segmented = frames; /* Continue with REC:CURR command */ - // fall through } + // fall through case PROTOCOL_V5: /* The frame limit has to be read on the fly, just set up * reading of the first frame */ From e2db8bf8ee8728c0c8eb816b40fb9131d6e388b2 Mon Sep 17 00:00:00 2001 From: fredzo Date: Mon, 5 Aug 2024 14:06:06 +0200 Subject: [PATCH 5/9] Fixed rigol driver label to match new supported models --- src/hardware/rigol-ds/api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index 604d94df8..f03661f8c 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -1160,7 +1160,7 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi) static struct sr_dev_driver rigol_ds_driver_info = { .name = "rigol-ds", - .longname = "Rigol DS", + .longname = "Rigol DS/DHO", .api_version = 1, .init = std_init, .cleanup = std_cleanup, From 990138dff8218fbc7bd39fc183c7e3d76d971516 Mon Sep 17 00:00:00 2001 From: fredzo Date: Wed, 7 Aug 2024 14:50:11 +0200 Subject: [PATCH 6/9] Added Rigol DHO1000 device id --- contrib/60-libsigrok.rules | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/60-libsigrok.rules b/contrib/60-libsigrok.rules index 29e545d42..8c357f223 100644 --- a/contrib/60-libsigrok.rules +++ b/contrib/60-libsigrok.rules @@ -255,6 +255,9 @@ ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044d", ENV{ID_SIGROK}="1" # Rigol DHO800 and DHO900 series ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="044c", ENV{ID_SIGROK}="1" +# Rigol DHO1000 series +ATTRS{idVendor}=="1ab1", ATTRS{idProduct}=="0610", ENV{ID_SIGROK}="1" + # Rohde&Schwarz HMO series mixed-signal oscilloscope (previously branded Hameg) VCP/USBTMC mode ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0117", ENV{ID_SIGROK}="1" ATTRS{idVendor}=="0aad", ATTRS{idProduct}=="0118", ENV{ID_SIGROK}="1" From 878cac5ef0dde2713d37bcf494ba0fa581e2ca90 Mon Sep 17 00:00:00 2001 From: fredzo Date: Wed, 7 Aug 2024 17:26:51 +0200 Subject: [PATCH 7/9] Reverted changes from Siglent branch included by mistake --- src/hardware/siglent-sds/api.c | 36 +- src/hardware/siglent-sds/protocol.c | 488 ++++++---------------------- src/hardware/siglent-sds/protocol.h | 9 +- 3 files changed, 107 insertions(+), 426 deletions(-) diff --git a/src/hardware/siglent-sds/api.c b/src/hardware/siglent-sds/api.c index 73bd15e77..76955e6da 100644 --- a/src/hardware/siglent-sds/api.c +++ b/src/hardware/siglent-sds/api.c @@ -171,8 +171,6 @@ enum series { SDS1000XP, SDS1000XE, SDS2000X, - SDS2000XP, - SDS2000XHD, }; /* short name, full name */ @@ -185,23 +183,19 @@ static const struct siglent_sds_vendor supported_vendors[] = { * number of vertical divs, live waveform samples, memory buffer samples */ static const struct siglent_sds_series supported_series[] = { [SDS1000CML] = {VENDOR(SIGLENT), "SDS1000CML", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, [SDS1000CNL] = {VENDOR(SIGLENT), "SDS1000CNL", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, [SDS1000DL] = {VENDOR(SIGLENT), "SDS1000DL", NON_SPO_MODEL, - { 50, 1 }, { 2, 1000 }, 18, 8, 25, 1400363}, + { 50, 1 }, { 2, 1000 }, 18, 8, 1400363}, [SDS1000X] = {VENDOR(SIGLENT), "SDS1000X", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, [SDS1000XP] = {VENDOR(SIGLENT), "SDS1000X+", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, [SDS1000XE] = {VENDOR(SIGLENT), "SDS1000XE", ESERIES, - { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, [SDS2000X] = {VENDOR(SIGLENT), "SDS2000X", SPO_MODEL, - { 50, 1 }, { 500, 100000 }, 14, 8, 25, 14000363}, - [SDS2000XP] = {VENDOR(SIGLENT), "SDS2000X+", E11, - { 100, 1 }, { 500, 100000 }, 10, 8, 30, 14000363}, - [SDS2000XHD] = {VENDOR(SIGLENT), "SDS2000XHD", E11, - { 100, 1 }, { 500, 100000 }, 10, 8, 30, 14000363}, + { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, }; #define SERIES(x) &supported_series[x] @@ -233,15 +227,6 @@ static const struct siglent_sds_model supported_models[] = { { SERIES(SDS2000X), "SDS2204X", { 2, 1000000000 }, 4, FALSE, 0 }, { SERIES(SDS2000X), "SDS2302X", { 2, 1000000000 }, 2, FALSE, 0 }, { SERIES(SDS2000X), "SDS2304X", { 2, 1000000000 }, 4, FALSE, 0 }, - { SERIES(SDS2000XP), "SDS2102X Plus", { 1, 1000000000 }, 2, TRUE, 16 }, - { SERIES(SDS2000XP), "SDS2104X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XP), "SDS2204X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XP), "SDS2354X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XP), "SDS2504X Plus", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XHD), "SDS2104X HD", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XHD), "SDS2204X HD", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XHD), "SDS2354X HD", { 1, 1000000000 }, 4, TRUE, 16 }, - { SERIES(SDS2000XHD), "SDS2504X HD", { 1, 1000000000 }, 4, TRUE, 16 }, }; static struct sr_dev_driver siglent_sds_driver_info; @@ -785,7 +770,6 @@ static int config_list(uint32_t key, GVariant **data, break; case SPO_MODEL: case ESERIES: - case E11: *data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources)); break; } @@ -876,8 +860,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) siglent_sds_get_dev_cfg_horizontal(sdi); switch (devc->model->series->protocol) { case SPO_MODEL: - case E11: - if (siglent_sds_config_set(sdi, "WFSU SP,0,NP,0,FP,0") != SR_OK) + if (siglent_sds_config_set(sdi, "WFSU SP,0,TYPE,1") != SR_OK) return SR_ERR; if (devc->average_enabled) { if (siglent_sds_config_set(sdi, "ACQW AVERAGE,%i", devc->average_samples) != SR_OK) @@ -898,8 +881,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) break; } - int tiemout = (devc->model->series->protocol == E11) ? 50 : 7000; - sr_scpi_source_add(sdi->session, scpi, G_IO_IN, tiemout, + sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 7000, siglent_sds_receive, (void *) sdi); std_session_send_df_header(sdi); diff --git a/src/hardware/siglent-sds/protocol.c b/src/hardware/siglent-sds/protocol.c index 7f4d389c4..d59e52cbc 100644 --- a/src/hardware/siglent-sds/protocol.c +++ b/src/hardware/siglent-sds/protocol.c @@ -159,7 +159,6 @@ SR_PRIV int siglent_sds_capture_start(const struct sr_dev_inst *sdi) switch (devc->model->series->protocol) { case SPO_MODEL: - case E11: if (devc->data_source == DATA_SOURCE_SCREEN) { char *buf; int out; @@ -168,22 +167,13 @@ SR_PRIV int siglent_sds_capture_start(const struct sr_dev_inst *sdi) devc->num_frames + 1, devc->limit_frames); if (siglent_sds_config_set(sdi, "ARM") != SR_OK) return SR_ERR; - if (devc->model->series->protocol == E11) { - /* This pause is necessary for large memory depths. */ - struct sr_channel *ch = devc->channel_entry->data; - if (ch->type == SR_CHANNEL_ANALOG) { - float wait = devc->memory_depth_analog / 100; - sr_spew("Waiting %.f ms for the instrument to enter ARM mode.", wait / 1000); - g_usleep(wait); - } - } if (sr_scpi_get_string(sdi->conn, ":INR?", &buf) != SR_OK) return SR_ERR; sr_atoi(buf, &out); g_free(buf); - if (out == DEVICE_STATE_TRIG_RDY || ((devc->model->series->protocol == E11) && (out == DEVICE_STATE_STOPPED))) { + if (out == DEVICE_STATE_TRIG_RDY) { siglent_sds_set_wait_event(devc, WAIT_TRIGGER); - } else if (out == DEVICE_STATE_DATA_TRIG_RDY || ((devc->model->series->protocol == E11) && (out == DEVICE_STATE_DATA_ACQ))) { + } else if (out == DEVICE_STATE_DATA_TRIG_RDY) { sr_spew("Device triggered."); siglent_sds_set_wait_event(devc, WAIT_BLOCK); return SR_OK; @@ -298,19 +288,6 @@ SR_PRIV int siglent_sds_channel_start(const struct sr_dev_inst *sdi) return SR_ERR; siglent_sds_set_wait_event(devc, WAIT_NONE); break; - case E11: - if (ch->type == SR_CHANNEL_LOGIC) { - if (sr_scpi_send(sdi->conn, "WAV:SOUR D%d", ch->index) != SR_OK) - return SR_ERR; - } - else { - if (sr_scpi_send(sdi->conn, "WAV:SOUR C%d", ch->index + 1) != SR_OK) - return SR_ERR; - } - if (sr_scpi_send(sdi->conn, "WAV:PRE?") != SR_OK) - return SR_ERR; - siglent_sds_set_wait_event(devc, WAIT_NONE); - break; case ESERIES: if (ch->type == SR_CHANNEL_ANALOG) { if (sr_scpi_send(sdi->conn, "C%d:WF? ALL", @@ -327,7 +304,6 @@ SR_PRIV int siglent_sds_channel_start(const struct sr_dev_inst *sdi) devc->num_channel_bytes = 0; devc->num_header_bytes = 0; devc->num_block_bytes = 0; - devc->num_bytes_current_block = 0; return SR_OK; } @@ -339,13 +315,12 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) struct dev_context *devc = sdi->priv; char *buf = (char *)devc->buffer; int ret, desc_length; - int block_offset = (devc->model->series->protocol == E11) ? 11 : 15; /* Offset for descriptor block. */ + int block_offset = 15; /* Offset for descriptor block. */ long data_length = 0; /* Read header from device. */ - int header_size = (devc->model->series->protocol == E11) ? (SIGLENT_DIG_HEADER_SIZE+block_offset+1 /*+1 for 0x0A footer */) : SIGLENT_HEADER_SIZE; ; /* Size of the header, defined in wave_desc_length. */ - ret = sr_scpi_read_data(scpi, buf, header_size); - if (ret < header_size) { + ret = sr_scpi_read_data(scpi, buf, SIGLENT_HEADER_SIZE); + if (ret < SIGLENT_HEADER_SIZE) { sr_err("Read error while reading data header."); return SR_ERR; } @@ -357,7 +332,7 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) memcpy(&desc_length, buf + 36, 4); /* Descriptor block length */ memcpy(&data_length, buf + 60, 4); /* Data block length */ - devc->block_header_size = desc_length + block_offset; + devc->block_header_size = desc_length + 15; devc->num_samples = data_length; sr_dbg("Received data block header: '%s' -> block length %d.", buf, ret); @@ -365,255 +340,100 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) return ret; } -static int siglent_sds_get_digital_e11(struct sr_dev_inst *sdi, struct sr_channel *ch, uint8_t samplerate_ratio, GArray *data_low_channels, GArray *data_high_channels, gboolean* low_channels, gboolean* high_channels) -{ - uint8_t tmp_value; /* Holding temp value from data */ - GSList *l; - GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ - GArray *buffdata; - gboolean first_pass = TRUE; - struct sr_scpi_dev_inst *scpi = sdi->conn; - struct dev_context *devc = sdi->priv; - int len = 0; - int channel_index = 0; - uint64_t samples_index; - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - samples_index = 0; - if (ch->type == SR_CHANNEL_LOGIC) { - if (ch->enabled) { - do { - if (sr_scpi_read_begin(scpi) != SR_OK) - return TRUE; - if (sr_scpi_send(sdi->conn, "WAV:SOUR D%d", ch->index) != SR_OK) - return SR_ERR; - if (sr_scpi_send(sdi->conn, "WAV:STARt %d", devc->num_block_bytes) != SR_OK) - return SR_ERR; - if (sr_scpi_send(sdi->conn, "WAV:DATA?") != SR_OK) - return SR_ERR; - // TODO factorize consume header - /* Read header size : The header is of form “#9000001000” which nine ASCII integers are used to give the number of the waveform data points (1000 pts). */ - sr_scpi_read_data(scpi, (char *)devc->buffer, 2); - int headerSize = devc->buffer[1]-'0'; - /* Conume header */ - sr_scpi_read_data(scpi, (char *)devc->buffer, headerSize); - do { - len = sr_scpi_read_data(scpi, (char *)(devc->buffer + devc->num_bytes_current_block), devc->num_samples-devc->num_bytes_current_block); - if (len == -1 || len == 0) { - sr_err("Read error, aborting capture."); - std_session_send_df_frame_end(sdi); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } - devc->num_block_bytes += len; - devc->num_bytes_current_block += len; - // sr_dbg("Read %" PRIu64 " bytes, %" PRIu64 " remaining.",devc->num_bytes_current_block, devc->num_samples - devc->num_bytes_current_block); - } while (devc->num_bytes_current_block < devc->num_samples); - /* Consume 0x0A 0x0A message footer */ - uint16_t footer; - sr_scpi_read_data(scpi, (char *)&footer, 2); - - if (first_pass) - buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_bytes_current_block); - g_array_append_vals(buffdata, (char *)(devc->buffer), devc->num_bytes_current_block); - - devc->num_block_read++; - devc->num_bytes_current_block = 0; - - if (first_pass) - tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_block_bytes*samplerate_ratio); /* New temp buffer. */ - first_pass = FALSE; - sr_err("Iterate on samples : number = %" PRIu64".",devc->num_block_bytes); - for (uint64_t cur_sample_index = 0; cur_sample_index < (unsigned)devc->num_block_bytes; cur_sample_index++) { - char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); - for (int ii = 0; ii < 8; ii++, sample >>= 1) { - if (ch->index < 8) { - channel_index = ch->index; - if (data_low_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - (*low_channels) = TRUE; /* We have at least one enabled low channel. */ - } else { - /* Get previous stored sample from low channel buffer. */ - tmp_value = g_array_index(data_low_channels, uint8_t, samples_index*samplerate_ratio); - } - } else { - channel_index = ch->index - 8; - if (data_high_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - (*high_channels) = TRUE; /* We have at least one enabled high channel. */ - } else { - /* Get previous stored sample from high channel buffer. */ - tmp_value = g_array_index(data_high_channels, uint8_t, samples_index*samplerate_ratio); - } - } - /* Check if the current scope sample bit is set. */ - if (sample & 0x1) { - tmp_value |= (1UL << channel_index); /* Set current scope sample bit based on channel index. */ - } - - - g_array_append_val(tmp_samplebuf, tmp_value); - - /* SDS2000X+: Since the LA sample rate is a fraction of the sample rate of the analog channels, - * there needs to be repeated "fake" samples inserted after each "real" sample - * in order to make the output match the timebase of an enabled analog channel. - * The scaling by a factor of 2.5 and 5 appears to be necessary due to an artifact - * where the instrument will present half of the entire sample quantity from the screen - * within a single block (625000 bytes, or 5000000 bits / samples). Which means there - * are some legitimate points missing that are filled with "fake" ones at larger timebases. */ - for (int i = 0; i < samplerate_ratio-1; i++, ii++) - g_array_append_val(tmp_samplebuf, tmp_value); - - samples_index++; - } - } - } while (devc->num_block_bytes < devc->num_samples); - - /* Clear the buffers to prepare for the new samples */ - if (ch->index < 8) { - g_free(g_array_steal(data_low_channels,NULL)); - } else { - g_free(g_array_steal(data_high_channels,NULL)); - } - - /* Storing the converted temp values from the the scope into the buffers. */ - for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { - uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); - if (ch->index < 8) - g_array_append_val(data_low_channels, value); - else - g_array_append_val(data_high_channels, value); - } - devc->num_block_bytes = 0; - g_free(g_array_steal(tmp_samplebuf, NULL)); - g_free(g_array_steal(buffdata, NULL)); - } - } - } - return len; -} - static int siglent_sds_get_digital(const struct sr_dev_inst *sdi, struct sr_channel *ch) { struct sr_scpi_dev_inst *scpi = sdi->conn; struct dev_context *devc = sdi->priv; + GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ char *buf = (char *)devc->buffer; /* Buffer from scope */ - GArray *data_low_channels, *data_high_channels; + uint8_t tmp_value; /* Holding temp value from data */ + GArray *data_low_channels, *data_high_channels, *buffdata; + GSList *l; gboolean low_channels; /* Lower channels enabled */ gboolean high_channels; /* Higher channels enabled */ - int len; + int len, channel_index; uint64_t samples_index; - uint8_t samplerate_ratio = 1; - - if (devc->model->series->protocol == E11) { - /* Read Pre header */ - siglent_sds_read_header(sdi); - char *cmd; - float fvalue; - float digital_samplerate; - cmd = g_strdup_printf("DIG:SRAT?"); - int res = sr_scpi_get_float(sdi->conn, cmd, &fvalue); - g_free(cmd); - if (res != SR_OK) { - return SR_ERR; - } - digital_samplerate = (long)fvalue; - samplerate_ratio = devc->samplerate / (digital_samplerate / 8); - devc->memory_depth_digital = devc->memory_depth_digital / samplerate_ratio; - sr_dbg("Digital configuration : memory depth = %" PRIu64 ", sammple rate = %f, digital sample rate = %f, sample ratio = %d.", - devc->memory_depth_digital,devc->samplerate,digital_samplerate,samplerate_ratio); - } - len = 0; + channel_index = 0; low_channels = FALSE; high_channels = FALSE; data_low_channels = g_array_new(FALSE, TRUE, sizeof(uint8_t)); data_high_channels = g_array_new(FALSE, TRUE, sizeof(uint8_t)); - if(devc->model->series->protocol == E11) { - len = siglent_sds_get_digital_e11(sdi,ch,samplerate_ratio,data_low_channels,data_high_channels,&low_channels,&high_channels); - } - else { - uint8_t tmp_value; /* Holding temp value from data */ - GArray *tmp_samplebuf; /* Temp buffer while iterating over the scope samples */ - GSList *l; - GArray *buffdata; - int channel_index = 0; - for (l = sdi->channels; l; l = l->next) { - ch = l->data; - samples_index = 0; - if (ch->type != SR_CHANNEL_LOGIC) - continue; - if (!ch->enabled) - continue; - if (sr_scpi_send(sdi->conn, "D%d:WF? DAT2", ch->index) != SR_OK) - return SR_ERR; - if (sr_scpi_read_begin(scpi) != SR_OK) - return TRUE; - len = sr_scpi_read_data(scpi, buf, -1); - if (len < 0) - return TRUE; - len -= 15; - buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); - buf += 15; /* Skipping the data header. */ - g_array_append_vals(buffdata, buf, len); - tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); /* New temp buffer. */ - for (uint64_t cur_sample_index = 0; cur_sample_index < devc->memory_depth_digital; cur_sample_index++) { - char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); - for (int ii = 0; ii < 8; ii++, sample >>= 1) { - if (ch->index < 8) { - channel_index = ch->index; - if (data_low_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - low_channels = TRUE; /* We have at least one enabled low channel. */ - } else { - /* Get previous stored sample from low channel buffer. */ - tmp_value = g_array_index(data_low_channels, uint8_t, samples_index); - } + for (l = sdi->channels; l; l = l->next) { + ch = l->data; + samples_index = 0; + if (ch->type != SR_CHANNEL_LOGIC) + continue; + if (!ch->enabled) + continue; + if (sr_scpi_send(sdi->conn, "D%d:WF? DAT2", ch->index) != SR_OK) + return SR_ERR; + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + len = sr_scpi_read_data(scpi, buf, -1); + if (len < 0) + return TRUE; + len -= 15; + buffdata = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); + buf += 15; /* Skipping the data header. */ + g_array_append_vals(buffdata, buf, len); + tmp_samplebuf = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); /* New temp buffer. */ + for (uint64_t cur_sample_index = 0; cur_sample_index < devc->memory_depth_digital; cur_sample_index++) { + char sample = (char)g_array_index(buffdata, uint8_t, cur_sample_index); + for (int ii = 0; ii < 8; ii++, sample >>= 1) { + if (ch->index < 8) { + channel_index = ch->index; + if (data_low_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + low_channels = TRUE; /* We have at least one enabled low channel. */ } else { - channel_index = ch->index - 8; - if (data_high_channels->len <= samples_index) { - tmp_value = 0; /* New sample. */ - high_channels = TRUE; /* We have at least one enabled high channel. */ - } else { - /* Get previous stored sample from high channel buffer. */ - tmp_value = g_array_index(data_high_channels, uint8_t, samples_index); - } + /* Get previous stored sample from low channel buffer. */ + tmp_value = g_array_index(data_low_channels, uint8_t, samples_index); + } + } else { + channel_index = ch->index - 8; + if (data_high_channels->len <= samples_index) { + tmp_value = 0; /* New sample. */ + high_channels = TRUE; /* We have at least one enabled high channel. */ + } else { + /* Get previous stored sample from high channel buffer. */ + tmp_value = g_array_index(data_high_channels, uint8_t, samples_index); } - /* Check if the current scope sample bit is set. */ - if (sample & 0x1) - tmp_value |= 1UL << channel_index; /* Set current scope sample bit based on channel index. */ - g_array_append_val(tmp_samplebuf, tmp_value); - samples_index++; } + /* Check if the current scope sample bit is set. */ + if (sample & 0x1) + tmp_value |= 1UL << channel_index; /* Set current scope sample bit based on channel index. */ + g_array_append_val(tmp_samplebuf, tmp_value); + samples_index++; } + } - /* Clear the buffers to prepare for the new samples */ - if (ch->index < 8) { - g_array_free(data_low_channels, TRUE); - data_low_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - } else { - g_array_free(data_high_channels, TRUE); - data_high_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - } + /* Clear the buffers to prepare for the new samples */ + if (ch->index < 8) { + g_array_free(data_low_channels, TRUE); + data_low_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } else { + g_array_free(data_high_channels, TRUE); + data_high_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } - /* Storing the converted temp values from the the scope into the buffers. */ - for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { - uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); - if (ch->index < 8) - g_array_append_val(data_low_channels, value); - else - g_array_append_val(data_high_channels, value); - } - g_array_free(tmp_samplebuf, TRUE); - g_array_free(buffdata, TRUE); + /* Storing the converted temp values from the the scope into the buffers. */ + for (uint64_t index = 0; index < tmp_samplebuf->len; index++) { + uint8_t value = g_array_index(tmp_samplebuf, uint8_t, index); + if (ch->index < 8) + g_array_append_val(data_low_channels, value); + else + g_array_append_val(data_high_channels, value); } + g_array_free(tmp_samplebuf, TRUE); + g_array_free(buffdata, TRUE); } /* Combining the lower and higher channel buffers into one buffer for sigrok. */ devc->dig_buffer = g_array_new(FALSE, FALSE, sizeof(uint8_t)); - for (uint64_t index = 0; index < devc->memory_depth_digital * samplerate_ratio; index++) { + for (uint64_t index = 0; index < devc->memory_depth_digital; index++) { uint8_t value; if (low_channels) { value = g_array_index(data_low_channels, uint8_t, index); @@ -714,10 +534,6 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) sr_dbg("Waiting %.f0 ms for device to prepare the output buffers", wait / 1000); g_usleep(wait); break; - case E11: - if (sr_scpi_read_begin(scpi) != SR_OK) - return TRUE; - break; } sr_dbg("New block with header expected."); @@ -731,9 +547,7 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) sdi->driver->dev_acquisition_stop(sdi); return TRUE; } - if(devc->model->series->protocol != E11) { - devc->num_block_bytes = len; - } + devc->num_block_bytes = len; devc->num_block_read = 0; if (len == -1) { @@ -749,44 +563,20 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) /* We received all data as one block. */ /* Offset the data block buffer past the IEEE header and description header. */ devc->buffer += devc->block_header_size; - devc->num_bytes_current_block = devc->num_samples; + len = devc->num_samples; } else { - sr_dbg("Requesting: %" PRIu64 " bytes for %" PRIu64 " samples.", devc->num_samples - devc->num_block_bytes,devc->num_samples); - /* SDS2000X+ sends 10MB or 5MB blocks, as found by "WAV:MAXPoint?". */ - /* It needs to have the next starting point specified to continue. */ - if (devc->model->series->protocol == E11 && (devc->num_block_bytes == 0)) { - /*if (sr_scpi_send(sdi->conn, "WAV:SOUR C%d", ch->index + 1) != SR_OK) - return SR_ERR;*/ - /* TODO handle multiple blocks for E11 prtocol => use ACQuire:POINts? and WAVeform:MAXPoint? commands to get total points and points per block */ - if (sr_scpi_send(sdi->conn, "WAV:STARt %d", devc->num_block_bytes) != SR_OK) - return SR_ERR; - if (sr_scpi_send(sdi->conn, "WAV:DATA?") != SR_OK) - return SR_ERR; - /* Read header size : The header is of form “#9000001000” which nine ASCII integers are used to give the number of the waveform data points (1000 pts). */ - sr_scpi_read_data(scpi, (char *)devc->buffer, 2); - int headerSize = devc->buffer[1]-'0'; - /* Conume header */ - sr_scpi_read_data(scpi, (char *)devc->buffer, headerSize); - } - do { - len = sr_scpi_read_data(scpi, (char *)(devc->buffer + devc->num_bytes_current_block), devc->num_samples-devc->num_bytes_current_block); - if (len == -1 || len == 0) { - sr_err("Read error, aborting capture."); - std_session_send_df_frame_end(sdi); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } - devc->num_block_bytes += len; - devc->num_bytes_current_block += len; - sr_dbg("Read %" PRIu64 " bytes, %" PRIu64 " remaining.",devc->num_bytes_current_block, devc->num_samples - devc->num_bytes_current_block); - } while (devc->model->series->protocol == E11 && (devc->num_bytes_current_block < devc->num_samples)); - if(devc->model->series->protocol == E11) { - /* Consume 0x0A 0x0A message footer */ - uint16_t footer; - sr_scpi_read_data(scpi, (char *)&footer, 2); + sr_dbg("Requesting: %" PRIu64 " bytes.", devc->num_samples - devc->num_block_bytes); + len = sr_scpi_read_data(scpi, (char *)devc->buffer, devc->num_samples-devc->num_block_bytes); + if (len == -1) { + sr_err("Read error, aborting capture."); + std_session_send_df_frame_end(sdi); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; } + devc->num_block_read++; + devc->num_block_bytes += len; } - sr_dbg("Received block: %i, %d bytes.", devc->num_block_read, devc->num_bytes_current_block); + sr_dbg("Received block: %i, %d bytes.", devc->num_block_read, len); if (ch->type == SR_CHANNEL_ANALOG) { float vdiv = devc->vdiv[ch->index]; float offset = devc->vert_offset[ch->index]; @@ -795,11 +585,11 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) float voltage, vdivlog; int digits; - data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), devc->num_bytes_current_block); - g_array_append_vals(data, devc->buffer, devc->num_bytes_current_block); + data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), len); + g_array_append_vals(data, devc->buffer, len); float_data = g_array_new(FALSE, FALSE, sizeof(float)); - for (i = 0; i < devc->num_bytes_current_block; i++) { - voltage = (float)g_array_index(data, int8_t, i) / devc->model->series->code_per_div; + for (i = 0; i < len; i++) { + voltage = (float)g_array_index(data, int8_t, i) / 25; voltage = ((vdiv * voltage) - offset); g_array_append_val(float_data, voltage); } @@ -818,23 +608,17 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) g_slist_free(analog.meaning->channels); g_array_free(data, TRUE); } - devc->num_block_read++; - devc->num_bytes_current_block = 0; len = 0; - uint64_t bytes_to_read = devc->num_samples - ((devc->model->series->protocol == E11) ? (devc->num_block_bytes) : (devc->num_block_bytes - SIGLENT_HEADER_SIZE)); - sr_dbg("Total samples: %" PRIu64 "; bytes already read %" PRIu64 "; bytes left to read: %" PRIu64 " bytes.",devc->num_samples, devc->num_block_bytes, bytes_to_read); - if (bytes_to_read <= 0) { + if (devc->num_samples == (devc->num_block_bytes - SIGLENT_HEADER_SIZE)) { sr_dbg("Transfer has been completed."); devc->num_header_bytes = 0; devc->num_block_bytes = 0; read_complete = TRUE; if (!sr_scpi_read_complete(scpi)) { - sr_err("Reading CH%d should have been completed.", ch->index + 1); - if (!devc->channel_entry->next) { - std_session_send_df_frame_end(sdi); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } + sr_err("Read should have been completed."); + std_session_send_df_frame_end(sdi); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; } devc->num_block_read = 0; } else { @@ -957,7 +741,7 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) } /* Timebase. */ - if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) + if (sr_scpi_get_float(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) return SR_ERR; sr_dbg("Current timebase: %g.", devc->timebase); @@ -1131,12 +915,6 @@ SR_PRIV int siglent_sds_get_dev_cfg_horizontal(const struct sr_dev_inst *sdi) } samplerate_scope = fvalue * 10000; } else { - sample_points_string[strlen(sample_points_string)] = '\0'; - if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { - sr_dbg("Invalid float converted from scope response."); - g_free(sample_points_string); - return SR_ERR; - } samplerate_scope = fvalue; } g_free(sample_points_string); @@ -1155,82 +933,10 @@ SR_PRIV int siglent_sds_get_dev_cfg_horizontal(const struct sr_dev_inst *sdi) } g_free(cmd); break; - case E11: { - double previous_timebase = devc->timebase; - /* Get the timebase. */ - if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) - return SR_ERR; - cmd = g_strdup_printf("SANU? C1"); - - /* SDS2000X+: If capturing from the display when the channels or timebase changed - * then quickly trigger and stop to get the correct memory depth. - * This is done due to the number of sample points not being updated after - * the after a channel is enabled/disabled or the timebase changes. */ - if (devc->data_source == DATA_SOURCE_SCREEN && - (devc->channels_switched || devc->timebase != previous_timebase)) { - if (sr_scpi_send(sdi->conn, "TRIG_MODE SINGLE") != SR_OK) - return SR_ERR; - res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); - if (devc->la_enabled) { - cmd = g_strdup_printf("SANU? D0"); - if (sr_scpi_get_float(sdi->conn, cmd, &fvalue) != SR_OK) - return SR_ERR; - devc->memory_depth_digital = (long)fvalue; - } - if (sr_scpi_send(sdi->conn, ":TRIG:STOP") != SR_OK) - return SR_ERR; - devc->channels_switched = FALSE; - } - else { - res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); - if (devc->la_enabled) { - cmd = g_strdup_printf("SANU? D0"); - if (sr_scpi_get_float(sdi->conn, cmd, &fvalue) != SR_OK) - return SR_ERR; - devc->memory_depth_digital = (long)fvalue; - } - } - g_free(cmd); - // TODO : refacto this part with SPO/NON-SPO models - samplerate_scope = 0; - fvalue = 0; - if (res != SR_OK) { - g_free(sample_points_string); - return SR_ERR; - } - if (g_strstr_len(sample_points_string, -1, "Mpts") != NULL) { - sample_points_string[strlen(sample_points_string) - 4] = '\0'; - if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { - sr_dbg("Invalid float converted from scope response."); - g_free(sample_points_string); - return SR_ERR; - } - samplerate_scope = fvalue * 1000000; - } else if (g_strstr_len(sample_points_string, -1, "Kpts") != NULL) { - sample_points_string[strlen(sample_points_string) - 4] = '\0'; - if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { - sr_dbg("Invalid float converted from scope response."); - g_free(sample_points_string); - return SR_ERR; - } - samplerate_scope = fvalue * 10000; - } else { - sample_points_string[strlen(sample_points_string)] = '\0'; - if (sr_atof_ascii(sample_points_string, &fvalue) != SR_OK) { - sr_dbg("Invalid float converted from scope response."); - g_free(sample_points_string); - return SR_ERR; - } - samplerate_scope = fvalue; - } - g_free(sample_points_string); - devc->memory_depth_analog = samplerate_scope; - break; - } }; /* Get the timebase. */ - if (sr_scpi_get_double(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) + if (sr_scpi_get_float(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) return SR_ERR; sr_dbg("Current timebase: %g.", devc->timebase); diff --git a/src/hardware/siglent-sds/protocol.h b/src/hardware/siglent-sds/protocol.h index a38c9f7e0..89abaf640 100644 --- a/src/hardware/siglent-sds/protocol.h +++ b/src/hardware/siglent-sds/protocol.h @@ -49,9 +49,6 @@ enum protocol_version { SPO_MODEL, NON_SPO_MODEL, ESERIES, - // Refers to E11 Siglent Programming Guide : - // https://www.siglenteu.com/wp-content/uploads/dlm_uploads/2024/03/ProgrammingGuide_EN11F.pdf - E11, }; enum data_source { @@ -72,7 +69,6 @@ struct siglent_sds_series { uint64_t min_vdiv[2]; int num_horizontal_divs; int num_vertical_divs; - int code_per_div; int buffer_samples; }; @@ -124,8 +120,7 @@ struct dev_context { gboolean analog_channels[MAX_ANALOG_CHANNELS]; gboolean digital_channels[MAX_DIGITAL_CHANNELS]; gboolean la_enabled; - gboolean channels_switched; - double timebase; + float timebase; float attenuation[MAX_ANALOG_CHANNELS]; float vdiv[MAX_ANALOG_CHANNELS]; int vert_reference[MAX_ANALOG_CHANNELS]; @@ -148,8 +143,6 @@ struct dev_context { uint64_t num_header_bytes; /* Number of data blocks bytes already read. */ uint64_t num_block_bytes; - /* Number of data bytes already read in the current block. */ - uint64_t num_bytes_current_block; /* Number of data blocks read. */ int num_block_read; /* What to wait for in *_receive. */ From 5a7c35fdc272eb50694d5cf1607c321d31420663 Mon Sep 17 00:00:00 2001 From: fredzo Date: Sat, 31 Aug 2024 12:42:09 +0200 Subject: [PATCH 8/9] Fixed typo in DHO4000 model names. --- src/hardware/rigol-ds/api.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index f03661f8c..fedd5e4a5 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -318,9 +318,9 @@ static const struct rigol_ds_model supported_models[] = { {SERIES(DHO1000), "DHO1104", {2, 1000000000}, CH_INFO(4, false), std_cmd}, {SERIES(DHO1000), "DHO1202", {2, 1000000000}, CH_INFO(2, false), std_cmd}, {SERIES(DHO1000), "DHO1204", {2, 1000000000}, CH_INFO(4, false), std_cmd}, - {SERIES(DHO4000), "DHO1074", {2, 1000000000}, CH_INFO(4, false), std_cmd}, - {SERIES(DHO4000), "DHO1104", {2, 1000000000}, CH_INFO(4, false), std_cmd}, - {SERIES(DHO4000), "DHO1204", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO4204", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO4404", {2, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO4000), "DHO4804", {2, 1000000000}, CH_INFO(4, false), std_cmd}, }; static struct sr_dev_driver rigol_ds_driver_info; From 7de294ee100e0c9664336cdbf48567bd5be9b1e2 Mon Sep 17 00:00:00 2001 From: fredzo Date: Fri, 13 Dec 2024 12:41:59 +0100 Subject: [PATCH 9/9] Added support for DHO824 model. --- src/hardware/rigol-ds/api.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hardware/rigol-ds/api.c b/src/hardware/rigol-ds/api.c index fedd5e4a5..f2940ad47 100644 --- a/src/hardware/rigol-ds/api.c +++ b/src/hardware/rigol-ds/api.c @@ -308,6 +308,7 @@ static const struct rigol_ds_model supported_models[] = { {SERIES(DHO800), "DHO804", {5, 1000000000}, CH_INFO(4, false), std_cmd}, {SERIES(DHO800), "DHO812", {5, 1000000000}, CH_INFO(2, false), std_cmd}, {SERIES(DHO800), "DHO814", {5, 1000000000}, CH_INFO(4, false), std_cmd}, + {SERIES(DHO800), "DHO824", {2, 1000000000}, CH_INFO(4, false), std_cmd}, {SERIES(DHO900), "DHO914", {2, 1000000000}, CH_INFO(4, true), std_cmd}, {SERIES(DHO900), "DHO914S", {2, 1000000000}, CH_INFO(4, true), std_cmd}, {SERIES(DHO900), "DHO924", {2, 1000000000}, CH_INFO(4, true), std_cmd},