From: marchelh Date: Sun, 9 Sep 2018 14:11:59 +0000 (+0200) Subject: siglent-sds: Add ESERIES device support. X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=c90065a9499768f1663771136da10ee05e641677;p=libsigrok.git siglent-sds: Add ESERIES device support. Due to some SCPI command changes that Siglent made, the connection failed due to the wrong commands being send to the device. This might fix parts of bug #1242, though initial tests show that further changes might be needed. [Note: This commit consists of multiple squashed commits from marchelh and various fixups and rebasing operations by Uwe Hermann ] --- diff --git a/src/hardware/siglent-sds/api.c b/src/hardware/siglent-sds/api.c index 790886bc..9811ac0c 100644 --- a/src/hardware/siglent-sds/api.c +++ b/src/hardware/siglent-sds/api.c @@ -188,7 +188,7 @@ static const struct siglent_sds_series supported_series[] = { { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, [SDS1000XP] = {VENDOR(SIGLENT), "SDS1000X+", SPO_MODEL, { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, - [SDS1000XE] = {VENDOR(SIGLENT), "SDS1000XE", SPO_MODEL, + [SDS1000XE] = {VENDOR(SIGLENT), "SDS1000XE", ESERIES, { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, [SDS2000X] = {VENDOR(SIGLENT), "SDS2000X", SPO_MODEL, { 50, 1 }, { 500, 100000 }, 14, 8, 14000363}, @@ -531,7 +531,7 @@ static int config_set(uint32_t key, GVariant *data, int ret, idx; const char *tmp_str; char buffer[16]; - char *cmd = NULL; + char *cmd = ""; char cmd4[4]; devc = sdi->priv; @@ -766,6 +766,7 @@ static int config_list(uint32_t key, GVariant **data, *data = g_variant_new_strv(data_sources, ARRAY_SIZE(data_sources) - 1); break; case SPO_MODEL: + case ESERIES: *data = g_variant_new_strv(ARRAY_AND_SIZE(data_sources)); break; } @@ -827,20 +828,17 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) if (ch->enabled) { /* Turn on LA module if currently off and digital channels are enabled. */ if (!devc->la_enabled) { - if (siglent_sds_config_set(sdi, "DGST ON") != SR_OK) + if (siglent_sds_config_set(sdi, "DI:SW?") != SR_OK) return SR_ERR; - g_usleep(630000); devc->la_enabled = TRUE; } devc->enabled_channels = g_slist_append( devc->enabled_channels, ch); } /* Enabled channel is currently disabled, or vice versa. */ - if (siglent_sds_config_set(sdi, "D%d:DGCH %s", ch->index, + if (siglent_sds_config_set(sdi, "D%d:TRA %s", ch->index, ch->enabled ? "ON" : "OFF") != SR_OK) return SR_ERR; - /* Slowing the command sequence down to let the device handle it. */ - g_usleep(630000); devc->digital_channels[ch->index] = ch->enabled; } } @@ -881,7 +879,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) break; } - sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50, + 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 8a2547df..3f1749a0 100644 --- a/src/hardware/siglent-sds/protocol.c +++ b/src/hardware/siglent-sds/protocol.c @@ -109,8 +109,10 @@ static int siglent_sds_event_wait(const struct sr_dev_inst *sdi) * not taking effect? Was some different condition meant * to get encoded? This needs review, and adjustment. */ - } while ((out | DEVICE_STATE_TRIG_RDY && out | DEVICE_STATE_DATA_ACQ) && out | DEVICE_STATE_STOPPED); - sr_dbg("Device triggerd 2."); + } while (out != DEVICE_STATE_TRIG_RDY || out != DEVICE_STATE_DATA_TRIG_RDY || out != DEVICE_STATE_STOPPED); + + sr_dbg("Device triggered."); + siglent_sds_set_wait_event(devc, WAIT_NONE); } @@ -168,7 +170,56 @@ SR_PRIV int siglent_sds_capture_start(const struct sr_dev_inst *sdi) sr_atoi(buf, &out); if (out == DEVICE_STATE_TRIG_RDY) { siglent_sds_set_wait_event(devc, WAIT_TRIGGER); - } else if (out == DEVICE_STATE_TRIG_RDY + 1) { + } else if (out == DEVICE_STATE_DATA_TRIG_RDY) { + sr_spew("Device triggered."); + siglent_sds_set_wait_event(devc, WAIT_BLOCK); + return SR_OK; + } else { + sr_spew("Device did not enter ARM mode."); + return SR_ERR; + } + } else { /* TODO: Implement history retrieval. */ + unsigned int framecount; + char buf[200]; + int ret; + + sr_dbg("Starting data capture for history frameset."); + if (siglent_sds_config_set(sdi, "FPAR?") != SR_OK) + return SR_ERR; + ret = sr_scpi_read_data(sdi->conn, buf, 200); + if (ret < 0) { + sr_err("Read error while reading data header."); + return SR_ERR; + } + memcpy(&framecount, buf + 40, 4); + if (devc->limit_frames > framecount) + sr_err("Frame limit higher than frames in buffer of device!"); + else if (devc->limit_frames == 0) + devc->limit_frames = framecount; + sr_dbg("Starting data capture for history frameset %" PRIu64 " of %" PRIu64, + devc->num_frames + 1, devc->limit_frames); + if (siglent_sds_config_set(sdi, "FRAM %i", devc->num_frames + 1) != SR_OK) + return SR_ERR; + if (siglent_sds_channel_start(sdi) != SR_OK) + return SR_ERR; + siglent_sds_set_wait_event(devc, WAIT_STOP); + } + break; + case ESERIES: + if (devc->data_source == DATA_SOURCE_SCREEN) { + char *buf; + int out; + + sr_dbg("Starting data capture for active frameset %" PRIu64 " of %" PRIu64, + devc->num_frames + 1, devc->limit_frames); + if (siglent_sds_config_set(sdi, "ARM") != SR_OK) + return SR_ERR; + if (sr_scpi_get_string(sdi->conn, ":INR?", &buf) != SR_OK) + return SR_ERR; + sr_atoi(buf, &out); + if (out == DEVICE_STATE_TRIG_RDY) { + siglent_sds_set_wait_event(devc, WAIT_TRIGGER); + } else if (out == DEVICE_STATE_DATA_TRIG_RDY) { sr_spew("Device triggered."); siglent_sds_set_wait_event(devc, WAIT_BLOCK); return SR_OK; @@ -223,14 +274,28 @@ SR_PRIV int siglent_sds_channel_start(const struct sr_dev_inst *sdi) ch = devc->channel_entry->data; - sr_dbg("Starting reading data from channel %d.", ch->index + 1); - - s = (ch->type == SR_CHANNEL_LOGIC) ? "D%d:WF?" : "C%d:WF? ALL"; - if (sr_scpi_send(sdi->conn, s, ch->index + 1) != SR_OK) - return SR_ERR; - siglent_sds_set_wait_event(devc, WAIT_NONE); + sr_dbg("Start reading data from channel %s.", ch->name); - siglent_sds_set_wait_event(devc, WAIT_BLOCK); + switch (devc->model->series->protocol) { + case NON_SPO_MODEL: + case SPO_MODEL: + s = (ch->type == SR_CHANNEL_LOGIC) ? "D%d:WF?" : "C%d:WF? ALL"; + if (sr_scpi_send(sdi->conn, s, ch->index + 1) != 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", + ch->index + 1) != SR_OK) + return SR_ERR; + } + siglent_sds_set_wait_event(devc, WAIT_NONE); + if (sr_scpi_read_begin(sdi->conn) != SR_OK) + return TRUE; + siglent_sds_set_wait_event(devc, WAIT_BLOCK); + break; + } devc->num_channel_bytes = 0; devc->num_header_bytes = 0; @@ -271,6 +336,123 @@ static int siglent_sds_read_header(struct sr_dev_inst *sdi) return ret; } +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; + gboolean low_channels; /* Lower channels enabled */ + gboolean high_channels; /* Higher channels enabled */ + int len, channel_index; + long samples_index; + + 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) { + if (ch->enabled) { + 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. */ + } 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++; + } + } + + /* Clear the buffers to prepare for the new samples */ + if (ch->index < 8) { + g_array_free(data_low_channels, FALSE); + data_low_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } else { + g_array_free(data_high_channels, FALSE); + data_high_channels = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + } + + /* Storing the converted temp values from the the scope into the buffers. */ + for (long 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; index++) { + uint8_t value; + if (low_channels) { + value = g_array_index(data_low_channels, uint8_t, index); + g_array_append_val(devc->dig_buffer, value); + } else { + value = 0; + g_array_append_val(devc->dig_buffer, value); + } + if (high_channels) { + value = g_array_index(data_high_channels, uint8_t, index); + g_array_append_val(devc->dig_buffer, value); + } else { + value = 0; + g_array_append_val(devc->dig_buffer, value); + } + } + + g_array_free(data_low_channels, TRUE); + g_array_free(data_high_channels, TRUE); + + return len; +} + SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; @@ -282,8 +464,10 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct sr_datafeed_logic logic; - int len, i; struct sr_channel *ch; + int len, i; + float wait; + gboolean read_complete = false; (void)fd; @@ -321,122 +505,162 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) sr_err("BUG: Unknown event target encountered."); break; } + ch = devc->channel_entry->data; len = 0; - if (devc->num_block_bytes == 0) { - if (devc->memory_depth >= 14000000) { - sr_err("Device memory depth is set to 14Mpts, so please be patient."); - g_usleep(4900000); /* Sleep for large memory set. */ - } - if (sr_scpi_read_begin(scpi) != SR_OK) - return TRUE; - sr_dbg("New block header expected."); - len = siglent_sds_read_header(sdi); - if (len == 0) - /* Still reading the header. */ - return TRUE; - if (len == -1) { - sr_err("Read error, aborting capture."); - packet.type = SR_DF_FRAME_END; - sr_session_send(sdi, &packet); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } - devc->num_block_bytes = 0; - devc->num_block_read = 0; - } - - if (len == -1) { - sr_err("Read error, aborting capture."); - packet.type = SR_DF_FRAME_END; - sr_session_send(sdi, &packet); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } - - while (devc->num_block_bytes < devc->num_samples) { - len = sr_scpi_read_data(scpi, (char *)devc->buffer, devc->num_samples); - if (len == -1) { - sr_err("Read error, aborting capture."); - packet.type = SR_DF_FRAME_END; - sr_session_send(sdi, &packet); - sdi->driver->dev_acquisition_stop(sdi); - return TRUE; - } - devc->num_block_read += 1; - devc->num_block_bytes += len; - if (devc->num_block_bytes >= devc->num_samples ) { - /* Offset the data block buffer past the IEEE header and description header. */ - devc->buffer += devc->block_header_size; - len = devc->num_samples; - } - 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]; - GArray *float_data; - static GArray *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); - 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; - voltage = ((vdiv * voltage) - offset); - g_array_append_val(float_data, voltage); + if (ch->type == SR_CHANNEL_ANALOG) { + if (devc->num_block_bytes == 0) { + /* Wait for the device to fill its output buffers. */ + switch (devc->model->series->protocol) { + case NON_SPO_MODEL: + case SPO_MODEL: + /* The older models need more time to prepare the the output buffers due to CPU speed. */ + wait = (devc->memory_depth_analog * 2.5); + sr_dbg("Waiting %.f0 ms for device to prepare the output buffers", wait / 1000); + g_usleep(wait); + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + break; + case ESERIES: + /* The newer models (ending with the E) have faster CPUs but still need time when a slow timebase is selected. */ + if (sr_scpi_read_begin(scpi) != SR_OK) + return TRUE; + wait = ((devc->timebase * devc->model->series->num_horizontal_divs) * 100000); + sr_dbg("Waiting %.f0 ms for device to prepare the output buffers", wait / 1000); + g_usleep(wait); + break; } - vdivlog = log10f(vdiv); - digits = -(int) vdivlog + (vdivlog < 0.0); - sr_analog_init(&analog, &encoding, &meaning, &spec, digits); - analog.meaning->channels = g_slist_append(NULL, ch); - analog.num_samples = float_data->len; - analog.data = (float *)float_data->data; - analog.meaning->mq = SR_MQ_VOLTAGE; - analog.meaning->unit = SR_UNIT_VOLT; - analog.meaning->mqflags = 0; - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(sdi, &packet); - g_slist_free(analog.meaning->channels); - g_array_free(data, TRUE); - } else { - logic.length = len; - logic.unitsize = 1; - logic.data = devc->buffer; - packet.type = SR_DF_LOGIC; - packet.payload = &logic; - sr_session_send(sdi, &packet); - } - if (devc->num_samples == devc->num_block_bytes) { - sr_dbg("Transfer has been completed."); - devc->num_header_bytes = 0; - devc->num_block_bytes = 0; - if (!sr_scpi_read_complete(scpi)) { - sr_err("Read should have been completed."); + sr_dbg("New block with header expected."); + len = siglent_sds_read_header(sdi); + if (len == 0) + /* Still reading the header. */ + return TRUE; + if (len == -1) { + sr_err("Read error, aborting capture."); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); sdi->driver->dev_acquisition_stop(sdi); return TRUE; } + devc->num_block_bytes = len; devc->num_block_read = 0; - } else { - sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read.", - devc->num_block_bytes, devc->num_samples); - } - } - if (devc->channel_entry->next) { - /* We got the frame for this channel, now get the next channel. */ - devc->channel_entry = devc->channel_entry->next; - siglent_sds_channel_start(sdi); + if (len == -1) { + sr_err("Read error, aborting capture."); + packet.type = SR_DF_FRAME_END; + sr_session_send(sdi, &packet); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; + } + + do { + read_complete = false; + if (devc->num_block_bytes > devc->num_samples) { + /* 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; + } else { + sr_dbg("Requesting: %li 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."); + packet.type = SR_DF_FRAME_END; + sr_session_send(sdi, &packet); + 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, len); + if (ch->type == SR_CHANNEL_ANALOG) { + float vdiv = devc->vdiv[ch->index]; + float offset = devc->vert_offset[ch->index]; + GArray *float_data; + static GArray *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); + 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; + voltage = ((vdiv * voltage) - offset); + g_array_append_val(float_data, voltage); + } + vdivlog = log10f(vdiv); + digits = -(int) vdivlog + (vdivlog < 0.0); + sr_analog_init(&analog, &encoding, &meaning, &spec, digits); + analog.meaning->channels = g_slist_append(NULL, ch); + analog.num_samples = float_data->len; + analog.data = (float *)float_data->data; + analog.meaning->mq = SR_MQ_VOLTAGE; + analog.meaning->unit = SR_UNIT_VOLT; + analog.meaning->mqflags = 0; + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + g_slist_free(analog.meaning->channels); + g_array_free(data, TRUE); + } + len = 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("Read should have been completed."); + packet.type = SR_DF_FRAME_END; + sr_session_send(sdi, &packet); + sdi->driver->dev_acquisition_stop(sdi); + return TRUE; + } + devc->num_block_read = 0; + } else { + sr_dbg("%" PRIu64 " of %" PRIu64 " block bytes read.", + devc->num_block_bytes, devc->num_samples); + } + } while (!read_complete); + + if (devc->channel_entry->next) { + /* We got the frame for this channel, now get the next channel. */ + devc->channel_entry = devc->channel_entry->next; + siglent_sds_channel_start(sdi); + } else { + /* Done with this frame. */ + packet.type = SR_DF_FRAME_END; + sr_session_send(sdi, &packet); + if (++devc->num_frames == devc->limit_frames) { + /* Last frame, stop capture. */ + sdi->driver->dev_acquisition_stop(sdi); + } else { + /* Get the next frame, starting with the first channel. */ + devc->channel_entry = devc->enabled_channels; + siglent_sds_capture_start(sdi); + + /* Start of next frame. */ + packet.type = SR_DF_FRAME_BEGIN; + sr_session_send(sdi, &packet); + } + } + } } else { - /* Done with this frame. */ + if (!siglent_sds_get_digital(sdi, ch)) + return TRUE; + logic.length = devc->dig_buffer->len; + logic.unitsize = 2; + logic.data = devc->dig_buffer->data; + packet.type = SR_DF_LOGIC; + packet.payload = &logic; + sr_session_send(sdi, &packet); packet.type = SR_DF_FRAME_END; sr_session_send(sdi, &packet); + sdi->driver->dev_acquisition_stop(sdi); if (++devc->num_frames == devc->limit_frames) { /* Last frame, stop capture. */ @@ -452,6 +676,11 @@ SR_PRIV int siglent_sds_receive(int fd, int revents, void *cb_data) } } + // sr_session_send(sdi, &packet); + // packet.type = SR_DF_FRAME_END; + // sr_session_send(sdi, &packet); + // sdi->driver->dev_acquisition_stop(sdi); + return TRUE; } @@ -463,8 +692,8 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) unsigned int i; int res, num_tokens; gchar **tokens; - int len; - float trigger_pos; + int len; + float trigger_pos; devc = sdi->priv; @@ -488,7 +717,7 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) sr_dbg("Check logic analyzer channel state."); devc->la_enabled = FALSE; - cmd = g_strdup_printf("DGST?"); + cmd = g_strdup_printf("DI:SW?"); res = sr_scpi_get_bool(sdi->conn, cmd, &status); g_free(cmd); if (res != SR_OK) @@ -497,7 +726,7 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) if (status) { devc->la_enabled = TRUE; for (i = 0; i < ARRAY_SIZE(devc->digital_channels); i++) { - cmd = g_strdup_printf("D%i:DGCH?", i); + cmd = g_strdup_printf("D%i:TRA?", i); res = sr_scpi_get_bool(sdi->conn, cmd, &devc->digital_channels[i]); g_free(cmd); if (res != SR_OK) @@ -570,25 +799,26 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) /* TODO: Horizontal trigger position. */ response = ""; trigger_pos = 0; - if (sr_scpi_get_string(sdi->conn, g_strdup_printf("%s:TRDL?", devc->trigger_source), &response) != SR_OK) - return SR_ERR; - len = strlen(response); - if (!g_ascii_strcasecmp(response + (len - 2), "us")) { - trigger_pos = atof(response) / SR_GHZ(1); - sr_dbg("Current trigger position us %s.", response); - } else if (!g_ascii_strcasecmp(response + (len - 2), "ns")) { - trigger_pos = atof(response) / SR_MHZ(1); - sr_dbg("Current trigger position ms %s.", response); - } else if (!g_ascii_strcasecmp(response + (len - 2), "ms")) { - trigger_pos = atof(response) / SR_KHZ(1); - sr_dbg("Current trigger position ns %s.", response); - } else if (!g_ascii_strcasecmp(response + (len - 2), "s")) { - trigger_pos = atof(response); - sr_dbg("Current trigger position s %s.", response); + // if (sr_scpi_get_string(sdi->conn, g_strdup_printf("%s:TRDL?", devc->trigger_source), &response) != SR_OK) + // return SR_ERR; + // len = strlen(response); + len = strlen(tokens[4]); + if (!g_ascii_strcasecmp(tokens[4] + (len - 2), "us")) { + trigger_pos = atof(tokens[4]) / SR_GHZ(1); + sr_dbg("Current trigger position us %s.", tokens[4] ); + } else if (!g_ascii_strcasecmp(tokens[4] + (len - 2), "ns")) { + trigger_pos = atof(tokens[4]) / SR_MHZ(1); + sr_dbg("Current trigger position ms %s.", tokens[4] ); + } else if (!g_ascii_strcasecmp(tokens[4] + (len - 2), "ms")) { + trigger_pos = atof(tokens[4]) / SR_KHZ(1); + sr_dbg("Current trigger position ns %s.", tokens[4] ); + } else if (!g_ascii_strcasecmp(tokens[4] + (len - 2), "s")) { + trigger_pos = atof(tokens[4]); + sr_dbg("Current trigger position s %s.", tokens[4] ); }; devc->horiz_triggerpos = trigger_pos; - sr_dbg("Current horizontal trigger position %.10f", devc->horiz_triggerpos); + sr_dbg("Current horizontal trigger position %.10f.", devc->horiz_triggerpos); /* Trigger slope. */ cmd = g_strdup_printf("%s:TRSL?", devc->trigger_source); @@ -598,13 +828,16 @@ SR_PRIV int siglent_sds_get_dev_cfg(const struct sr_dev_inst *sdi) return SR_ERR; sr_dbg("Current trigger slope: %s.", devc->trigger_slope); - /* Trigger level. */ - cmd = g_strdup_printf("%s:TRLV?", devc->trigger_source); - res = sr_scpi_get_float(sdi->conn, cmd, &devc->trigger_level); - g_free(cmd); - if (res != SR_OK) - return SR_ERR; - sr_dbg("Current trigger level: %g.", devc->trigger_level); + /* Trigger level, only when analog channel. */ + if (g_str_has_prefix(tokens[2], "C")) { + cmd = g_strdup_printf("%s:TRLV?", devc->trigger_source); + res = sr_scpi_get_float(sdi->conn, cmd, &devc->trigger_level); + g_free(cmd); + if (res != SR_OK) + return SR_ERR; + sr_dbg("Current trigger level: %g.", devc->trigger_level); + } + return SR_OK; } @@ -653,37 +886,60 @@ SR_PRIV int siglent_sds_get_dev_cfg_horizontal(const struct sr_dev_inst *sdi) float samplerate_scope, fvalue; devc = sdi->priv; - cmd = g_strdup_printf("SANU? C1"); - res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); - g_free(cmd); - samplerate_scope = 0; - fvalue = 0; - if (res != SR_OK) - 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."); + switch (devc->model->series->protocol) { + case SPO_MODEL: + case NON_SPO_MODEL: + cmd = g_strdup_printf("SANU? C1"); + res = sr_scpi_get_string(sdi->conn, cmd, &sample_points_string); + g_free(cmd); + samplerate_scope = 0; + fvalue = 0; + if (res != SR_OK) 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."); + 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."); + return SR_ERR; + } + samplerate_scope = fvalue * 10000; + } else { + samplerate_scope = fvalue; } - 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); + devc->memory_depth_analog = samplerate_scope; + break; + case ESERIES: + cmd = g_strdup_printf("SANU? C1"); + if (sr_scpi_get_float(sdi->conn, cmd, &fvalue) != SR_OK) return SR_ERR; + devc->memory_depth_analog = (long)fvalue; + 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; } - samplerate_scope = fvalue * 10000; - } else { - samplerate_scope = fvalue; - } - g_free(sample_points_string); + g_free(cmd); + break; + }; + /* Get the timebase. */ if (sr_scpi_get_float(sdi->conn, ":TDIV?", &devc->timebase) != SR_OK) return SR_ERR; + sr_dbg("Current timebase: %g.", devc->timebase); - devc->samplerate = samplerate_scope / (devc->timebase * devc->model->series->num_horizontal_divs); - devc->memory_depth = samplerate_scope; + devc->samplerate = devc->memory_depth_analog / (devc->timebase * devc->model->series->num_horizontal_divs); + sr_dbg("Current samplerate: %0f.", devc->samplerate); + sr_dbg("Current memory depth: %lu.", devc->memory_depth_analog); + return SR_OK; } diff --git a/src/hardware/siglent-sds/protocol.h b/src/hardware/siglent-sds/protocol.h index b0c926ed..09165205 100644 --- a/src/hardware/siglent-sds/protocol.h +++ b/src/hardware/siglent-sds/protocol.h @@ -32,7 +32,8 @@ //#define ACQ_BUFFER_SIZE (6000000) #define ACQ_BUFFER_SIZE (18000000) -#define SIGLENT_HEADER_SIZE 351 +#define SIGLENT_HEADER_SIZE 363 +#define SIGLENT_DIG_HEADER_SIZE 346 /* Maximum number of samples to retrieve at once. */ #define ACQ_BLOCK_SIZE (30 * 1000) @@ -40,13 +41,15 @@ #define MAX_ANALOG_CHANNELS 4 #define MAX_DIGITAL_CHANNELS 16 -#define DEVICE_STATE_STOPPED 0 /* Scope is in stopped state */ -#define DEVICE_STATE_DATA_ACQ 1 /* A new signal has been acquired */ -#define DEVICE_STATE_TRIG_RDY 8192 /* Trigger is ready */ +#define DEVICE_STATE_STOPPED 0 /* Scope is in stopped state bit */ +#define DEVICE_STATE_DATA_ACQ 1 /* A new signal has been acquired bit */ +#define DEVICE_STATE_TRIG_RDY 8192 /* Trigger is ready bit */ +#define DEVICE_STATE_DATA_TRIG_RDY 8193 /* Trigger is ready bit */ enum protocol_version { SPO_MODEL, NON_SPO_MODEL, + ESERIES, }; enum data_source { @@ -109,7 +112,8 @@ struct dev_context { uint64_t analog_frame_size; uint64_t digital_frame_size; uint64_t num_samples; - uint64_t memory_depth; + uint64_t memory_depth_analog; + uint64_t memory_depth_digital; long block_header_size; float samplerate; @@ -149,6 +153,7 @@ struct dev_context { /* Acq buffers used for reading from the scope and sending data to app. */ unsigned char *buffer; float *data; + GArray *dig_buffer; }; SR_PRIV int siglent_sds_config_set(const struct sr_dev_inst *sdi,