X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fhp-3457a%2Fapi.c;h=1a5e5d920a8f9f0f03191ba3f4de204582681c73;hb=88a0265ebcb265ba839c02cc5bcd39e359c9f60f;hp=d19e0827571e46b308ab3783bc6c729cbea17f83;hpb=db23af7fc26c9a69d500d806b060c131361e9565;p=libsigrok.git diff --git a/src/hardware/hp-3457a/api.c b/src/hardware/hp-3457a/api.c index d19e0827..1a5e5d92 100644 --- a/src/hardware/hp-3457a/api.c +++ b/src/hardware/hp-3457a/api.c @@ -43,13 +43,19 @@ static int create_front_channel(struct sr_dev_inst *sdi, int chan_idx) { struct sr_channel *channel; struct sr_channel_group *front; + struct channel_context *chanc; + + chanc = g_malloc(sizeof(*chanc)); + chanc->location = CONN_FRONT; channel = sr_channel_new(sdi, chan_idx++, SR_CHANNEL_ANALOG, TRUE, "Front"); + channel->priv = chanc; front = g_malloc0(sizeof(*front)); front->name = g_strdup("Front"); front->channels = g_slist_append(front->channels, channel); + sdi->channel_groups = g_slist_append(sdi->channel_groups, front); return chan_idx; @@ -58,13 +64,40 @@ static int create_front_channel(struct sr_dev_inst *sdi, int chan_idx) static int create_rear_channels(struct sr_dev_inst *sdi, int chan_idx, const struct rear_card_info *card) { - (void) sdi; + unsigned int i; + struct sr_channel *channel; + struct sr_channel_group *group; + struct channel_context *chanc; + char name[16]; /* When card is NULL, we couldn't identify the type of card. */ if (!card) return chan_idx; - /* TODO: Create channel descriptor for plug-in cards here. */ + group = g_malloc0(sizeof(*group)); + group->priv = NULL; + group->name = g_strdup(card->cg_name); + sdi->channel_groups = g_slist_append(sdi->channel_groups, group); + + for (i = 0; i < card->num_channels; i++) { + + chanc = g_malloc(sizeof(*chanc)); + chanc->location = CONN_REAR; + + if (card->type == REAR_TERMINALS) { + chanc->index = -1; + g_snprintf(name, sizeof(name), "%s", card->cg_name); + } else { + chanc->index = i; + g_snprintf(name, sizeof(name), "%s%u", card->cg_name, i); + } + + channel = sr_channel_new(sdi, chan_idx++, SR_CHANNEL_ANALOG, + FALSE, name); + channel->priv = chanc; + group->channels = g_slist_append(group->channels, channel); + } + return chan_idx; } @@ -148,11 +181,6 @@ static GSList *dev_list(const struct sr_dev_driver *di) return ((struct drv_context *)(di->context))->instances; } -static int dev_clear(const struct sr_dev_driver *di) -{ - return std_dev_clear(di, NULL); -} - /* * We need to set the HP 3457A to a known state, and there are quite a number * of knobs to tweak. Here's a brief explanation of what's going on. For more @@ -180,7 +208,7 @@ static int dev_open(struct sr_dev_inst *sdi) if (sr_scpi_open(scpi) != SR_OK) return SR_ERR; - devc=sdi->priv; + devc = sdi->priv; sr_scpi_send(scpi, "PRESET"); sr_scpi_send(scpi, "INBUF ON"); @@ -199,6 +227,8 @@ static int dev_close(struct sr_dev_inst *sdi) if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; + /* Disable scan-advance (preserve relay life). */ + sr_scpi_send(scpi, "SADV HOLD"); /* Switch back to auto-triggering. */ sr_scpi_send(scpi, "TRIG AUTO"); @@ -209,11 +239,6 @@ static int dev_close(struct sr_dev_inst *sdi) return SR_OK; } -static int cleanup(const struct sr_dev_driver *di) -{ - return dev_clear(di); -} - static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { @@ -242,6 +267,7 @@ static int config_set(uint32_t key, GVariant *data, { int ret; enum sr_mq mq; + enum sr_mqflag mq_flags; struct dev_context *devc; GVariant *tuple_child; @@ -260,7 +286,9 @@ static int config_set(uint32_t key, GVariant *data, case SR_CONF_MEASURED_QUANTITY: tuple_child = g_variant_get_child_value(data, 0); mq = g_variant_get_uint32(tuple_child); - ret = hp_3457a_set_mq(sdi, mq); + tuple_child = g_variant_get_child_value(data, 1); + mq_flags = g_variant_get_uint64(tuple_child); + ret = hp_3457a_set_mq(sdi, mq, mq_flags); g_variant_unref(tuple_child); break; case SR_CONF_ADC_POWERLINE_CYCLES: @@ -310,6 +338,21 @@ static int config_list(uint32_t key, GVariant **data, return ret; } +static void create_channel_index_list(GSList *channels, GArray **arr) +{ + struct sr_channel *channel; + struct channel_context *chanc; + GSList *list_elem; + + *arr = g_array_new(FALSE, FALSE, sizeof(unsigned int)); + + for (list_elem = channels; list_elem; list_elem = list_elem->next) { + channel = list_elem->data; + chanc = channel->priv; + g_array_append_val(*arr, chanc->index); + } +} + /* * TRIG SGL * Trigger the first measurement, then hold. We can't let the instrument @@ -318,14 +361,21 @@ static int config_list(uint32_t key, GVariant **data, * reading for sample N, but a new measurement is made and when we read the * HIRES register, it contains data for sample N+1. This would produce * wrong readings. + * SADV AUTO + * Activate the scan-advance feature. This automatically connects the next + * channel in the scan list to the A/D converter. This way, we do not need to + * occupy the HP-IB bus to send channel select commands. */ -static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) +static int dev_acquisition_start(const struct sr_dev_inst *sdi) { int ret; + gboolean front_selected, rear_selected; struct sr_scpi_dev_inst *scpi; + struct sr_channel *channel; struct dev_context *devc; - - (void)cb_data; + struct channel_context *chanc; + GArray *ch_list; + GSList *channels; if (sdi->status != SR_ST_ACTIVE) return SR_ERR_DEV_CLOSED; @@ -340,6 +390,44 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) std_session_send_df_header(sdi, LOG_PREFIX); + front_selected = rear_selected = FALSE; + devc->active_channels = NULL; + + for (channels = sdi->channels; channels; channels = channels->next) { + channel = channels->data; + + if (!channel->enabled) + continue; + + chanc = channel->priv; + + if (chanc->location == CONN_FRONT) + front_selected = TRUE; + if (chanc->location == CONN_REAR) + rear_selected = TRUE; + + devc->active_channels = g_slist_append(devc->active_channels, channel); + } + + if (front_selected && rear_selected) { + sr_err("Can not use front and rear channels at the same time!"); + g_slist_free(devc->active_channels); + return SR_ERR_ARG; + } + + devc->current_channel = devc->active_channels->data; + devc->num_active_channels = g_slist_length(devc->active_channels); + + hp_3457a_select_input(sdi, front_selected ? CONN_FRONT : CONN_REAR); + + /* For plug-in cards, use the scan-advance features to scan channels. */ + if (rear_selected && (devc->rear_card->card_id != REAR_TERMINALS)) { + create_channel_index_list(devc->active_channels, &ch_list); + hp_3457a_send_scan_list(sdi, (void *)ch_list->data, ch_list->len); + sr_scpi_send(scpi, "SADV AUTO"); + g_array_free(ch_list, TRUE); + } + /* Start first measurement. */ sr_scpi_send(scpi, "TRIG SGL"); devc->acq_state = ACQ_TRIGGERED_MEASUREMENT; @@ -348,12 +436,13 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) return SR_OK; } -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; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; + devc = sdi->priv; + + g_slist_free(devc->active_channels); return SR_OK; } @@ -363,10 +452,9 @@ SR_PRIV struct sr_dev_driver hp_3457a_driver_info = { .longname = "HP 3457A", .api_version = 1, .init = init, - .cleanup = cleanup, + .cleanup = std_cleanup, .scan = scan, .dev_list = dev_list, - .dev_clear = dev_clear, .config_get = config_get, .config_set = config_set, .config_list = config_list,