X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fhameg-hmo%2Fprotocol.c;h=41b14d48b71aa5b10fe01cec522b23a5ae6c5333;hb=d779dcacb70ffcfed190612e39a3ac5df62b31e0;hp=6d2ad3c413a92466e36ba88297dfbfa5725bf386;hpb=692716f5d1aae4ef06c67b57aaf253f46f538c33;p=libsigrok.git diff --git a/src/hardware/hameg-hmo/protocol.c b/src/hardware/hameg-hmo/protocol.c index 6d2ad3c4..41b14d48 100644 --- a/src/hardware/hameg-hmo/protocol.c +++ b/src/hardware/hameg-hmo/protocol.c @@ -59,6 +59,7 @@ static const char *hameg_scpi_dialect[] = { static const uint32_t devopts[] = { SR_CONF_OSCILLOSCOPE, + SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, SR_CONF_LIMIT_FRAMES | SR_CONF_GET | SR_CONF_SET, SR_CONF_SAMPLERATE | SR_CONF_GET, SR_CONF_TIMEBASE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, @@ -88,19 +89,30 @@ static const char *scope_trigger_slopes[] = { "EITH", }; -static const char *compact2_trigger_sources[] = { +/* HMO compact2 */ +static const char *an2_dig8_trigger_sources[] = { "CH1", "CH2", "LINE", "EXT", "PATT", "BUS1", "BUS2", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", }; -static const char *compact4_trigger_sources[] = { +/* HMO xxx2 */ +static const char *an2_dig16_trigger_sources[] = { + "CH1", "CH2", + "LINE", "EXT", "PATT", "BUS1", "BUS2", + "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", + "D8", "D9", "D10", "D11", "D12", "D13", "D14", "D15", +}; + +/* HMO compact4 */ +static const char *an4_dig8_trigger_sources[] = { "CH1", "CH2", "CH3", "CH4", "LINE", "EXT", "PATT", "BUS1", "BUS2", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", }; -static const char *compact4_dig16_trigger_sources[] = { +/* HMO xxx4 */ +static const char *an4_dig16_trigger_sources[] = { "CH1", "CH2", "CH3", "CH4", "LINE", "EXT", "PATT", "BUS1", "BUS2", "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", @@ -177,9 +189,8 @@ static const char *scope_digital_channel_names[] = { static const struct scope_config scope_models[] = { { - /* HMO2522/3032/3042/3052 support 16 digital channels but they're not supported yet. */ - .name = {"HMO1002", "HMO722", "HMO1022", "HMO1522", "HMO2022", "HMO2522", - "HMO3032", "HMO3042", "HMO3052", NULL}, + /* HMO722/1002/1022/1522/2022 support only 8 digital channels. */ + .name = {"HMO722", "HMO1002", "HMO1022", "HMO1522", "HMO2022", NULL}, .analog_channels = 2, .digital_channels = 8, .digital_pods = 1, @@ -196,8 +207,44 @@ static const struct scope_config scope_models[] = { .coupling_options = &coupling_options, .num_coupling_options = ARRAY_SIZE(coupling_options), - .trigger_sources = &compact2_trigger_sources, - .num_trigger_sources = ARRAY_SIZE(compact2_trigger_sources), + .trigger_sources = &an2_dig8_trigger_sources, + .num_trigger_sources = ARRAY_SIZE(an2_dig8_trigger_sources), + + .trigger_slopes = &scope_trigger_slopes, + .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes), + + .timebases = &timebases, + .num_timebases = ARRAY_SIZE(timebases), + + .vdivs = &vdivs, + .num_vdivs = ARRAY_SIZE(vdivs), + + .num_xdivs = 12, + .num_ydivs = 8, + + .scpi_dialect = &hameg_scpi_dialect, + }, + { + /* HMO3032/3042/3052/3522 support 16 digital channels. */ + .name = {"HMO3032", "HMO3042", "HMO3052", "HMO3522", NULL}, + .analog_channels = 2, + .digital_channels = 16, + .digital_pods = 2, + + .analog_names = &scope_analog_channel_names, + .digital_names = &scope_digital_channel_names, + + .devopts = &devopts, + .num_devopts = ARRAY_SIZE(devopts), + + .devopts_cg_analog = &devopts_cg_analog, + .num_devopts_cg_analog = ARRAY_SIZE(devopts_cg_analog), + + .coupling_options = &coupling_options, + .num_coupling_options = ARRAY_SIZE(coupling_options), + + .trigger_sources = &an2_dig16_trigger_sources, + .num_trigger_sources = ARRAY_SIZE(an2_dig16_trigger_sources), .trigger_slopes = &scope_trigger_slopes, .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes), @@ -231,8 +278,8 @@ static const struct scope_config scope_models[] = { .coupling_options = &coupling_options, .num_coupling_options = ARRAY_SIZE(coupling_options), - .trigger_sources = &compact4_trigger_sources, - .num_trigger_sources = ARRAY_SIZE(compact4_trigger_sources), + .trigger_sources = &an4_dig8_trigger_sources, + .num_trigger_sources = ARRAY_SIZE(an4_dig8_trigger_sources), .trigger_slopes = &scope_trigger_slopes, .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes), @@ -266,8 +313,8 @@ static const struct scope_config scope_models[] = { .coupling_options = &coupling_options, .num_coupling_options = ARRAY_SIZE(coupling_options), - .trigger_sources = &compact4_dig16_trigger_sources, - .num_trigger_sources = ARRAY_SIZE(compact4_dig16_trigger_sources), + .trigger_sources = &an4_dig16_trigger_sources, + .num_trigger_sources = ARRAY_SIZE(an4_dig16_trigger_sources), .trigger_slopes = &scope_trigger_slopes, .num_trigger_slopes = ARRAY_SIZE(scope_trigger_slopes), @@ -329,27 +376,22 @@ static int scope_state_get_array_option(struct sr_scpi_dev_inst *scpi, const char *command, const char *(*array)[], unsigned int n, int *result) { char *tmp; - unsigned int i; + int idx; if (sr_scpi_get_string(scpi, command, &tmp) != SR_OK) { g_free(tmp); return SR_ERR; } - for (i = 0; i < n; i++) { - if (!g_strcmp0(tmp, (*array)[i])) { - *result = i; - g_free(tmp); - tmp = NULL; - break; - } - } - - if (tmp) { + if ((idx = std_str_idx_s(tmp, *array, n)) < 0) { g_free(tmp); - return SR_ERR; + return SR_ERR_ARG; } + *result = idx; + + g_free(tmp); + return SR_OK; } @@ -384,13 +426,29 @@ static int array_float_get(gchar *value, const uint64_t array[][2], return SR_ERR; } -static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi, +static struct sr_channel *get_channel_by_index_and_type(GSList *channel_lhead, + int index, int type) +{ + while (channel_lhead) { + struct sr_channel *ch = channel_lhead->data; + if (ch->index == index && ch->type == type) + return ch; + + channel_lhead = channel_lhead->next; + } + + return 0; +} + +static int analog_channel_state_get(struct sr_dev_inst *sdi, const struct scope_config *config, struct scope_state *state) { unsigned int i, j; char command[MAX_COMMAND_SIZE]; char *tmp_str; + struct sr_channel *ch; + struct sr_scpi_dev_inst *scpi = sdi->conn; for (i = 0; i < config->analog_channels; i++) { g_snprintf(command, sizeof(command), @@ -401,6 +459,10 @@ static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi, &state->analog_channels[i].state) != SR_OK) return SR_ERR; + ch = get_channel_by_index_and_type(sdi->channels, i, SR_CHANNEL_ANALOG); + if (ch) + ch->enabled = state->analog_channels[i].state; + g_snprintf(command, sizeof(command), (*config->scpi_dialect)[SCPI_CMD_GET_VERTICAL_DIV], i + 1); @@ -451,12 +513,14 @@ static int analog_channel_state_get(struct sr_scpi_dev_inst *scpi, return SR_OK; } -static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi, +static int digital_channel_state_get(struct sr_dev_inst *sdi, const struct scope_config *config, struct scope_state *state) { unsigned int i; char command[MAX_COMMAND_SIZE]; + struct sr_channel *ch; + struct sr_scpi_dev_inst *scpi = sdi->conn; for (i = 0; i < config->digital_channels; i++) { g_snprintf(command, sizeof(command), @@ -466,6 +530,10 @@ static int digital_channel_state_get(struct sr_scpi_dev_inst *scpi, if (sr_scpi_get_bool(scpi, command, &state->digital_channels[i]) != SR_OK) return SR_ERR; + + ch = get_channel_by_index_and_type(sdi->channels, i, SR_CHANNEL_LOGIC); + if (ch) + ch->enabled = state->digital_channels[i]; } for (i = 0; i < config->digital_pods; i++) { @@ -486,7 +554,6 @@ SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi) struct dev_context *devc; struct scope_state *state; const struct scope_config *config; - int tmp; unsigned int i; float tmp_float; @@ -500,8 +567,21 @@ SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi) channel_found = FALSE; for (i = 0; i < config->analog_channels; i++) { - if (state->analog_channels[i].state) { - g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1); + if (!state->analog_channels[i].state) + continue; + g_snprintf(chan_name, sizeof(chan_name), "CHAN%d", i + 1); + g_snprintf(tmp_str, sizeof(tmp_str), + (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE], + chan_name); + channel_found = TRUE; + break; + } + + if (!channel_found) { + for (i = 0; i < config->digital_pods; i++) { + if (!state->digital_pods[i]) + continue; + g_snprintf(chan_name, sizeof(chan_name), "POD%d", i); g_snprintf(tmp_str, sizeof(tmp_str), (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE], chan_name); @@ -510,19 +590,6 @@ SR_PRIV int hmo_update_sample_rate(const struct sr_dev_inst *sdi) } } - if (!channel_found) { - for (i = 0; i < config->digital_pods; i++) { - if (state->digital_pods[i]) { - g_snprintf(chan_name, sizeof(chan_name), "POD%d", i); - g_snprintf(tmp_str, sizeof(tmp_str), - (*config->scpi_dialect)[SCPI_CMD_GET_SAMPLE_RATE_LIVE], - chan_name); - channel_found = TRUE; - break; - } - } - } - /* No channel is active, ask the instrument for the sample rate * in single shot mode */ if (!channel_found) { @@ -558,10 +625,10 @@ SR_PRIV int hmo_scope_state_get(struct sr_dev_inst *sdi) sr_info("Fetching scope state"); - if (analog_channel_state_get(sdi->conn, config, state) != SR_OK) + if (analog_channel_state_get(sdi, config, state) != SR_OK) return SR_ERR; - if (digital_channel_state_get(sdi->conn, config, state) != SR_OK) + if (digital_channel_state_get(sdi, config, state) != SR_OK) return SR_ERR; if (sr_scpi_get_float(sdi->conn, @@ -640,11 +707,11 @@ SR_PRIV void hmo_scope_state_free(struct scope_state *state) SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi) { - char tmp[25]; int model_index; unsigned int i, j, group; struct sr_channel *ch; struct dev_context *devc; + int ret; devc = sdi->priv; model_index = -1; @@ -668,9 +735,13 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi) devc->analog_groups = g_malloc0(sizeof(struct sr_channel_group*) * scope_models[model_index].analog_channels); - devc->digital_groups = g_malloc0(sizeof(struct sr_channel_group*) * scope_models[model_index].digital_pods); + if (!devc->analog_groups || !devc->digital_groups) { + g_free(devc->analog_groups); + g_free(devc->digital_groups); + return SR_ERR_MALLOC; + } /* Add analog channels. */ for (i = 0; i < scope_models[model_index].analog_channels; i++) { @@ -688,15 +759,19 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi) } /* Add digital channel groups. */ + ret = SR_OK; for (i = 0; i < scope_models[model_index].digital_pods; i++) { - g_snprintf(tmp, 25, "POD%d", i); - devc->digital_groups[i] = g_malloc0(sizeof(struct sr_channel_group)); - - devc->digital_groups[i]->name = g_strdup(tmp); + if (!devc->digital_groups[i]) { + ret = SR_ERR_MALLOC; + break; + } + devc->digital_groups[i]->name = g_strdup_printf("POD%d", i); sdi->channel_groups = g_slist_append(sdi->channel_groups, devc->digital_groups[i]); } + if (ret != SR_OK) + return ret; /* Add digital channels. */ for (i = 0; i < scope_models[model_index].digital_channels; i++) { @@ -709,6 +784,7 @@ SR_PRIV int hmo_init_device(struct sr_dev_inst *sdi) } devc->model_config = &scope_models[model_index]; + devc->samples_limit = 0; devc->frame_limit = 0; if (!(devc->model_state = scope_state_new(devc->model_config))) @@ -747,8 +823,6 @@ SR_PRIV void hmo_queue_logic_data(struct dev_context *devc, } else { store = devc->logic_data; size = store->len / devc->pod_count; - if (size != pod_data->len) - return; if (group >= devc->pod_count) return; } @@ -764,6 +838,10 @@ SR_PRIV void hmo_queue_logic_data(struct dev_context *devc, *logic_data = pod_data->data[idx]; logic_data += logic_step; } + + /* Truncate acquisition if a smaller number of samples has been requested. */ + if (devc->samples_limit > 0 && devc->logic_data->len > devc->samples_limit * devc->pod_count) + devc->logic_data->len = devc->samples_limit * devc->pod_count; } /* Submit data for all channels, after the individual groups got collected. */ @@ -853,7 +931,6 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) { if (data) g_byte_array_free(data, TRUE); - return TRUE; } @@ -861,6 +938,9 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) analog.data = data->data; analog.num_samples = data->len / sizeof(float); + /* Truncate acquisition if a smaller number of samples has been requested. */ + if (devc->samples_limit > 0 && analog.num_samples > devc->samples_limit) + analog.num_samples = devc->samples_limit; analog.encoding = &encoding; analog.meaning = &meaning; analog.spec = &spec; @@ -893,13 +973,15 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) spec.spec_digits = 2; packet.payload = &analog; sr_session_send(sdi, &packet); + devc->num_samples = data->len / sizeof(float); g_slist_free(meaning.channels); g_byte_array_free(data, TRUE); data = NULL; break; case SR_CHANNEL_LOGIC: if (sr_scpi_get_block(sdi->conn, NULL, &data) != SR_OK) { - g_free(data); + if (data) + g_byte_array_free(data, TRUE); return TRUE; } @@ -920,6 +1002,9 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) packet.type = SR_DF_LOGIC; logic.data = data->data; logic.length = data->len; + /* Truncate acquisition if a smaller number of samples has been requested. */ + if (devc->samples_limit > 0 && logic.length > devc->samples_limit) + logic.length = devc->samples_limit; logic.unitsize = 1; packet.payload = &logic; sr_session_send(sdi, &packet); @@ -928,6 +1013,7 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) hmo_queue_logic_data(devc, group, data); } + devc->num_samples = data->len / devc->pod_count; g_byte_array_free(data, TRUE); data = NULL; break; @@ -961,10 +1047,10 @@ SR_PRIV int hmo_receive_data(int fd, int revents, void *cb_data) /* * End of frame was reached. Stop acquisition after the specified - * number of frames, or continue reception by starting over at - * the first enabled channel. + * number of frames or after the specified number of samples, or + * continue reception by starting over at the first enabled channel. */ - if (++devc->num_frames == devc->frame_limit) { + if (++devc->num_frames >= devc->frame_limit || devc->num_samples >= devc->samples_limit) { sr_dev_acquisition_stop(sdi); hmo_cleanup_logic_data(devc); } else {