diff --git a/src/hardware/scpi-pps/profiles.c b/src/hardware/scpi-pps/profiles.c index 577aa41e9..731bf07fe 100644 --- a/src/hardware/scpi-pps/profiles.c +++ b/src/hardware/scpi-pps/profiles.c @@ -275,6 +275,197 @@ static int chroma_62000p_probe_channels(struct sr_dev_inst *sdi, return SR_OK; } +/* Elektro Automatik PS 20xx series */ +static const uint32_t ea_ps_20xx_devopts[] = { + SR_CONF_CONTINUOUS, + SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET, + SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET, +}; + +static const uint32_t ea_ps_20xx_devopts_cg[] = { + SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_VOLTAGE | SR_CONF_GET, + SR_CONF_VOLTAGE_TARGET | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_CURRENT | SR_CONF_GET, + SR_CONF_CURRENT_LIMIT | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST, + SR_CONF_ENABLED | SR_CONF_GET | SR_CONF_SET, +}; + +static const struct channel_group_spec ea_ps_20xx_cg[] = { + { "1", CH_IDX(0), PPS_OVP | PPS_OCP, SR_MQFLAG_DC }, +}; + +static int ea_ps_20xx_probe_channels(struct sr_dev_inst *sdi, + struct sr_scpi_hw_info *hw_info, + struct channel_spec **channels, unsigned int *num_channels, + struct channel_group_spec **channel_groups, + unsigned int *num_channel_groups) +{ + struct sr_scpi_dev_inst *scpi; + int ret; + float nom_volt, nom_curr, nom_pow; + char *response; + + scpi = sdi->conn; + /* Get nominal voltage */ + ret = sr_scpi_get_string(scpi, ":SYST:NOM:VOLT?", &response); + if (ret != SR_OK && !response) { + sr_err("Failed to get nominal voltage."); + return ret; + } + /* Remove unit */ + response[ret] = 0; + if (sr_atof_ascii(response, &nom_volt) != SR_OK) { + sr_err("Failed to convert nominal voltage from: '%s'", response); + return SR_ERR_DATA; + } + if (nom_volt < 0) { + sr_err("Suspicious nominal voltage %f, ignoring.", nom_volt); + return SR_ERR_DATA; + } + + /* Get nominal current */ + ret = sr_scpi_get_string(scpi, ":SYST:NOM:CURR?", &response); + if (ret != SR_OK && !response) { + sr_err("Failed to get nominal current."); + return ret; + } + /* Remove unit */ + response[ret] = 0; + if (sr_atof_ascii(response, &nom_curr) != SR_OK) { + sr_err("Failed to convert nominal current from: '%s'", response); + return SR_ERR_DATA; + } + if (nom_curr < 0) { + sr_err("Suspicious nominal current %f, ignoring.", nom_volt); + return SR_ERR_DATA; + } + + /* Get nominal power */ + ret = sr_scpi_get_string(scpi, ":SYST:NOM:POW?", &response); + if (ret != SR_OK && !response) { + sr_err("Failed to get nominal power."); + return ret; + } + /* Remove unit */ + response[ret] = 0; + if (sr_atof_ascii(response, &nom_pow) != SR_OK) { + sr_err("Failed to convert nominal power from: '%s'", response); + return SR_ERR_DATA; + } + if (nom_pow < 0) { + sr_err("Suspicious nominal power %f, ignoring.", nom_volt); + return SR_ERR_DATA; + } + + *channels = g_malloc0(sizeof(struct channel_spec)); + *channel_groups = g_malloc0(sizeof(struct channel_group_spec)); + **channel_groups = ea_ps_20xx_cg[0]; + *num_channel_groups = 1; + + (*channels)[0].name = "1"; + + (*channels)[0].current[0] = 0.0; + (*channels)[0].current[1] = nom_curr; + (*channels)[0].current[2] = 0.01; /* Programming resolution. */ + (*channels)[0].current[3] = 2; /* Spec digits. */ + (*channels)[0].current[4] = 2; /* Encoding digits. */ + + (*channels)[0].voltage[0] = 0.0; + (*channels)[0].voltage[1] = nom_volt; + (*channels)[0].voltage[2] = 0.01; /* Programming resolution. */ + (*channels)[0].voltage[3] = 2; /* Spec digits. */ + (*channels)[0].voltage[4] = 2; /* Encoding digits. */ + + (*channels)[0].power[0] = 0.0; + (*channels)[0].power[1] = nom_pow; + (*channels)[0].power[2] = 0; /* Programming resolution. */ + (*channels)[0].power[3] = 2; /* Spec digits. */ + (*channels)[0].power[4] = 2; /* Encoding digits. */ + *num_channels = 1; + + return SR_OK; +} + +static const struct scpi_command ea_ps_20xx_cmd[] = { + { SCPI_CMD_REMOTE, "SYST:LOCK 1" }, + { SCPI_CMD_LOCAL, "SYST:LOCK 0" }, + { SCPI_CMD_GET_MEAS_VOLTAGE, ":MEAS:VOLT?" }, + { SCPI_CMD_GET_MEAS_CURRENT, ":MEAS:CURR?" }, + { SCPI_CMD_GET_MEAS_POWER, ":MEAS:POW?" }, + { SCPI_CMD_GET_VOLTAGE_TARGET, ":VOLT?" }, + { SCPI_CMD_SET_VOLTAGE_TARGET, ":VOLT %.2f" }, + { SCPI_CMD_GET_CURRENT_LIMIT, ":CURR?" }, + { SCPI_CMD_SET_CURRENT_LIMIT, ":CURR %.2f" }, + { SCPI_CMD_GET_OUTPUT_ENABLED, ":OUTP?" }, + { SCPI_CMD_SET_OUTPUT_ENABLE, ":OUTP 1" }, + { SCPI_CMD_SET_OUTPUT_DISABLE, ":OUTP 0" }, + { SCPI_CMD_SET_OVER_VOLTAGE_PROTECTION_THRESHOLD, ":VOLT:PROT %.2f" }, + { SCPI_CMD_SET_OVER_CURRENT_PROTECTION_THRESHOLD, ":CURR:PROT %.2f" }, + ALL_ZERO +}; + +static int ea_ps_20xx_update_status(const struct sr_dev_inst *sdi) +{ + struct sr_scpi_dev_inst *scpi; + int ret; + int response; + gboolean cv, cc; + gboolean regulation_changed; + char *regulation; + + scpi = sdi->conn; + + ret = sr_scpi_get_int(scpi, "STAT:QUES?", &response); + if (ret != SR_OK) + return ret; + + /* OVP */ + if (response & (1 << 0)) + sr_session_send_meta(sdi, SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE, + g_variant_new_boolean(response & (1 << 0))); + + /* OCP */ + if (response & (1 << 1)) + sr_session_send_meta(sdi, SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE, + g_variant_new_boolean(response & (1 << 1))); + + /* OTP */ + if (response & (1 << 3)) + sr_session_send_meta(sdi, SR_CONF_OVER_TEMPERATURE_PROTECTION_ACTIVE, + g_variant_new_boolean(response & (1 << 3))); + + ret = sr_scpi_get_int(scpi, "STAT:OPER?", &response); + if (ret != SR_OK) + return ret; + + /* CV */ + cv = (response & (1 << 8)); + regulation_changed = (response & (1 << 8)); + /* CC */ + cc = (response & (1 << 9)); + regulation_changed = (response & (1 << 9)) | regulation_changed; + + if (regulation_changed) { + if (cv && !cc) + regulation = "CV"; + else if (cc && !cv) + regulation = "CC"; + else if (!cv && !cc) + regulation = ""; + else { + sr_dbg("Undefined regulation for EA PS 20xx " + "(CV=%i, CC=%i).", cv, cc); + return FALSE; + } + sr_session_send_meta(sdi, SR_CONF_REGULATION, + g_variant_new_string(regulation)); + } + + return SR_OK; +} + /* Envox EEZ PSU Series */ static const uint32_t eez_psu_devopts[] = { SR_CONF_CONTINUOUS, @@ -1570,6 +1761,18 @@ SR_PRIV const struct scpi_pps pps_profiles[] = { .update_status = NULL, }, + /* Elektro Automatik PS 20xx series*/ + { "EA Elektro-Automatik GmbH & Co. KG", "PS 20(42|84)-", SCPI_DIALECT_UNKNOWN, 0, + ARRAY_AND_SIZE(ea_ps_20xx_devopts), + ARRAY_AND_SIZE(ea_ps_20xx_devopts_cg), + NULL, 0, + NULL, 0, + ea_ps_20xx_cmd, + .probe_channels = ea_ps_20xx_probe_channels, + .init_acquisition = NULL, + .update_status = ea_ps_20xx_update_status, + }, + /* * Envox EEZ PSU Series * The documented identification strings disagree with the behavior