SR_CONF_SERIALCOMM,
};
+static struct pps_channel_instance pci[] = {
+ { SR_MQ_VOLTAGE, SCPI_CMD_GET_MEAS_VOLTAGE, "V" },
+ { SR_MQ_CURRENT, SCPI_CMD_GET_MEAS_CURRENT, "I" },
+ { SR_MQ_POWER, SCPI_CMD_GET_MEAS_POWER, "P" },
+};
+
static int init(struct sr_context *sr_ctx)
{
return std_init(sr_ctx, di, LOG_PREFIX);
struct sr_channel_group *cg;
struct sr_channel *ch;
const struct scpi_pps *device;
+ struct pps_channel *pch;
const struct channel_group_spec *cgs;
struct pps_channel_group *pcg;
GRegex *model_re;
GMatchInfo *model_mi;
+ GSList *l;
uint64_t mask;
- unsigned int i, j;
+ unsigned int ch_num, ch_idx, old_idx, i, j;
const char *vendor;
+ char ch_name[16];
if (sr_scpi_get_hw_id(scpi, &hw_info) != SR_OK) {
sr_info("Couldn't get IDN response.");
devc->device = device;
sdi->priv = devc;
- for (i = 0; i < device->num_channels; i++) {
- ch = sr_channel_new(i, SR_CHANNEL_ANALOG, TRUE,
- device->channels[i].name);
- sdi->channels = g_slist_append(sdi->channels, ch);
+ ch_idx = 0;
+ for (ch_num = 0; ch_num < device->num_channels; ch_num++) {
+ /* Create one channel per measurable output unit. */
+ old_idx = ch_idx;
+ for (i = 0; i < ARRAY_SIZE(pci); i++) {
+ if (!scpi_cmd_get(sdi, pci[i].command))
+ continue;
+ g_snprintf(ch_name, 16, "%s%s", pci[i].prefix,
+ device->channels[ch_num].name);
+ ch = sr_channel_new(ch_idx++, SR_CHANNEL_ANALOG, TRUE, ch_name);
+ pch = g_malloc0(sizeof(struct pps_channel));
+ pch->hw_output_idx = ch_num;
+ pch->hwname = device->channels[ch_num].name;
+ pch->mq = pci[i].mq;
+ ch->priv = pch;
+ sdi->channels = g_slist_append(sdi->channels, ch);
+ }
+ if (ch_idx == old_idx) {
+ /*
+ * Didn't create any channels for this hardware output.
+ * This can happen if the device has no measurement capability.
+ */
+ g_free(pch);
+ continue;
+ }
}
for (i = 0; i < device->num_channel_groups; i++) {
cg->name = g_strdup(cgs->name);
for (j = 0, mask = 1; j < 64; j++, mask <<= 1) {
if (cgs->channel_index_mask & mask) {
- ch = g_slist_nth_data(sdi->channels, j);
- cg->channels = g_slist_append(cg->channels, ch);
+ for (l = sdi->channels; l; l = l->next) {
+ ch = l->data;
+ pch = ch->priv;
+ if (pch->hw_output_idx == j)
+ cg->channels = g_slist_append(cg->channels, ch);
+ }
}
}
pcg = g_malloc0(sizeof(struct pps_channel_group));
struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
struct sr_channel *ch;
+ struct pps_channel *pch;
const GVariantType *gvtype;
unsigned int i;
int cmd, ret;
* These options only apply to channel groups with a single
* channel -- they're per-channel settings for the device.
*/
- if (g_slist_length(cg->channels) > 1)
- return SR_ERR_NA;
/*
* Config keys are handled below depending on whether a channel
}
ch = cg->channels->data;
+ pch = ch->priv;
}
gvtype = NULL;
}
if (gvtype) {
if (cg)
- ret = scpi_cmd_resp(sdi, data, gvtype, cmd, ch->name);
+ ret = scpi_cmd_resp(sdi, data, gvtype, cmd, pch->hwname);
else
ret = scpi_cmd_resp(sdi, data, gvtype, cmd);
} else if (cg) {
switch (key) {
case SR_CONF_OUTPUT_REGULATION:
ret = SR_ERR;
- if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_REGULATION, ch->name) == SR_OK) {
+ if (scpi_cmd(sdi, SCPI_CMD_GET_OUTPUT_REGULATION, pch->hwname) == SR_OK) {
if (sr_scpi_get_string(scpi, NULL, &s) == SR_OK) {
if (strcmp(s, "CC") && strcmp(s, "CV") && strcmp(s, "UR")) {
sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
const struct sr_channel_group *cg)
{
struct sr_channel *ch;
+ struct pps_channel *pch;
double d;
int ret;
const char *s;
if (g_slist_length(cg->channels) > 1)
return SR_ERR_NA;
ch = cg->channels->data;
+ pch = ch->priv;
switch (key) {
case SR_CONF_OUTPUT_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
- ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, ch->name, s);
+ ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLED, pch->hwname, s);
break;
case SR_CONF_OUTPUT_VOLTAGE_MAX:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, ch->name, d);
+ ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_MAX, pch->hwname, d);
break;
case SR_CONF_OUTPUT_CURRENT_MAX:
d = g_variant_get_double(data);
- ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, ch->name, d);
+ ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_MAX, pch->hwname, d);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLED,
- ch->name, s);
+ pch->hwname, s);
break;
case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD,
- ch->name, d);
+ pch->hwname, d);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
s = g_variant_get_boolean(data) ? "ON" : "OFF";
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLED,
- ch->name, s);
+ pch->hwname, s);
break;
case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD:
d = g_variant_get_double(data);
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD,
- ch->name, d);
+ pch->hwname, d);
break;
default:
ret = SR_ERR_NA;
}
} else {
/* Channel group specified. */
- if (!sdi)
- return SR_ERR_ARG;
/*
* Per-channel-group options depending on a channel are actually
* done with the first channel. Channel groups in PPS can have
* more than one channel, but they will typically be of equal
- * specification for use in series or parallel mode. Drop requests
- * for groups with more than one channel just to make sure.
+ * specification for use in series or parallel mode.
*/
- if (g_slist_length(cg->channels) > 1)
- return SR_ERR_NA;
ch = cg->channels->data;
switch (key) {
struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
struct sr_channel *ch;
- int ret;
+ struct pps_channel *pch;
+ int cmd, ret;
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
scpi = sdi->conn;
devc->cb_data = cb_data;
- if ((ret = sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 100,
+ if ((ret = sr_scpi_source_add(sdi->session, scpi, G_IO_IN, 10,
scpi_pps_receive_data, (void *)sdi)) != SR_OK)
return ret;
std_session_send_df_header(sdi, LOG_PREFIX);
- /* Prime the pipe. */
- devc->state = STATE_VOLTAGE;
+ /* Prime the pipe with the first channel's fetch. */
ch = sdi->channels->data;
+ pch = ch->priv;
devc->cur_channel = ch;
- scpi_cmd(sdi, SCPI_CMD_GET_MEAS_VOLTAGE, ch->name);
+ if (pch->mq == SR_MQ_VOLTAGE)
+ cmd = SCPI_CMD_GET_MEAS_VOLTAGE;
+ else if (pch->mq == SR_MQ_CURRENT)
+ cmd = SCPI_CMD_GET_MEAS_CURRENT;
+ else if (pch->mq == SR_MQ_POWER)
+ cmd = SCPI_CMD_GET_MEAS_POWER;
+ else
+ return SR_ERR;
+ scpi_cmd(sdi, cmd, pch->hwname);
return SR_OK;
}
static int dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
{
- struct dev_context *devc;
struct sr_scpi_dev_inst *scpi;
float f;
if (sdi->status != SR_ST_ACTIVE)
return SR_ERR_DEV_CLOSED;
- devc = sdi->priv;
scpi = sdi->conn;
/*
sr_scpi_get_float(scpi, NULL, &f);
sr_scpi_source_remove(sdi->session, scpi);
- /* Just in case something is queued up. */
- devc->state = STATE_STOP;
-
return SR_OK;
}
struct sr_datafeed_analog analog;
const struct sr_dev_inst *sdi;
struct sr_scpi_dev_inst *scpi;
+ struct pps_channel *pch;
GSList *l;
float f;
+ int cmd;
(void)fd;
(void)revents;
if (!(devc = sdi->priv))
return TRUE;
- if (devc->state == STATE_STOP)
- return TRUE;
-
scpi = sdi->conn;
/* Retrieve requested value for this state. */
if (sr_scpi_get_float(scpi, NULL, &f) == SR_OK) {
+ pch = devc->cur_channel->priv;
packet.type = SR_DF_ANALOG;
packet.payload = &analog;
analog.channels = g_slist_append(NULL, devc->cur_channel);
analog.num_samples = 1;
- if (devc->state == STATE_VOLTAGE) {
- analog.mq = SR_MQ_VOLTAGE;
+ analog.mq = pch->mq;
+ if (pch->mq == SR_MQ_VOLTAGE)
analog.unit = SR_UNIT_VOLT;
- } else {
- analog.mq = SR_MQ_CURRENT;
+ else if (pch->mq == SR_MQ_CURRENT)
analog.unit = SR_UNIT_AMPERE;
- }
+ else if (pch->mq == SR_MQ_POWER)
+ analog.unit = SR_UNIT_WATT;
analog.mqflags = SR_MQFLAG_DC;
analog.data = &f;
sr_session_send(sdi, &packet);
g_slist_free(analog.channels);
}
- if (devc->state == STATE_VOLTAGE) {
- /* Just got voltage, request current for this channel. */
- devc->state = STATE_CURRENT;
- scpi_cmd(sdi, SCPI_CMD_GET_MEAS_CURRENT, devc->cur_channel->name);
- } else if (devc->state == STATE_CURRENT) {
- /*
- * Done with voltage and current for this channel, switch to
- * the next enabled channel.
- */
- do {
- l = g_slist_find(sdi->channels, devc->cur_channel);
- if (l->next)
- devc->cur_channel = l->next->data;
- else
- devc->cur_channel = sdi->channels->data;
- } while (!devc->cur_channel->enabled);
-
- /* Request voltage. */
- devc->state = STATE_VOLTAGE;
- scpi_cmd(sdi, SCPI_CMD_GET_MEAS_VOLTAGE, devc->cur_channel->name);
- }
+ /* Find next enabled channel. */
+ do {
+ l = g_slist_find(sdi->channels, devc->cur_channel);
+ if (l->next)
+ devc->cur_channel = l->next->data;
+ else
+ devc->cur_channel = sdi->channels->data;
+ } while (!devc->cur_channel->enabled);
+
+ pch = devc->cur_channel->priv;
+ if (pch->mq == SR_MQ_VOLTAGE)
+ cmd = SCPI_CMD_GET_MEAS_VOLTAGE;
+ else if (pch->mq == SR_MQ_CURRENT)
+ cmd = SCPI_CMD_GET_MEAS_CURRENT;
+ else if (pch->mq == SR_MQ_POWER)
+ cmd = SCPI_CMD_GET_MEAS_POWER;
+ else
+ return SR_ERR;
+ scpi_cmd(sdi, cmd, pch->hwname);
return TRUE;
}