]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/hp-3457a/api.c
Remove unnecessary dev_clear() callbacks
[libsigrok.git] / src / hardware / hp-3457a / api.c
index 1b652bdd9a0deaf13462da67fd7352c023b4690b..1a5e5d920a8f9f0f03191ba3f4de204582681c73 100644 (file)
@@ -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)
 {
@@ -313,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
@@ -321,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;
@@ -343,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;
@@ -351,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;
 }
@@ -366,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,