From: Soeren Apel Date: Wed, 27 Aug 2014 11:02:20 +0000 (+0200) Subject: yokogawa-dlm: Do not block when receiving and save frame length in scope state X-Git-Tag: libsigrok-0.4.0~1069 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=af3487ec288c9eb7042932140fcc8d53abf8c382;p=libsigrok.git yokogawa-dlm: Do not block when receiving and save frame length in scope state --- diff --git a/src/hardware/yokogawa-dlm/api.c b/src/hardware/yokogawa-dlm/api.c index f7a9dfa1..030bf854 100644 --- a/src/hardware/yokogawa-dlm/api.c +++ b/src/hardware/yokogawa-dlm/api.c @@ -670,8 +670,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) return SR_ERR; } + /* Request data for the first enabled channel. */ + devc->current_channel = devc->enabled_channels; + dlm_channel_data_request(sdi); + /* Call our callback when data comes in or after 50ms. */ - sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 50, + sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 10, dlm_data_receive, (void *)sdi); return SR_OK; @@ -680,7 +684,6 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) { struct dev_context *devc; - struct sr_scpi_dev_inst *scpi; struct sr_datafeed_packet packet; (void)cb_data; @@ -697,8 +700,8 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data) devc->num_frames = 0; g_slist_free(devc->enabled_channels); devc->enabled_channels = NULL; - scpi = sdi->conn; - sr_scpi_source_remove(sdi->session, scpi); + + sr_scpi_source_remove(sdi->session, sdi->conn); return SR_OK; } diff --git a/src/hardware/yokogawa-dlm/protocol.c b/src/hardware/yokogawa-dlm/protocol.c index f18e97ea..84ea966d 100644 --- a/src/hardware/yokogawa-dlm/protocol.c +++ b/src/hardware/yokogawa-dlm/protocol.c @@ -267,6 +267,9 @@ static void scope_state_dump(struct scope_config *config, sr_info("Current samplerate: %s", tmp); g_free(tmp); + sr_info("Current samples per acquisition (i.e. frame): %d", + state->samples_per_frame); + sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)", (*config->trigger_sources)[state->trigger_source], (*config->trigger_slopes)[state->trigger_slope], @@ -563,6 +566,11 @@ SR_PRIV int dlm_scope_state_query(struct sr_dev_inst *sdi) state->trigger_slope = i; + if (dlm_acq_length_get(sdi->conn, &state->samples_per_frame) != SR_OK) { + sr_err("Failed to query acquisition length."); + return SR_ERR; + } + dlm_sample_rate_query(sdi); scope_state_dump(config, state); @@ -710,42 +718,34 @@ SR_PRIV int dlm_device_init(struct sr_dev_inst *sdi, int model_index) return SR_OK; } -/** - * Send an SCPI command, read the reply and store the result in scpi_response - * without performing any processing on it. - * - * @param scpi Previously initialised SCPI device structure. - * @param command The SCPI command to send to the device (can be NULL). - * @param scpi_response Pointer where to store the parsed result. - * - * @return SR_OK on success, SR_ERR on failure. - */ -static int dlm_scpi_get_raw(struct sr_scpi_dev_inst *scpi, - const char *command, GArray **scpi_response) +SR_PRIV int dlm_channel_data_request(const struct sr_dev_inst *sdi) { - char buf[256]; - int len; - - if (command) - if (sr_scpi_send(scpi, command) != SR_OK) - return SR_ERR; - - if (sr_scpi_read_begin(scpi) != SR_OK) - return SR_ERR; + struct dev_context *devc; + struct sr_channel *ch; + int result; - *scpi_response = g_array_new(FALSE, FALSE, sizeof(uint8_t)); + devc = sdi->priv; + ch = devc->current_channel->data; - while (!sr_scpi_read_complete(scpi)) { - len = sr_scpi_read_data(scpi, buf, sizeof(buf)); - if (len < 0) { - g_array_free(*scpi_response, TRUE); - *scpi_response = NULL; - return SR_ERR; - } - g_array_append_vals(*scpi_response, buf, len); + switch (ch->type) { + case SR_CHANNEL_ANALOG: + result = dlm_analog_data_get(sdi->conn, ch->index + 1); + break; + case SR_CHANNEL_LOGIC: + result = dlm_digital_data_get(sdi->conn); + break; + default: + sr_err("Invalid channel type encountered (%d).", + ch->type); + result = SR_ERR; } - return SR_OK; + if (result == SR_OK) + devc->data_pending = TRUE; + else + devc->data_pending = FALSE; + + return result; } /** @@ -783,32 +783,34 @@ static int dlm_block_data_header_process(GArray *data, int *len) * Turns raw sample data into voltages and sends them off to the session bus. * * @param data The raw sample data. - * @samples Number of samples that were acquired. * @ch_state Pointer to the state of the channel whose data we're processing. * @sdi The device instance. * * @return SR_ERR when data is trucated, SR_OK otherwise. */ -static int dlm_analog_samples_send(GArray *data, int samples, +static int dlm_analog_samples_send(GArray *data, struct analog_channel_state *ch_state, struct sr_dev_inst *sdi) { - int i; + uint32_t i, samples; float voltage, range, offset; GArray *float_data; struct dev_context *devc; + struct scope_state *model_state; struct sr_channel *ch; struct sr_datafeed_analog analog; struct sr_datafeed_packet packet; + devc = sdi->priv; + model_state = devc->model_state; + samples = model_state->samples_per_frame; + ch = devc->current_channel->data; + if (data->len < samples * sizeof(uint8_t)) { sr_err("Truncated waveform data packet received."); return SR_ERR; } - devc = sdi->priv; - ch = devc->current_channel->data; - range = ch_state->waveform_range; offset = ch_state->waveform_offset; @@ -844,18 +846,24 @@ static int dlm_analog_samples_send(GArray *data, int samples, * Sends logic sample data off to the session bus. * * @param data The raw sample data. - * @samples Number of samples that were acquired. * @ch_state Pointer to the state of the channel whose data we're processing. * @sdi The device instance. * * @return SR_ERR when data is trucated, SR_OK otherwise. */ -static int dlm_digital_samples_send(GArray *data, int samples, +static int dlm_digital_samples_send(GArray *data, struct sr_dev_inst *sdi) { + struct dev_context *devc; + struct scope_state *model_state; + uint32_t samples; struct sr_datafeed_logic logic; struct sr_datafeed_packet packet; + devc = sdi->priv; + model_state = devc->model_state; + samples = model_state->samples_per_frame; + if (data->len < samples * sizeof(uint8_t)) { sr_err("Truncated waveform data packet received."); return SR_ERR; @@ -886,13 +894,13 @@ static int dlm_digital_samples_send(GArray *data, int samples, */ SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data) { - struct sr_channel *ch; struct sr_dev_inst *sdi; struct scope_state *model_state; struct dev_context *devc; + struct sr_channel *ch; struct sr_datafeed_packet packet; - GArray *data; - int result, num_bytes, samples; + int chunk_len, num_bytes; + static GArray *data = NULL; (void)fd; (void)revents; @@ -906,90 +914,105 @@ SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data) if (!(model_state = (struct scope_state*)devc->model_state)) return FALSE; - if (dlm_acq_length_get(sdi->conn, &samples) != SR_OK) { - sr_err("Failed to query acquisition length."); + /* Are we waiting for a response from the device? */ + if (!devc->data_pending) return TRUE; + + /* Check if a new query response is coming our way. */ + if (!data) { + if (sr_scpi_read_begin(sdi->conn) == SR_OK) + /* The 16 here accounts for the header and EOL. */ + data = g_array_sized_new(FALSE, FALSE, sizeof(uint8_t), + 16 + model_state->samples_per_frame); + else + return TRUE; } - packet.type = SR_DF_FRAME_BEGIN; - sr_session_send(sdi, &packet); + /* Store incoming data. */ + chunk_len = sr_scpi_read_data(sdi->conn, devc->receive_buffer, + RECEIVE_BUFFER_SIZE); + if (chunk_len < 0) { + sr_err("Error while reading data: %d", chunk_len); + goto fail; + } + g_array_append_vals(data, devc->receive_buffer, chunk_len); - /* Request data for all active channels. */ - for (devc->current_channel = devc->enabled_channels; - devc->current_channel; - devc->current_channel = devc->current_channel->next) { - ch = devc->current_channel->data; + /* Read the entire query response before processing. */ + if (!sr_scpi_read_complete(sdi->conn)) + return TRUE; - switch (ch->type) { - case SR_CHANNEL_ANALOG: - result = dlm_analog_data_get(sdi->conn, ch->index + 1); - break; - case SR_CHANNEL_LOGIC: - result = dlm_digital_data_get(sdi->conn); - break; - default: - sr_err("Invalid channel type encountered (%d).", - ch->type); - continue; - } + /* We finished reading and are no longer waiting for data. */ + devc->data_pending = FALSE; - if (result != SR_OK) { - sr_err("Failed to query aquisition data."); - goto fail; - } + /* Signal the beginning of a new frame if this is the first channel. */ + if (devc->current_channel == devc->enabled_channels) { + packet.type = SR_DF_FRAME_BEGIN; + sr_session_send(sdi, &packet); + } - data = NULL; - if (dlm_scpi_get_raw(sdi->conn, NULL, &data) != SR_OK) { - sr_err("Failed to receive waveform data from device."); - goto fail; - } + if (dlm_block_data_header_process(data, &num_bytes) != SR_OK) { + sr_err("Encountered malformed block data header."); + goto fail; + } - if (dlm_block_data_header_process(data, &num_bytes) != SR_OK) { - sr_err("Encountered malformed block data header."); - goto fail; - } + if (num_bytes == 0) { + sr_warn("Zero-length waveform data packet received. " \ + "Live mode not supported yet, stopping " \ + "acquisition and retrying."); + /* Don't care about return value here. */ + dlm_acquisition_stop(sdi->conn); + g_array_free(data, TRUE); + return TRUE; + } - if (num_bytes == 0) { - sr_warn("Zero-length waveform data packet received. " \ - "Live mode not supported yet, stopping " \ - "acquisition and retrying."); - /* Don't care about return value here. */ - dlm_acquisition_stop(sdi->conn); + ch = devc->current_channel->data; + switch (ch->type) { + case SR_CHANNEL_ANALOG: + if (dlm_analog_samples_send(data, + &model_state->analog_states[ch->index], + sdi) != SR_OK) goto fail; - } - - switch (ch->type) { - case SR_CHANNEL_ANALOG: - if (dlm_analog_samples_send(data, samples, - &model_state->analog_states[ch->index], - sdi) != SR_OK) - goto fail; - break; + break; + case SR_CHANNEL_LOGIC: + if (dlm_digital_samples_send(data, sdi) != SR_OK) + goto fail; + break; + default: + sr_err("Invalid channel type encountered."); + break; + } - case SR_CHANNEL_LOGIC: - if (dlm_digital_samples_send(data, samples, - sdi) != SR_OK) - goto fail; - break; + g_array_free(data, TRUE); + data = NULL; - default: - sr_err("Invalid channel type encountered."); - break; - } + /* Signal the end of this frame if this was the last enabled channel + * and set the next enabled channel. Then, request its data. + */ + if (!devc->current_channel->next) { + packet.type = SR_DF_FRAME_END; + sr_session_send(sdi, &packet); + devc->current_channel = devc->enabled_channels; + + /* As of now we only support importing the current acquisition + * data so we're going to stop at this point. + */ + sdi->driver->dev_acquisition_stop(sdi, cb_data); + return TRUE; + } else + devc->current_channel = devc->current_channel->next; - g_array_free(data, TRUE); + if (dlm_channel_data_request(sdi) != SR_OK) { + sr_err("Failed to request aquisition data."); + goto fail; } - packet.type = SR_DF_FRAME_END; - sr_session_send(sdi, &packet); - - sdi->driver->dev_acquisition_stop(sdi, cb_data); - return TRUE; fail: - if (data) + if (data) { g_array_free(data, TRUE); + data = NULL; + } - return TRUE; + return FALSE; } diff --git a/src/hardware/yokogawa-dlm/protocol.h b/src/hardware/yokogawa-dlm/protocol.h index 54b087cd..edb83a7c 100644 --- a/src/hardware/yokogawa-dlm/protocol.h +++ b/src/hardware/yokogawa-dlm/protocol.h @@ -33,6 +33,8 @@ #define LOG_PREFIX "yokogawa-dlm" #define MAX_INSTRUMENT_VERSIONS 4 +#define RECEIVE_BUFFER_SIZE (4096) + /* See Communication Interface User's Manual on p. 268 (:WAVeform:ALL:SEND?). */ #define DLM_MAX_FRAME_LENGTH (12500) /* See Communication Interface User's Manual on p. 269 (:WAVeform:SEND?). */ @@ -101,6 +103,7 @@ struct scope_state { int trigger_source; int trigger_slope; uint64_t sample_rate; + uint32_t samples_per_frame; }; /** Private, per-device-instance driver context. */ @@ -116,6 +119,9 @@ struct dev_context { uint64_t num_frames; uint64_t frame_limit; + + char receive_buffer[RECEIVE_BUFFER_SIZE]; + gboolean data_pending; }; /*--- api.c -----------------------------------------------------------------*/ @@ -130,4 +136,6 @@ SR_PRIV void dlm_scope_state_destroy(struct scope_state *state); SR_PRIV int dlm_scope_state_query(struct sr_dev_inst *sdi); SR_PRIV int dlm_sample_rate_query(const struct sr_dev_inst *sdi); +SR_PRIV int dlm_channel_data_request(const struct sr_dev_inst *sdi); + #endif diff --git a/src/hardware/yokogawa-dlm/protocol_wrappers.c b/src/hardware/yokogawa-dlm/protocol_wrappers.c index 419420d1..a4fc2cd7 100644 --- a/src/hardware/yokogawa-dlm/protocol_wrappers.c +++ b/src/hardware/yokogawa-dlm/protocol_wrappers.c @@ -270,9 +270,25 @@ int dlm_acquisition_stop(struct sr_scpi_dev_inst *scpi) int dlm_acq_length_get(struct sr_scpi_dev_inst *scpi, - int *response) + uint32_t *response) { - return sr_scpi_get_int(scpi, ":WAVEFORM:LENGTH?", response); + int ret; + char *s; + long tmp; + + if (sr_scpi_get_string(scpi, ":WAVEFORM:LENGTH?", &s) != SR_OK) + if (!s) + return SR_ERR; + + if (sr_atol(s, &tmp) == SR_OK) + ret = SR_OK; + else + ret = SR_ERR; + + g_free(s); + *response = tmp; + + return ret; } int dlm_chunks_per_acq_get(struct sr_scpi_dev_inst *scpi, int *response) diff --git a/src/hardware/yokogawa-dlm/protocol_wrappers.h b/src/hardware/yokogawa-dlm/protocol_wrappers.h index 127693dc..a88ef200 100644 --- a/src/hardware/yokogawa-dlm/protocol_wrappers.h +++ b/src/hardware/yokogawa-dlm/protocol_wrappers.h @@ -79,7 +79,7 @@ extern int dlm_response_headers_set(struct sr_scpi_dev_inst *scpi, extern int dlm_acquisition_stop(struct sr_scpi_dev_inst *scpi); extern int dlm_acq_length_get(struct sr_scpi_dev_inst *scpi, - int *response); + uint32_t *response); extern int dlm_chunks_per_acq_get(struct sr_scpi_dev_inst *scpi, int *response); extern int dlm_start_frame_set(struct sr_scpi_dev_inst *scpi, int value);