X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fhp-3457a%2Fapi.c;h=64fdab54deef5cbc875d57f3b3c07fbb84a498c5;hb=755793e991c4d429f99254f23008bfddb89d8e00;hp=1b652bdd9a0deaf13462da67fd7352c023b4690b;hpb=2c04f943efb4f7590941c44c27d8ca5d831b82dd;p=libsigrok.git diff --git a/src/hardware/hp-3457a/api.c b/src/hardware/hp-3457a/api.c index 1b652bdd..64fdab54 100644 --- a/src/hardware/hp-3457a/api.c +++ b/src/hardware/hp-3457a/api.c @@ -31,25 +31,31 @@ static const uint32_t drvopts[] = { }; static const uint32_t devopts[] = { - SR_CONF_CONTINUOUS | SR_CONF_SET, + SR_CONF_CONTINUOUS, SR_CONF_LIMIT_SAMPLES | SR_CONF_SET, SR_CONF_MEASURED_QUANTITY | SR_CONF_SET, SR_CONF_ADC_POWERLINE_CYCLES | SR_CONF_SET | SR_CONF_GET, }; -SR_PRIV struct sr_dev_driver hp_3457a_driver_info; +static struct sr_dev_driver hp_3457a_driver_info; 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; } @@ -133,26 +166,11 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi) return sdi; } -static int init(struct sr_dev_driver *di, struct sr_context *sr_ctx) -{ - return std_init(sr_ctx, di, LOG_PREFIX); -} - static GSList *scan(struct sr_dev_driver *di, GSList *options) { return sr_scpi_scan(di->context, options, probe_device); } -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,15 +198,13 @@ 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"); sr_scpi_send(scpi, "TRIG HOLD"); sr_scpi_get_float(scpi, "NPLC?", &devc->nplc); - sdi->status = SR_ST_ACTIVE; - return SR_OK; } @@ -196,35 +212,25 @@ static int dev_close(struct sr_dev_inst *sdi) { struct sr_scpi_dev_inst *scpi = sdi->conn; - 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"); sr_scpi_close(scpi); - sdi->status = SR_ST_INACTIVE; - 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) { - int ret; struct dev_context *devc; (void)cg; devc = sdi->priv; - ret = SR_OK; switch (key) { case SR_CONF_ADC_POWERLINE_CYCLES: *data = g_variant_new_double(devc->nplc); @@ -233,14 +239,12 @@ static int config_get(uint32_t key, GVariant **data, return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_set(uint32_t key, GVariant *data, - const struct sr_dev_inst *sdi, - const struct sr_channel_group *cg) + const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ret; enum sr_mq mq; enum sr_mqflag mq_flags; struct dev_context *devc; @@ -248,12 +252,8 @@ static int config_set(uint32_t key, GVariant *data, (void)cg; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; - devc = sdi->priv; - ret = SR_OK; switch (key) { case SR_CONF_LIMIT_SAMPLES: devc->limit_samples = g_variant_get_uint64(data); @@ -263,54 +263,41 @@ static int config_set(uint32_t key, GVariant *data, mq = g_variant_get_uint32(tuple_child); 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; + return hp_3457a_set_mq(sdi, mq, mq_flags); case SR_CONF_ADC_POWERLINE_CYCLES: - ret = hp_3457a_set_nplc(sdi, g_variant_get_double(data)); - break; + return hp_3457a_set_nplc(sdi, g_variant_get_double(data)); default: - ret = SR_ERR_NA; + return SR_ERR_NA; } - return ret; + return SR_OK; } static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { - int ret; - - if (key == SR_CONF_SCAN_OPTIONS) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - scanopts, ARRAY_SIZE(scanopts), sizeof(uint32_t)); - return SR_OK; - } else if ((key == SR_CONF_DEVICE_OPTIONS) && !sdi) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - drvopts, ARRAY_SIZE(drvopts), sizeof(uint32_t)); - return SR_OK; - } else if ((key == SR_CONF_DEVICE_OPTIONS) && !cg) { - *data = g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, - devopts, ARRAY_SIZE(devopts), sizeof(uint32_t)); - return SR_OK; - } - - /* From here on, we're only concerned with channel group config. */ - if (!cg) - return SR_ERR_NA; - /* * TODO: Implement channel group configuration when adding support for * plug-in cards. */ - ret = SR_OK; - switch (key) { - default: - ret = SR_ERR_NA; - } + return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts); +} - 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); + } } /* @@ -321,17 +308,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; - - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; + struct channel_context *chanc; + GArray *ch_list; + GSList *channels; scpi = sdi->conn; devc = sdi->priv; @@ -341,7 +332,50 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi, void *cb_data) if (ret != SR_OK) return ret; - std_session_send_df_header(sdi, LOG_PREFIX); + std_session_send_df_header(sdi); + + 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->num_active_channels = g_slist_length(devc->active_channels); + if (!devc->num_active_channels) { + sr_err("Need at least one active channel!"); + g_slist_free(devc->active_channels); + return SR_ERR_ARG; + } + devc->current_channel = devc->active_channels->data; + + 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"); @@ -351,25 +385,26 @@ 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; + + devc = sdi->priv; - if (sdi->status != SR_ST_ACTIVE) - return SR_ERR_DEV_CLOSED; + g_slist_free(devc->active_channels); return SR_OK; } -SR_PRIV struct sr_dev_driver hp_3457a_driver_info = { +static struct sr_dev_driver hp_3457a_driver_info = { .name = "hp-3457a", .longname = "HP 3457A", .api_version = 1, - .init = init, - .cleanup = cleanup, + .init = std_init, + .cleanup = std_cleanup, .scan = scan, - .dev_list = dev_list, - .dev_clear = dev_clear, + .dev_list = std_dev_list, + .dev_clear = std_dev_clear, .config_get = config_get, .config_set = config_set, .config_list = config_list, @@ -379,3 +414,4 @@ SR_PRIV struct sr_dev_driver hp_3457a_driver_info = { .dev_acquisition_stop = dev_acquisition_stop, .context = NULL, }; +SR_REGISTER_DEV_DRIVER(hp_3457a_driver_info);