scpi: Make helper functions from scpi-pps available library-wide.
This commit is contained in:
parent
5a1afc0907
commit
91ef511db2
|
@ -92,6 +92,7 @@ libsigrok_la_SOURCES += \
|
|||
# SCPI support
|
||||
libsigrok_la_SOURCES += \
|
||||
src/scpi/scpi.c \
|
||||
src/scpi/helpers.c \
|
||||
src/scpi/scpi_tcp.c
|
||||
if NEED_RPC
|
||||
libsigrok_la_SOURCES += \
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include "scpi.h"
|
||||
#include "protocol.h"
|
||||
|
||||
SR_PRIV struct sr_dev_driver scpi_pps_driver_info;
|
||||
|
@ -72,7 +73,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
|
|||
|
||||
device = NULL;
|
||||
for (i = 0; i < num_pps_profiles; i++) {
|
||||
vendor = get_vendor(hw_info->manufacturer);
|
||||
vendor = sr_vendor_alias(hw_info->manufacturer);
|
||||
if (strcasecmp(vendor, pps_profiles[i].vendor))
|
||||
continue;
|
||||
model_re = g_regex_new(pps_profiles[i].model, 0, 0, NULL);
|
||||
|
@ -128,7 +129,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
|
|||
for (ch_num = 0; ch_num < num_channels; ch_num++) {
|
||||
/* Create one channel per measurable output unit. */
|
||||
for (i = 0; i < ARRAY_SIZE(pci); i++) {
|
||||
if (!scpi_cmd_get(sdi, pci[i].command))
|
||||
if (!scpi_cmd_get(devc->device->commands, pci[i].command))
|
||||
continue;
|
||||
g_snprintf(ch_name, 16, "%s%s", pci[i].prefix,
|
||||
channels[ch_num].name);
|
||||
|
@ -165,7 +166,7 @@ static struct sr_dev_inst *probe_device(struct sr_scpi_dev_inst *scpi)
|
|||
sr_scpi_hw_info_free(hw_info);
|
||||
hw_info = NULL;
|
||||
|
||||
scpi_cmd(sdi, SCPI_CMD_LOCAL);
|
||||
scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL);
|
||||
sr_scpi_close(scpi);
|
||||
|
||||
return sdi;
|
||||
|
@ -201,13 +202,15 @@ static int dev_open(struct sr_dev_inst *sdi)
|
|||
|
||||
sdi->status = SR_ST_ACTIVE;
|
||||
|
||||
scpi_cmd(sdi, SCPI_CMD_REMOTE);
|
||||
devc = sdi->priv;
|
||||
scpi_cmd(sdi, devc->device->commands, SCPI_CMD_REMOTE);
|
||||
devc = sdi->priv;
|
||||
devc->beeper_was_set = FALSE;
|
||||
if (scpi_cmd_resp(sdi, &beeper, G_VARIANT_TYPE_BOOLEAN, SCPI_CMD_BEEPER) == SR_OK) {
|
||||
if (scpi_cmd_resp(sdi, devc->device->commands, &beeper,
|
||||
G_VARIANT_TYPE_BOOLEAN, SCPI_CMD_BEEPER) == SR_OK) {
|
||||
if (g_variant_get_boolean(beeper)) {
|
||||
devc->beeper_was_set = TRUE;
|
||||
scpi_cmd(sdi, SCPI_CMD_BEEPER_DISABLE);
|
||||
scpi_cmd(sdi, devc->device->commands, SCPI_CMD_BEEPER_DISABLE);
|
||||
}
|
||||
g_variant_unref(beeper);
|
||||
}
|
||||
|
@ -227,8 +230,8 @@ static int dev_close(struct sr_dev_inst *sdi)
|
|||
scpi = sdi->conn;
|
||||
if (scpi) {
|
||||
if (devc->beeper_was_set)
|
||||
scpi_cmd(sdi, SCPI_CMD_BEEPER_ENABLE);
|
||||
scpi_cmd(sdi, SCPI_CMD_LOCAL);
|
||||
scpi_cmd(sdi, devc->device->commands, SCPI_CMD_BEEPER_ENABLE);
|
||||
scpi_cmd(sdi, devc->device->commands, SCPI_CMD_LOCAL);
|
||||
sr_scpi_close(scpi);
|
||||
sdi->status = SR_ST_INACTIVE;
|
||||
}
|
||||
|
@ -258,6 +261,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
|
|||
const GVariantType *gvtype;
|
||||
unsigned int i;
|
||||
int cmd, ret;
|
||||
char *s;
|
||||
|
||||
if (!sdi)
|
||||
return SR_ERR_ARG;
|
||||
|
@ -347,12 +351,33 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
|
|||
gvtype = G_VARIANT_TYPE_STRING;
|
||||
cmd = SCPI_CMD_GET_OUTPUT_REGULATION;
|
||||
}
|
||||
if (gvtype) {
|
||||
if (cg)
|
||||
select_channel(sdi, cg->channels->data);
|
||||
ret = scpi_cmd_resp(sdi, data, gvtype, cmd);
|
||||
} else
|
||||
ret = SR_ERR_NA;
|
||||
if (!gvtype)
|
||||
return SR_ERR_NA;
|
||||
|
||||
if (cg)
|
||||
select_channel(sdi, cg->channels->data);
|
||||
ret = scpi_cmd_resp(sdi, devc->device->commands, data, gvtype, cmd);
|
||||
|
||||
if (cmd == SCPI_CMD_GET_OUTPUT_REGULATION) {
|
||||
/*
|
||||
* The Rigol DP800 series return CV/CC/UR, Philips PM2800
|
||||
* return VOLT/CURR. We always return a GVariant string in
|
||||
* the Rigol notation.
|
||||
*/
|
||||
if ((ret = sr_scpi_get_string(sdi->conn, NULL, &s)) != SR_OK)
|
||||
return ret;
|
||||
if (!strcmp(s, "CV") || !strcmp(s, "VOLT")) {
|
||||
*data = g_variant_new_string("CV");
|
||||
} else if (!strcmp(s, "CC") || !strcmp(s, "CURR")) {
|
||||
*data = g_variant_new_string("CC");
|
||||
} else if (!strcmp(s, "UR")) {
|
||||
*data = g_variant_new_string("UR");
|
||||
} else {
|
||||
sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
|
||||
ret = SR_ERR_DATA;
|
||||
}
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -360,6 +385,7 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *s
|
|||
static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sdi,
|
||||
const struct sr_channel_group *cg)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
double d;
|
||||
int ret;
|
||||
|
||||
|
@ -373,51 +399,65 @@ static int config_set(uint32_t key, GVariant *data, const struct sr_dev_inst *sd
|
|||
/* Channel group specified. */
|
||||
select_channel(sdi, cg->channels->data);
|
||||
|
||||
devc = sdi->priv;
|
||||
ret = SR_OK;
|
||||
switch (key) {
|
||||
case SR_CONF_ENABLED:
|
||||
if (g_variant_get_boolean(data))
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_ENABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OUTPUT_ENABLE);
|
||||
else
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OUTPUT_DISABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OUTPUT_DISABLE);
|
||||
break;
|
||||
case SR_CONF_VOLTAGE_TARGET:
|
||||
d = g_variant_get_double(data);
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_VOLTAGE_TARGET, d);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_VOLTAGE_TARGET, d);
|
||||
break;
|
||||
case SR_CONF_OUTPUT_FREQUENCY_TARGET:
|
||||
d = g_variant_get_double(data);
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_FREQUENCY_TARGET, d);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_FREQUENCY_TARGET, d);
|
||||
break;
|
||||
case SR_CONF_CURRENT_LIMIT:
|
||||
d = g_variant_get_double(data);
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_CURRENT_LIMIT, d);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_CURRENT_LIMIT, d);
|
||||
break;
|
||||
case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED:
|
||||
if (g_variant_get_boolean(data))
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_ENABLE);
|
||||
else
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_DISABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_DISABLE);
|
||||
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, d);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, d);
|
||||
break;
|
||||
case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED:
|
||||
if (g_variant_get_boolean(data))
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE);
|
||||
else
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE);
|
||||
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, d);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, d);
|
||||
break;
|
||||
case SR_CONF_OVER_TEMPERATURE_PROTECTION:
|
||||
if (g_variant_get_boolean(data))
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_ENABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_ENABLE);
|
||||
else
|
||||
ret = scpi_cmd(sdi, SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_DISABLE);
|
||||
ret = scpi_cmd(sdi, devc->device->commands,
|
||||
SCPI_CMD_SET_OVER_TEMPERATURE_PROTECTION_DISABLE);
|
||||
break;
|
||||
default:
|
||||
ret = SR_ERR_NA;
|
||||
|
@ -536,8 +576,7 @@ static int config_list(uint32_t key, GVariant **data, const struct sr_dev_inst *
|
|||
return ret;
|
||||
}
|
||||
|
||||
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, void *cb_data)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
struct sr_scpi_dev_inst *scpi;
|
||||
|
@ -572,7 +611,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi,
|
|||
cmd = SCPI_CMD_GET_MEAS_POWER;
|
||||
else
|
||||
return SR_ERR;
|
||||
scpi_cmd(sdi, cmd, pch->hwname);
|
||||
scpi_cmd(sdi, devc->device->commands, cmd, pch->hwname);
|
||||
|
||||
return SR_OK;
|
||||
}
|
||||
|
|
|
@ -26,27 +26,6 @@
|
|||
#define CH_IDX(x) (1 << x)
|
||||
#define FREQ_DC_ONLY {0, 0, 0}
|
||||
|
||||
static const char *pps_vendors[][2] = {
|
||||
{ "RIGOL TECHNOLOGIES", "Rigol" },
|
||||
{ "HEWLETT-PACKARD", "HP" },
|
||||
{ "PHILIPS", "Philips" },
|
||||
{ "CHROMA", "Chroma" },
|
||||
{ "Chroma ATE", "Chroma" },
|
||||
{ "Agilent Technologies", "Agilent" },
|
||||
};
|
||||
|
||||
SR_PRIV const char *get_vendor(const char *raw_vendor)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(pps_vendors); i++) {
|
||||
if (!strcasecmp(raw_vendor, pps_vendors[i][0]))
|
||||
return pps_vendors[i][1];
|
||||
}
|
||||
|
||||
return raw_vendor;
|
||||
}
|
||||
|
||||
static const uint32_t devopts_none[] = { };
|
||||
|
||||
/* Agilent/Keysight N5700A series */
|
||||
|
@ -96,6 +75,7 @@ static const struct scpi_command agilent_n5700a_cmd[] = {
|
|||
/* Current limit (CC mode) and OCP are set using the same command. */
|
||||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR?" },
|
||||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR %.6f" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
/* Chroma 61600 series AC source */
|
||||
|
@ -141,6 +121,7 @@ static const struct scpi_command chroma_61604_cmd[] = {
|
|||
/* This is not a current limit mode. It is overcurrent protection. */
|
||||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:LIM?" },
|
||||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:LIM %.2f" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
/* Chroma 62000 series DC source */
|
||||
|
@ -183,6 +164,7 @@ static const struct scpi_command chroma_62000_cmd[] = {
|
|||
{ SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, ":SOUR:VOLT:PROT:HIGH %.6f" },
|
||||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:PROT:HIGH?" },
|
||||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":SOUR:CURR:PROT:HIGH %.6f" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
static int chroma_62000p_probe_channels(struct sr_dev_inst *sdi,
|
||||
|
@ -307,6 +289,7 @@ static const struct scpi_command rigol_dp800_cmd[] = {
|
|||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, ":OUTP:OCP:QUES?" },
|
||||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_THRESHOLD, ":OUTP:OCP:VAL?" },
|
||||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":OUTP:OCP:VAL %.6f" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
/* HP 663xx series */
|
||||
|
@ -337,6 +320,7 @@ static const struct scpi_command hp_6632b_cmd[] = {
|
|||
{ SCPI_CMD_SET_VOLTAGE_TARGET, ":SOUR:VOLT %.6f" },
|
||||
{ SCPI_CMD_GET_CURRENT_LIMIT, ":SOUR:CURR?" },
|
||||
{ SCPI_CMD_SET_CURRENT_LIMIT, ":SOUR:CURR %.6f" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
/* Philips/Fluke PM2800 series */
|
||||
|
@ -483,6 +467,7 @@ static const struct scpi_command philips_pm2800_cmd[] = {
|
|||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_ENABLE, ":SOUR:CURR:PROT:STAT ON" },
|
||||
{ SCPI_CMD_SET_OVER_CURRENT_PROTECTION_DISABLE, ":SOUR:CURR:PROT:STAT OFF" },
|
||||
{ SCPI_CMD_GET_OVER_CURRENT_PROTECTION_ACTIVE, ":SOUR:CURR:PROT:TRIP?" },
|
||||
ALL_ZERO
|
||||
};
|
||||
|
||||
SR_PRIV const struct scpi_pps pps_profiles[] = {
|
||||
|
@ -492,7 +477,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(agilent_n5700a_devopts_cg),
|
||||
ARRAY_AND_SIZE(agilent_n5767a_ch),
|
||||
ARRAY_AND_SIZE(agilent_n5767a_cg),
|
||||
ARRAY_AND_SIZE(agilent_n5700a_cmd),
|
||||
agilent_n5700a_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
/* Chroma 61604 */
|
||||
|
@ -501,7 +486,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(chroma_61604_devopts_cg),
|
||||
ARRAY_AND_SIZE(chroma_61604_ch),
|
||||
ARRAY_AND_SIZE(chroma_61604_cg),
|
||||
ARRAY_AND_SIZE(chroma_61604_cmd),
|
||||
chroma_61604_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
/* Chroma 62000 series */
|
||||
|
@ -510,7 +495,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(chroma_62000_devopts_cg),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
ARRAY_AND_SIZE(chroma_62000_cmd),
|
||||
chroma_62000_cmd,
|
||||
.probe_channels = chroma_62000p_probe_channels,
|
||||
},
|
||||
/* HP 6632B */
|
||||
|
@ -519,7 +504,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(devopts_none),
|
||||
ARRAY_AND_SIZE(hp_6632b_ch),
|
||||
ARRAY_AND_SIZE(hp_6632b_cg),
|
||||
ARRAY_AND_SIZE(hp_6632b_cmd),
|
||||
hp_6632b_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
|
||||
|
@ -529,7 +514,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp821a_ch),
|
||||
ARRAY_AND_SIZE(rigol_dp820_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp800_cmd),
|
||||
rigol_dp800_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
{ "Rigol", "^DP831A$", PPS_OTP,
|
||||
|
@ -537,7 +522,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp831_ch),
|
||||
ARRAY_AND_SIZE(rigol_dp830_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp800_cmd),
|
||||
rigol_dp800_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
{ "Rigol", "^(DP832|DP832A)$", PPS_OTP,
|
||||
|
@ -545,7 +530,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(rigol_dp800_devopts_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp832_ch),
|
||||
ARRAY_AND_SIZE(rigol_dp830_cg),
|
||||
ARRAY_AND_SIZE(rigol_dp800_cmd),
|
||||
rigol_dp800_cmd,
|
||||
.probe_channels = NULL,
|
||||
},
|
||||
|
||||
|
@ -555,7 +540,7 @@ SR_PRIV const struct scpi_pps pps_profiles[] = {
|
|||
ARRAY_AND_SIZE(philips_pm2800_devopts_cg),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
ARRAY_AND_SIZE(philips_pm2800_cmd),
|
||||
philips_pm2800_cmd,
|
||||
philips_pm2800_probe_channels,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -20,112 +20,9 @@
|
|||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <stdarg.h>
|
||||
#include "scpi.h"
|
||||
#include "protocol.h"
|
||||
|
||||
SR_PRIV const char *scpi_cmd_get(const struct sr_dev_inst *sdi, int command)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
unsigned int i;
|
||||
const char *cmd;
|
||||
|
||||
devc = sdi->priv;
|
||||
cmd = NULL;
|
||||
for (i = 0; i < devc->device->num_commands; i++) {
|
||||
if (devc->device->commands[i].command == command) {
|
||||
cmd = devc->device->commands[i].string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...)
|
||||
{
|
||||
struct sr_scpi_dev_inst *scpi;
|
||||
va_list args;
|
||||
int ret;
|
||||
const char *cmd;
|
||||
|
||||
if (!(cmd = scpi_cmd_get(sdi, command))) {
|
||||
/* Device does not implement this command, that's OK. */
|
||||
return SR_OK_CONTINUE;
|
||||
}
|
||||
|
||||
scpi = sdi->conn;
|
||||
va_start(args, command);
|
||||
ret = sr_scpi_send_variadic(scpi, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, GVariant **gvar,
|
||||
const GVariantType *gvtype, int command, ...)
|
||||
{
|
||||
struct sr_scpi_dev_inst *scpi;
|
||||
va_list args;
|
||||
double d;
|
||||
int ret;
|
||||
char *s;
|
||||
const char *cmd;
|
||||
|
||||
if (!(cmd = scpi_cmd_get(sdi, command))) {
|
||||
/* Device does not implement this command, that's OK. */
|
||||
return SR_OK_CONTINUE;
|
||||
}
|
||||
|
||||
scpi = sdi->conn;
|
||||
va_start(args, command);
|
||||
ret = sr_scpi_send_variadic(scpi, cmd, args);
|
||||
va_end(args);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
/* Non-standard data type responses. */
|
||||
if (command == SCPI_CMD_GET_OUTPUT_REGULATION) {
|
||||
/*
|
||||
* The Rigol DP800 series return CV/CC/UR, Philips PM2800
|
||||
* return VOLT/CURR. We always return a GVariant string in
|
||||
* the Rigol notation.
|
||||
*/
|
||||
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) != SR_OK)
|
||||
return ret;
|
||||
if (!strcmp(s, "CV") || !strcmp(s, "VOLT")) {
|
||||
*gvar = g_variant_new_string("CV");
|
||||
} else if (!strcmp(s, "CC") || !strcmp(s, "CURR")) {
|
||||
*gvar = g_variant_new_string("CC");
|
||||
} else if (!strcmp(s, "UR")) {
|
||||
*gvar = g_variant_new_string("UR");
|
||||
} else {
|
||||
sr_dbg("Unknown response to SCPI_CMD_GET_OUTPUT_REGULATION: %s", s);
|
||||
ret = SR_ERR_DATA;
|
||||
}
|
||||
g_free(s);
|
||||
} else {
|
||||
/* Straight SCPI getters to GVariant types. */
|
||||
if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_BOOLEAN)) {
|
||||
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) != SR_OK)
|
||||
return ret;
|
||||
if (!strcasecmp(s, "ON") || !strcasecmp(s, "1") || !strcasecmp(s, "YES"))
|
||||
*gvar = g_variant_new_boolean(TRUE);
|
||||
else if (!strcasecmp(s, "OFF") || !strcasecmp(s, "0") || !strcasecmp(s, "NO"))
|
||||
*gvar = g_variant_new_boolean(FALSE);
|
||||
else
|
||||
ret = SR_ERR;
|
||||
g_free(s);
|
||||
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_DOUBLE)) {
|
||||
if ((ret = sr_scpi_get_double(scpi, NULL, &d)) == SR_OK)
|
||||
*gvar = g_variant_new_double(d);
|
||||
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_STRING)) {
|
||||
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) == SR_OK)
|
||||
*gvar = g_variant_new_string(s);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch)
|
||||
{
|
||||
struct dev_context *devc;
|
||||
|
@ -149,7 +46,8 @@ SR_PRIV int select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch)
|
|||
}
|
||||
}
|
||||
|
||||
if ((ret = scpi_cmd(sdi, SCPI_CMD_SELECT_CHANNEL, new_pch->hwname)) >= 0)
|
||||
if ((ret = scpi_cmd(sdi, devc->device->commands, SCPI_CMD_SELECT_CHANNEL,
|
||||
new_pch->hwname)) >= 0)
|
||||
devc->cur_channel = ch;
|
||||
|
||||
return ret;
|
||||
|
@ -235,7 +133,7 @@ SR_PRIV int scpi_pps_receive_data(int fd, int revents, void *cb_data)
|
|||
cmd = SCPI_CMD_GET_MEAS_POWER;
|
||||
else
|
||||
return SR_ERR;
|
||||
scpi_cmd(sdi, cmd);
|
||||
scpi_cmd(sdi, devc->device->commands, cmd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <glib.h>
|
||||
#include <libsigrok/libsigrok.h>
|
||||
#include "libsigrok-internal.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#define LOG_PREFIX "scpi-pps"
|
||||
|
||||
|
@ -92,7 +93,6 @@ struct scpi_pps {
|
|||
const struct channel_group_spec *channel_groups;
|
||||
unsigned int num_channel_groups;
|
||||
const struct scpi_command *commands;
|
||||
unsigned int num_commands;
|
||||
int (*probe_channels) (struct sr_dev_inst *sdi, struct sr_scpi_hw_info *hwinfo,
|
||||
struct channel_spec **channels, unsigned int *num_channels,
|
||||
struct channel_group_spec **channel_groups, unsigned int *num_channel_groups);
|
||||
|
@ -106,11 +106,6 @@ struct channel_spec {
|
|||
float frequency[3];
|
||||
};
|
||||
|
||||
struct scpi_command {
|
||||
int command;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
struct channel_group_spec {
|
||||
const char *name;
|
||||
uint64_t channel_index_mask;
|
||||
|
@ -160,10 +155,6 @@ SR_PRIV extern unsigned int num_pps_profiles;
|
|||
SR_PRIV extern const struct scpi_pps pps_profiles[];
|
||||
|
||||
SR_PRIV const char *get_vendor(const char *raw_vendor);
|
||||
SR_PRIV const char *scpi_cmd_get(const struct sr_dev_inst *sdi, int command);
|
||||
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, int command, ...);
|
||||
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, GVariant **gvar,
|
||||
const GVariantType *gvtype, int command, ...);
|
||||
SR_PRIV int select_channel(const struct sr_dev_inst *sdi, struct sr_channel *ch);
|
||||
SR_PRIV struct sr_channel *next_enabled_channel(const struct sr_dev_inst *sdi,
|
||||
struct sr_channel *cur_channel);
|
||||
|
|
13
src/scpi.h
13
src/scpi.h
|
@ -58,6 +58,11 @@ enum {
|
|||
SCPI_CMD_GET_SAMPLE_RATE_LIVE,
|
||||
};
|
||||
|
||||
struct scpi_command {
|
||||
int command;
|
||||
const char *string;
|
||||
};
|
||||
|
||||
struct sr_scpi_hw_info {
|
||||
char *manufacturer;
|
||||
char *model;
|
||||
|
@ -125,4 +130,12 @@ SR_PRIV int sr_scpi_get_hw_id(struct sr_scpi_dev_inst *scpi,
|
|||
struct sr_scpi_hw_info **scpi_response);
|
||||
SR_PRIV void sr_scpi_hw_info_free(struct sr_scpi_hw_info *hw_info);
|
||||
|
||||
SR_PRIV const char *sr_vendor_alias(const char *raw_vendor);
|
||||
SR_PRIV const char *scpi_cmd_get(const struct scpi_command *cmdtable, int command);
|
||||
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi,
|
||||
const struct scpi_command *cmdtable, int command, ...);
|
||||
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi,
|
||||
const struct scpi_command *cmdtable,
|
||||
GVariant **gvar, const GVariantType *gvtype, int command, ...);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* This file is part of the libsigrok project.
|
||||
*
|
||||
* Copyright (C) 2015 Bert Vermeulen <bert@biot.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <strings.h>
|
||||
#include <libsigrok/libsigrok.h>
|
||||
#include "libsigrok-internal.h"
|
||||
#include "scpi.h"
|
||||
|
||||
#define LOG_PREFIX "scpi/helpers"
|
||||
|
||||
static const char *scpi_vendors[][2] = {
|
||||
{ "HEWLETT-PACKARD", "HP" },
|
||||
{ "Agilent Technologies", "Agilent" },
|
||||
{ "RIGOL TECHNOLOGIES", "Rigol" },
|
||||
{ "PHILIPS", "Philips" },
|
||||
{ "CHROMA", "Chroma" },
|
||||
{ "Chroma ATE", "Chroma" },
|
||||
};
|
||||
|
||||
SR_PRIV const char *sr_vendor_alias(const char *raw_vendor)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(scpi_vendors); i++) {
|
||||
if (!strcasecmp(raw_vendor, scpi_vendors[i][0]))
|
||||
return scpi_vendors[i][1];
|
||||
}
|
||||
|
||||
return raw_vendor;
|
||||
}
|
||||
|
||||
SR_PRIV const char *scpi_cmd_get(const struct scpi_command *cmdtable, int command)
|
||||
{
|
||||
unsigned int i;
|
||||
const char *cmd;
|
||||
|
||||
if (!cmdtable)
|
||||
return NULL;
|
||||
|
||||
cmd = NULL;
|
||||
for (i = 0; cmdtable[i].command; i++) {
|
||||
if (cmdtable[i].command == command) {
|
||||
cmd = cmdtable[i].string;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
SR_PRIV int scpi_cmd(const struct sr_dev_inst *sdi, const struct scpi_command *cmdtable,
|
||||
int command, ...)
|
||||
{
|
||||
struct sr_scpi_dev_inst *scpi;
|
||||
va_list args;
|
||||
int ret;
|
||||
const char *cmd;
|
||||
|
||||
if (!(cmd = scpi_cmd_get(cmdtable, command))) {
|
||||
/* Device does not implement this command, that's OK. */
|
||||
/* TODO: deprecate SR_OK_CONTINUE */
|
||||
return SR_OK_CONTINUE;
|
||||
}
|
||||
|
||||
scpi = sdi->conn;
|
||||
va_start(args, command);
|
||||
ret = sr_scpi_send_variadic(scpi, cmd, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SR_PRIV int scpi_cmd_resp(const struct sr_dev_inst *sdi, const struct scpi_command *cmdtable,
|
||||
GVariant **gvar, const GVariantType *gvtype, int command, ...)
|
||||
{
|
||||
struct sr_scpi_dev_inst *scpi;
|
||||
va_list args;
|
||||
double d;
|
||||
int ret;
|
||||
char *s;
|
||||
const char *cmd;
|
||||
|
||||
if (!(cmd = scpi_cmd_get(cmdtable, command))) {
|
||||
/* Device does not implement this command, that's OK. */
|
||||
return SR_OK_CONTINUE;
|
||||
}
|
||||
|
||||
scpi = sdi->conn;
|
||||
va_start(args, command);
|
||||
ret = sr_scpi_send_variadic(scpi, cmd, args);
|
||||
va_end(args);
|
||||
if (ret != SR_OK)
|
||||
return ret;
|
||||
|
||||
/* Straight SCPI getters to GVariant types. */
|
||||
if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_BOOLEAN)) {
|
||||
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) != SR_OK)
|
||||
return ret;
|
||||
if (!strcasecmp(s, "ON") || !strcasecmp(s, "1")
|
||||
|| !strcasecmp(s, "YES"))
|
||||
*gvar = g_variant_new_boolean(TRUE);
|
||||
else if (!strcasecmp(s, "OFF") || !strcasecmp(s, "0")
|
||||
|| !strcasecmp(s, "NO"))
|
||||
*gvar = g_variant_new_boolean(FALSE);
|
||||
else
|
||||
ret = SR_ERR;
|
||||
g_free(s);
|
||||
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_DOUBLE)) {
|
||||
if ((ret = sr_scpi_get_double(scpi, NULL, &d)) == SR_OK)
|
||||
*gvar = g_variant_new_double(d);
|
||||
} if (g_variant_type_equal(gvtype, G_VARIANT_TYPE_STRING)) {
|
||||
if ((ret = sr_scpi_get_string(scpi, NULL, &s)) == SR_OK)
|
||||
*gvar = g_variant_new_string(s);
|
||||
} else {
|
||||
sr_err("Unable to convert to desired GVariant type.");
|
||||
ret = SR_ERR_NA;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue