yokogawa-dlm: Do not block when receiving and save frame length in scope state

This commit is contained in:
Soeren Apel 2014-08-27 13:02:20 +02:00
parent 8ab929d614
commit af3487ec28
5 changed files with 171 additions and 121 deletions

View File

@ -670,8 +670,12 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data)
return SR_ERR; 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. */ /* 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); dlm_data_receive, (void *)sdi);
return SR_OK; 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) static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
{ {
struct dev_context *devc; struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
struct sr_datafeed_packet packet; struct sr_datafeed_packet packet;
(void)cb_data; (void)cb_data;
@ -697,8 +700,8 @@ static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
devc->num_frames = 0; devc->num_frames = 0;
g_slist_free(devc->enabled_channels); g_slist_free(devc->enabled_channels);
devc->enabled_channels = NULL; 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; return SR_OK;
} }

View File

@ -267,6 +267,9 @@ static void scope_state_dump(struct scope_config *config,
sr_info("Current samplerate: %s", tmp); sr_info("Current samplerate: %s", tmp);
g_free(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)", sr_info("Current trigger: %s (source), %s (slope) %.2f (offset)",
(*config->trigger_sources)[state->trigger_source], (*config->trigger_sources)[state->trigger_source],
(*config->trigger_slopes)[state->trigger_slope], (*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; 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); dlm_sample_rate_query(sdi);
scope_state_dump(config, state); 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; return SR_OK;
} }
/** SR_PRIV int dlm_channel_data_request(const struct sr_dev_inst *sdi)
* 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)
{ {
char buf[256]; struct dev_context *devc;
int len; struct sr_channel *ch;
int result;
if (command) devc = sdi->priv;
if (sr_scpi_send(scpi, command) != SR_OK) ch = devc->current_channel->data;
return SR_ERR;
if (sr_scpi_read_begin(scpi) != SR_OK) switch (ch->type) {
return SR_ERR; case SR_CHANNEL_ANALOG:
result = dlm_analog_data_get(sdi->conn, ch->index + 1);
*scpi_response = g_array_new(FALSE, FALSE, sizeof(uint8_t)); break;
case SR_CHANNEL_LOGIC:
while (!sr_scpi_read_complete(scpi)) { result = dlm_digital_data_get(sdi->conn);
len = sr_scpi_read_data(scpi, buf, sizeof(buf)); break;
if (len < 0) { default:
g_array_free(*scpi_response, TRUE); sr_err("Invalid channel type encountered (%d).",
*scpi_response = NULL; ch->type);
return SR_ERR; result = SR_ERR;
}
g_array_append_vals(*scpi_response, buf, len);
} }
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. * Turns raw sample data into voltages and sends them off to the session bus.
* *
* @param data The raw sample data. * @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. * @ch_state Pointer to the state of the channel whose data we're processing.
* @sdi The device instance. * @sdi The device instance.
* *
* @return SR_ERR when data is trucated, SR_OK otherwise. * @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 analog_channel_state *ch_state,
struct sr_dev_inst *sdi) struct sr_dev_inst *sdi)
{ {
int i; uint32_t i, samples;
float voltage, range, offset; float voltage, range, offset;
GArray *float_data; GArray *float_data;
struct dev_context *devc; struct dev_context *devc;
struct scope_state *model_state;
struct sr_channel *ch; struct sr_channel *ch;
struct sr_datafeed_analog analog; struct sr_datafeed_analog analog;
struct sr_datafeed_packet packet; 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)) { if (data->len < samples * sizeof(uint8_t)) {
sr_err("Truncated waveform data packet received."); sr_err("Truncated waveform data packet received.");
return SR_ERR; return SR_ERR;
} }
devc = sdi->priv;
ch = devc->current_channel->data;
range = ch_state->waveform_range; range = ch_state->waveform_range;
offset = ch_state->waveform_offset; 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. * Sends logic sample data off to the session bus.
* *
* @param data The raw sample data. * @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. * @ch_state Pointer to the state of the channel whose data we're processing.
* @sdi The device instance. * @sdi The device instance.
* *
* @return SR_ERR when data is trucated, SR_OK otherwise. * @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 sr_dev_inst *sdi)
{ {
struct dev_context *devc;
struct scope_state *model_state;
uint32_t samples;
struct sr_datafeed_logic logic; struct sr_datafeed_logic logic;
struct sr_datafeed_packet packet; 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)) { if (data->len < samples * sizeof(uint8_t)) {
sr_err("Truncated waveform data packet received."); sr_err("Truncated waveform data packet received.");
return SR_ERR; 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) SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data)
{ {
struct sr_channel *ch;
struct sr_dev_inst *sdi; struct sr_dev_inst *sdi;
struct scope_state *model_state; struct scope_state *model_state;
struct dev_context *devc; struct dev_context *devc;
struct sr_channel *ch;
struct sr_datafeed_packet packet; struct sr_datafeed_packet packet;
GArray *data; int chunk_len, num_bytes;
int result, num_bytes, samples; static GArray *data = NULL;
(void)fd; (void)fd;
(void)revents; (void)revents;
@ -906,42 +914,40 @@ SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data)
if (!(model_state = (struct scope_state*)devc->model_state)) if (!(model_state = (struct scope_state*)devc->model_state))
return FALSE; return FALSE;
if (dlm_acq_length_get(sdi->conn, &samples) != SR_OK) { /* Are we waiting for a response from the device? */
sr_err("Failed to query acquisition length."); 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; return TRUE;
} }
/* 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);
/* Read the entire query response before processing. */
if (!sr_scpi_read_complete(sdi->conn))
return TRUE;
/* We finished reading and are no longer waiting for data. */
devc->data_pending = FALSE;
/* 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; packet.type = SR_DF_FRAME_BEGIN;
sr_session_send(sdi, &packet); sr_session_send(sdi, &packet);
/* 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;
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;
}
if (result != SR_OK) {
sr_err("Failed to query aquisition data.");
goto fail;
}
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) { if (dlm_block_data_header_process(data, &num_bytes) != SR_OK) {
@ -955,41 +961,58 @@ SR_PRIV int dlm_data_receive(int fd, int revents, void *cb_data)
"acquisition and retrying."); "acquisition and retrying.");
/* Don't care about return value here. */ /* Don't care about return value here. */
dlm_acquisition_stop(sdi->conn); dlm_acquisition_stop(sdi->conn);
goto fail; g_array_free(data, TRUE);
return TRUE;
} }
ch = devc->current_channel->data;
switch (ch->type) { switch (ch->type) {
case SR_CHANNEL_ANALOG: case SR_CHANNEL_ANALOG:
if (dlm_analog_samples_send(data, samples, if (dlm_analog_samples_send(data,
&model_state->analog_states[ch->index], &model_state->analog_states[ch->index],
sdi) != SR_OK) sdi) != SR_OK)
goto fail; goto fail;
break; break;
case SR_CHANNEL_LOGIC: case SR_CHANNEL_LOGIC:
if (dlm_digital_samples_send(data, samples, if (dlm_digital_samples_send(data, sdi) != SR_OK)
sdi) != SR_OK)
goto fail; goto fail;
break; break;
default: default:
sr_err("Invalid channel type encountered."); sr_err("Invalid channel type encountered.");
break; break;
} }
g_array_free(data, TRUE); g_array_free(data, TRUE);
} data = NULL;
/* 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; packet.type = SR_DF_FRAME_END;
sr_session_send(sdi, &packet); 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); sdi->driver->dev_acquisition_stop(sdi, cb_data);
return TRUE;
} else
devc->current_channel = devc->current_channel->next;
if (dlm_channel_data_request(sdi) != SR_OK) {
sr_err("Failed to request aquisition data.");
goto fail;
}
return TRUE; return TRUE;
fail: fail:
if (data) if (data) {
g_array_free(data, TRUE); g_array_free(data, TRUE);
data = NULL;
}
return TRUE; return FALSE;
} }

View File

@ -33,6 +33,8 @@
#define LOG_PREFIX "yokogawa-dlm" #define LOG_PREFIX "yokogawa-dlm"
#define MAX_INSTRUMENT_VERSIONS 4 #define MAX_INSTRUMENT_VERSIONS 4
#define RECEIVE_BUFFER_SIZE (4096)
/* See Communication Interface User's Manual on p. 268 (:WAVeform:ALL:SEND?). */ /* See Communication Interface User's Manual on p. 268 (:WAVeform:ALL:SEND?). */
#define DLM_MAX_FRAME_LENGTH (12500) #define DLM_MAX_FRAME_LENGTH (12500)
/* See Communication Interface User's Manual on p. 269 (:WAVeform:SEND?). */ /* See Communication Interface User's Manual on p. 269 (:WAVeform:SEND?). */
@ -101,6 +103,7 @@ struct scope_state {
int trigger_source; int trigger_source;
int trigger_slope; int trigger_slope;
uint64_t sample_rate; uint64_t sample_rate;
uint32_t samples_per_frame;
}; };
/** Private, per-device-instance driver context. */ /** Private, per-device-instance driver context. */
@ -116,6 +119,9 @@ struct dev_context {
uint64_t num_frames; uint64_t num_frames;
uint64_t frame_limit; uint64_t frame_limit;
char receive_buffer[RECEIVE_BUFFER_SIZE];
gboolean data_pending;
}; };
/*--- api.c -----------------------------------------------------------------*/ /*--- 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_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_sample_rate_query(const struct sr_dev_inst *sdi);
SR_PRIV int dlm_channel_data_request(const struct sr_dev_inst *sdi);
#endif #endif

View File

@ -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 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) int dlm_chunks_per_acq_get(struct sr_scpi_dev_inst *scpi, int *response)

View File

@ -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_acquisition_stop(struct sr_scpi_dev_inst *scpi);
extern int dlm_acq_length_get(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, extern int dlm_chunks_per_acq_get(struct sr_scpi_dev_inst *scpi,
int *response); int *response);
extern int dlm_start_frame_set(struct sr_scpi_dev_inst *scpi, int value); extern int dlm_start_frame_set(struct sr_scpi_dev_inst *scpi, int value);