/* Model ID, model name, max current/voltage/power, current/voltage digits. */
static const struct rdtech_dps_model supported_models[] = {
- { 3005, "DPS3005", 5, 30, 160, 3, 2 },
- { 5005, "DPS5005", 5, 50, 250, 3, 2 },
- { 5205, "DPH5005", 5, 50, 250, 3, 2 },
- { 5015, "DPS5015", 15, 50, 750, 2, 2 },
- { 5020, "DPS5020", 20, 50, 1000, 2, 2 },
- { 8005, "DPS8005", 5, 80, 408, 3, 2 },
+ { MODEL_DPS, 3005, "DPS3005", 5, 30, 160, 3, 2 },
+ { MODEL_DPS, 5005, "DPS5005", 5, 50, 250, 3, 2 },
+ { MODEL_DPS, 5205, "DPH5005", 5, 50, 250, 3, 2 },
+ { MODEL_DPS, 5015, "DPS5015", 15, 50, 750, 2, 2 },
+ { MODEL_DPS, 5020, "DPS5020", 20, 50, 1000, 2, 2 },
+ { MODEL_DPS, 8005, "DPS8005", 5, 80, 408, 3, 2 },
+ /* All RD specs taken from the 2020.12.2 instruction manual. */
+ { MODEL_RD , 6006, "RD6006" , 6, 60, 360, 3, 2 },
+ { MODEL_RD , 6012, "RD6012" , 12, 60, 720, 2, 2 },
+ { MODEL_RD , 6018, "RD6018" , 18, 60, 1080, 2, 2 },
};
static struct sr_dev_driver rdtech_dps_driver_info;
+static struct sr_dev_driver rdtech_rd_driver_info;
-static struct sr_dev_inst *probe_device(struct sr_modbus_dev_inst *modbus)
+static struct sr_dev_inst *probe_device(struct sr_modbus_dev_inst *modbus,
+ enum rdtech_dps_model_type model_type)
{
+ static const char *type_prefix[] = {
+ [MODEL_DPS] = "DPS",
+ [MODEL_RD] = "RD",
+ };
+
uint16_t id, version;
+ uint32_t serno;
int ret;
- const struct rdtech_dps_model *model;
+ const struct rdtech_dps_model *model, *supported;
size_t i;
struct sr_dev_inst *sdi;
struct dev_context *devc;
- ret = rdtech_dps_get_model_version(modbus, &id, &version);
+ ret = rdtech_dps_get_model_version(modbus,
+ model_type, &id, &version, &serno);
+ sr_dbg("probe: ret %d, type %s, model %u, vers %u, snr %u.",
+ ret, type_prefix[model_type], id, version, serno);
if (ret != SR_OK)
return NULL;
model = NULL;
for (i = 0; i < ARRAY_SIZE(supported_models); i++) {
- if (id == supported_models[i].id) {
- model = &supported_models[i];
- break;
- }
+ supported = &supported_models[i];
+ if (model_type != supported->model_type)
+ continue;
+ if (id != supported->id)
+ continue;
+ model = supported;
+ break;
}
if (!model) {
- sr_err("Unknown model: %u.", id);
+ sr_err("Unknown model: %s%u.", type_prefix[model_type], id);
return NULL;
}
sdi = g_malloc0(sizeof(*sdi));
sdi->status = SR_ST_INACTIVE;
sdi->vendor = g_strdup("RDTech");
- sdi->model = g_strdup(model->name);
- sdi->version = g_strdup_printf("v%u", version);
+ switch (model_type) {
+ case MODEL_DPS:
+ sdi->model = g_strdup(model->name);
+ sdi->version = g_strdup_printf("v%u", version);
+ sdi->driver = &rdtech_dps_driver_info;
+ break;
+ case MODEL_RD:
+ sdi->model = g_strdup(model->name);
+ sdi->version = g_strdup_printf("v%u.%u",
+ version / 100, version % 100);
+ if (serno)
+ sdi->serial_num = g_strdup_printf("%u", serno);
+ sdi->driver = &rdtech_rd_driver_info;
+ break;
+ default:
+ sr_err("Programming error, unhandled DPS/DPH/RD device type.");
+ g_free(sdi->vendor);
+ g_free(sdi);
+ return NULL;
+ }
sdi->conn = modbus;
- sdi->driver = &rdtech_dps_driver_info;
sdi->inst_type = SR_INST_MODBUS;
sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "V");
return sdi;
}
+static struct sr_dev_inst *probe_device_dps(struct sr_modbus_dev_inst *modbus)
+{
+ return probe_device(modbus, MODEL_DPS);
+}
+
+static struct sr_dev_inst *probe_device_rd(struct sr_modbus_dev_inst *modbus)
+{
+ return probe_device(modbus, MODEL_RD);
+}
+
static int config_compare(gconstpointer a, gconstpointer b)
{
const struct sr_config *ac = a, *bc = b;
return ac->key != bc->key;
}
-static GSList *scan(struct sr_dev_driver *di, GSList *options)
+static GSList *scan(struct sr_dev_driver *di, GSList *options,
+ enum rdtech_dps_model_type model_type)
{
+ static const char *default_serialcomm_dps = "9600/8n1";
+ static const char *default_serialcomm_rd = "115200/8n1";
+
struct sr_config default_serialcomm = {
.key = SR_CONF_SERIALCOMM,
- .data = g_variant_new_string("9600/8n1"),
+ .data = NULL,
};
struct sr_config default_modbusaddr = {
.key = SR_CONF_MODBUSADDR,
.data = g_variant_new_uint64(1),
};
GSList *opts, *devices;
+ const char *serialcomm;
+ struct sr_dev_inst *(*probe_func)(struct sr_modbus_dev_inst *modbus);
+
+ /* TODO See why di->context isn't available yet at this time. */
+ serialcomm = NULL;
+ probe_func = NULL;
+ if (di->context == &rdtech_dps_driver_info || model_type == MODEL_DPS) {
+ serialcomm = default_serialcomm_dps;
+ probe_func = probe_device_dps;
+ }
+ if (di->context == &rdtech_rd_driver_info || model_type == MODEL_RD) {
+ serialcomm = default_serialcomm_rd;
+ probe_func = probe_device_rd;
+ }
+ if (!probe_func)
+ return NULL;
+ if (serialcomm && *serialcomm)
+ default_serialcomm.data = g_variant_new_string(serialcomm);
opts = options;
if (!g_slist_find_custom(options, &default_serialcomm, config_compare))
if (!g_slist_find_custom(options, &default_modbusaddr, config_compare))
opts = g_slist_prepend(opts, &default_modbusaddr);
- devices = sr_modbus_scan(di->context, opts, probe_device);
+ devices = sr_modbus_scan(di->context, opts, probe_func);
while (opts != options)
opts = g_slist_delete_link(opts, opts);
return devices;
}
+static GSList *scan_dps(struct sr_dev_driver *di, GSList *options)
+{
+ return scan(di, options, MODEL_DPS);
+}
+
+static GSList *scan_rd(struct sr_dev_driver *di, GSList *options)
+{
+ return scan(di, options, MODEL_RD);
+}
+
static int dev_open(struct sr_dev_inst *sdi)
{
struct sr_modbus_dev_inst *modbus;
.api_version = 1,
.init = std_init,
.cleanup = std_cleanup,
- .scan = scan,
+ .scan = scan_dps,
.dev_list = std_dev_list,
.dev_clear = std_dev_clear,
.config_get = config_get,
.context = NULL,
};
SR_REGISTER_DEV_DRIVER(rdtech_dps_driver_info);
+
+static struct sr_dev_driver rdtech_rd_driver_info = {
+ .name = "rdtech-rd",
+ .longname = "RDTech RD series power supply",
+ .api_version = 1,
+ .init = std_init,
+ .cleanup = std_cleanup,
+ .scan = scan_rd,
+ .dev_list = std_dev_list,
+ .dev_clear = std_dev_clear,
+ .config_get = config_get,
+ .config_set = config_set,
+ .config_list = config_list,
+ .dev_open = dev_open,
+ .dev_close = dev_close,
+ .dev_acquisition_start = dev_acquisition_start,
+ .dev_acquisition_stop = dev_acquisition_stop,
+ .context = NULL,
+};
+SR_REGISTER_DEV_DRIVER(rdtech_rd_driver_info);
#include "protocol.h"
enum rdtech_dps_register {
- REG_USET = 0x00, /* Mirror of 0x50 */
- REG_ISET = 0x01, /* Mirror of 0x51 */
- REG_UOUT = 0x02,
- REG_IOUT = 0x03,
- REG_POWER = 0x04,
- REG_UIN = 0x05,
- REG_LOCK = 0x06,
- REG_PROTECT = 0x07,
- REG_CV_CC = 0x08,
- REG_ENABLE = 0x09,
- REG_BACKLIGHT = 0x0A, /* Mirror of 0x55 */
- REG_MODEL = 0x0B,
- REG_VERSION = 0x0C,
-
- REG_PRESET = 0x23, /* Loads a preset into preset 0. */
+ REG_DPS_USET = 0x00, /* Mirror of 0x50 */
+ REG_DPS_ISET = 0x01, /* Mirror of 0x51 */
+ REG_DPS_UOUT = 0x02,
+ REG_DPS_IOUT = 0x03,
+ REG_DPS_POWER = 0x04,
+ REG_DPS_UIN = 0x05,
+ REG_DPS_LOCK = 0x06,
+ REG_DPS_PROTECT = 0x07,
+ REG_DPS_CV_CC = 0x08,
+ REG_DPS_ENABLE = 0x09,
+ REG_DPS_BACKLIGHT = 0x0A, /* Mirror of 0x55 */
+ REG_DPS_MODEL = 0x0B,
+ REG_DPS_VERSION = 0x0C,
+
+ REG_DPS_PRESET = 0x23, /* Loads a preset into preset 0. */
/*
* Add (preset * 0x10) to each of the following, for preset 1-9.
* Preset 0 regs below are the active output settings.
*/
- PRE_USET = 0x50,
- PRE_ISET = 0x51,
- PRE_OVPSET = 0x52,
- PRE_OCPSET = 0x53,
- PRE_OPPSET = 0x54,
- PRE_BACKLIGHT = 0x55,
- PRE_DISABLE = 0x56, /* Disable output if 0 is copied here from a preset (1 is no change). */
- PRE_BOOT = 0x57, /* Enable output at boot if 1. */
+ PRE_DPS_USET = 0x50,
+ PRE_DPS_ISET = 0x51,
+ PRE_DPS_OVPSET = 0x52,
+ PRE_DPS_OCPSET = 0x53,
+ PRE_DPS_OPPSET = 0x54,
+ PRE_DPS_BACKLIGHT = 0x55,
+ PRE_DPS_DISABLE = 0x56, /* Disable output if 0 is copied here from a preset (1 is no change). */
+ PRE_DPS_BOOT = 0x57, /* Enable output at boot if 1. */
};
-#define REG_PRESET_STRIDE 0x10
+#define PRE_DPS_STRIDE 0x10
enum rdtech_dps_protect_state {
STATE_NORMAL = 0,
MODE_CC = 1,
};
+enum rdtech_rd_register {
+ REG_RD_MODEL = 0, /* u16 */
+ REG_RD_SERIAL = 1, /* u32 */
+ REG_RD_FIRMWARE = 3, /* u16 */
+ REG_RD_TEMP_INT = 4, /* 2x u16 */
+ REG_RD_TEMP_INT_F = 6, /* 2x u16 */
+ REG_RD_VOLT_TGT = 8, /* u16 */
+ REG_RD_CURR_LIM = 9, /* u16 */
+ REG_RD_VOLTAGE = 10, /* u16 */
+ REG_RD_CURRENT = 11, /* u16 */
+ REG_RD_ENERGY = 12, /* u16 */
+ REG_RD_POWER = 13, /* u16 */
+ REG_RD_VOLT_IN = 14, /* u16 */
+ REG_RD_PROTECT = 16, /* u16 */
+ REG_RD_REGULATION = 17, /* u16 */
+ REG_RD_ENABLE = 18, /* u16 */
+ /*
+ * Battery at 32 == 0x20 pp:
+ * Mode, voltage, temperature, capacity, energy.
+ */
+ /*
+ * Date/time at 48 == 0x30 pp:
+ * Year, month, day, hour, minute, second.
+ */
+ /* Backlight at 72 == 0x48. */
+ REG_RD_OVP_THR = 82, /* 0x52 */
+ REG_RD_OCP_THR = 83, /* 0x53 */
+ /* One "live" slot and 9 "memory" positions. */
+ REG_RD_START_MEM = 84, /* 0x54 */
+};
+
/* Retries failed modbus read attempts for improved reliability. */
static int rdtech_dps_read_holding_registers(struct sr_modbus_dev_inst *modbus,
int address, int nb_registers, uint16_t *registers)
return ret;
}
-/* Get one 16bit register. */
-static int rdtech_dps_get_reg(const struct sr_dev_inst *sdi,
- uint16_t address, uint16_t *value)
+/* Set one 16bit register. LE format for DPS devices. */
+static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
+ uint16_t address, uint16_t value)
{
struct dev_context *devc;
struct sr_modbus_dev_inst *modbus;
uint16_t registers[1];
int ret;
- const uint8_t *rdptr;
+ uint8_t *wrptr;
devc = sdi->priv;
modbus = sdi->conn;
+ wrptr = (void *)registers;
+ write_u16le(wrptr, value);
+
g_mutex_lock(&devc->rw_mutex);
- ret = rdtech_dps_read_holding_registers(modbus,
- address, ARRAY_SIZE(registers), registers);
+ ret = sr_modbus_write_multiple_registers(modbus, address,
+ ARRAY_SIZE(registers), registers);
g_mutex_unlock(&devc->rw_mutex);
- rdptr = (void *)registers;
- *value = read_u16le(rdptr);
-
return ret;
}
-/* Set one 16bit register. */
-static int rdtech_dps_set_reg(const struct sr_dev_inst *sdi,
+/* Set one 16bit register. BE format for RD devices. */
+static int rdtech_rd_set_reg(const struct sr_dev_inst *sdi,
uint16_t address, uint16_t value)
{
struct dev_context *devc;
modbus = sdi->conn;
wrptr = (void *)registers;
- write_u16le(wrptr, value);
+ write_u16be(wrptr, value);
g_mutex_lock(&devc->rw_mutex);
ret = sr_modbus_write_multiple_registers(modbus, address,
/* Get DPS model number and firmware version from a connected device. */
SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus,
- uint16_t *model, uint16_t *version)
+ enum rdtech_dps_model_type model_type,
+ uint16_t *model, uint16_t *version, uint32_t *serno)
{
- uint16_t registers[REG_VERSION + 1 - REG_MODEL];
+ uint16_t registers[4];
int ret;
const uint8_t *rdptr;
- /* Silence a compiler warning about an unused routine. */
- (void)rdtech_dps_get_reg;
-
/*
- * Get the MODEL and VERSION registers. No mutex here, because
- * there is no sr_dev_inst when this function is called.
+ * No mutex here because when the routine executes then the
+ * device instance was not created yet (probe phase).
*/
- ret = rdtech_dps_read_holding_registers(modbus,
- REG_MODEL, ARRAY_SIZE(registers), registers);
- if (ret != SR_OK)
- return ret;
-
- rdptr = (void *)registers;
- *model = read_u16le_inc(&rdptr);
- *version = read_u16le_inc(&rdptr);
- sr_info("RDTech DPS PSU model: %u version: %u", *model, *version);
-
- return ret;
+ switch (model_type) {
+ case MODEL_DPS:
+ /* Get the MODEL and VERSION registers. */
+ ret = rdtech_dps_read_holding_registers(modbus,
+ REG_DPS_MODEL, 2, registers);
+ if (ret != SR_OK)
+ return ret;
+ rdptr = (void *)registers;
+ *model = read_u16le_inc(&rdptr);
+ *version = read_u16le_inc(&rdptr);
+ *serno = 0;
+ sr_info("RDTech DPS/DPH model: %u version: %u",
+ *model, *version);
+ return SR_OK;
+ case MODEL_RD:
+ /* Get the MODEL, SERIAL, and FIRMWARE registers. */
+ ret = rdtech_dps_read_holding_registers(modbus,
+ REG_RD_MODEL, 4, registers);
+ if (ret != SR_OK)
+ return ret;
+ rdptr = (void *)registers;
+ *model = read_u16be_inc(&rdptr) / 10;
+ *serno = read_u32be_inc(&rdptr);
+ *version = read_u16be_inc(&rdptr);
+ sr_info("RDTech RD model: %u version: %u, serno %u",
+ *model, *version, *serno);
+ return SR_OK;
+ default:
+ sr_err("Unexpected RDTech PSU device type. Programming error?");
+ return SR_ERR_ARG;
+ }
+ /* UNREACH */
}
/* Send a measured value to the session feed. */
{
struct dev_context *devc;
struct sr_modbus_dev_inst *modbus;
- uint16_t registers[REG_ENABLE + 1 - REG_USET];
+ uint16_t registers[12];
int ret;
const uint8_t *rdptr;
uint16_t uset_raw, iset_raw, uout_raw, iout_raw, power_raw;
if (!state)
return SR_ERR_ARG;
- /* Transfer a chunk of registers in a single call. */
- g_mutex_lock(&devc->rw_mutex);
- ret = rdtech_dps_read_holding_registers(modbus,
- REG_USET, ARRAY_SIZE(registers), registers);
- g_mutex_unlock(&devc->rw_mutex);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ /*
+ * Transfer a chunk of registers in a single call. It's
+ * unfortunate that the model dependency and the sparse
+ * register map force us to open code addresses, sizes,
+ * and the sequence of the registers and how to interpret
+ * their bit fields. But then this is not too unusual for
+ * a hardware specific device driver ...
+ *
+ * TODO Optionally reduce the transfer volume depending
+ * on the caller specified state query context.
+ */
+ g_mutex_lock(&devc->rw_mutex);
+ ret = rdtech_dps_read_holding_registers(modbus,
+ REG_DPS_USET, 10, registers);
+ g_mutex_unlock(&devc->rw_mutex);
+ if (ret != SR_OK)
+ return ret;
- /* Interpret the registers' values. */
- rdptr = (const void *)registers;
- uset_raw = read_u16le_inc(&rdptr);
- volt_target = uset_raw / devc->voltage_multiplier;
- iset_raw = read_u16le_inc(&rdptr);
- curr_limit = iset_raw / devc->current_multiplier;
- uout_raw = read_u16le_inc(&rdptr);
- curr_voltage = uout_raw / devc->voltage_multiplier;
- iout_raw = read_u16le_inc(&rdptr);
- curr_current = iout_raw / devc->current_multiplier;
- power_raw = read_u16le_inc(&rdptr);
- curr_power = power_raw / 100.0f;
- (void)read_u16le_inc(&rdptr); /* UIN */
- reg_val = read_u16le_inc(&rdptr); /* LOCK */
- is_lock = reg_val != 0;
- reg_val = read_u16le_inc(&rdptr); /* PROTECT */
- uses_ovp = reg_val == STATE_OVP;
- uses_ocp = reg_val == STATE_OCP;
- reg_state = read_u16le_inc(&rdptr); /* CV_CC */
- is_reg_cc = reg_state == MODE_CC;
- out_state = read_u16le_inc(&rdptr); /* ENABLE */
- is_out_enabled = out_state != 0;
+ /* Interpret the registers' values. */
+ rdptr = (const void *)registers;
+ uset_raw = read_u16le_inc(&rdptr);
+ volt_target = uset_raw / devc->voltage_multiplier;
+ iset_raw = read_u16le_inc(&rdptr);
+ curr_limit = iset_raw / devc->current_multiplier;
+ uout_raw = read_u16le_inc(&rdptr);
+ curr_voltage = uout_raw / devc->voltage_multiplier;
+ iout_raw = read_u16le_inc(&rdptr);
+ curr_current = iout_raw / devc->current_multiplier;
+ power_raw = read_u16le_inc(&rdptr);
+ curr_power = power_raw / 100.0f;
+ (void)read_u16le_inc(&rdptr); /* UIN */
+ reg_val = read_u16le_inc(&rdptr); /* LOCK */
+ is_lock = reg_val != 0;
+ reg_val = read_u16le_inc(&rdptr); /* PROTECT */
+ uses_ovp = reg_val == STATE_OVP;
+ uses_ocp = reg_val == STATE_OCP;
+ reg_state = read_u16le_inc(&rdptr); /* CV_CC */
+ is_reg_cc = reg_state == MODE_CC;
+ out_state = read_u16le_inc(&rdptr); /* ENABLE */
+ is_out_enabled = out_state != 0;
+
+ /* Transfer another chunk of registers in a single call. */
+ g_mutex_lock(&devc->rw_mutex);
+ ret = rdtech_dps_read_holding_registers(modbus,
+ PRE_DPS_OVPSET, 2, registers);
+ g_mutex_unlock(&devc->rw_mutex);
+ if (ret != SR_OK)
+ return ret;
- /*
- * Transfer another chunk of registers in a single call.
- * TODO Unfortunately this call site open codes a fixed number
- * of registers to read. But there is already some leakage of
- * the register layout in this routine, and adding more device
- * types in the future will make things "worse". So accept it.
- */
- g_mutex_lock(&devc->rw_mutex);
- ret = rdtech_dps_read_holding_registers(modbus,
- PRE_OVPSET, 2, registers);
- g_mutex_unlock(&devc->rw_mutex);
- if (ret != SR_OK)
- return ret;
+ /* Interpret the second registers chunk's values. */
+ rdptr = (const void *)registers;
+ ovpset_raw = read_u16le_inc(&rdptr); /* PRE OVPSET */
+ ovp_threshold = ovpset_raw * devc->voltage_multiplier;
+ ocpset_raw = read_u16le_inc(&rdptr); /* PRE OCPSET */
+ ocp_threshold = ocpset_raw * devc->current_multiplier;
+
+ break;
+
+ case MODEL_RD:
+ /* Retrieve a set of adjacent registers. */
+ g_mutex_lock(&devc->rw_mutex);
+ ret = rdtech_dps_read_holding_registers(modbus,
+ REG_RD_VOLT_TGT, 11, registers);
+ g_mutex_unlock(&devc->rw_mutex);
+ if (ret != SR_OK)
+ return ret;
+
+ /* Interpret the registers' raw content. */
+ rdptr = (const void *)registers;
+ uset_raw = read_u16be_inc(&rdptr); /* USET */
+ volt_target = uset_raw / devc->voltage_multiplier;
+ iset_raw = read_u16be_inc(&rdptr); /* ISET */
+ curr_limit = iset_raw / devc->current_multiplier;
+ uout_raw = read_u16be_inc(&rdptr); /* UOUT */
+ curr_voltage = uout_raw / devc->voltage_multiplier;
+ iout_raw = read_u16be_inc(&rdptr); /* IOUT */
+ curr_current = iout_raw / devc->current_multiplier;
+ (void)read_u16be_inc(&rdptr); /* ENERGY */
+ power_raw = read_u16be_inc(&rdptr); /* POWER */
+ curr_power = power_raw / 100.0f;
+ (void)read_u16be_inc(&rdptr); /* VOLT_IN */
+ (void)read_u16be_inc(&rdptr);
+ reg_val = read_u16be_inc(&rdptr); /* PROTECT */
+ uses_ovp = reg_val == STATE_OVP;
+ uses_ocp = reg_val == STATE_OCP;
+ reg_state = read_u16be_inc(&rdptr); /* REGULATION */
+ is_reg_cc = reg_state == MODE_CC;
+ out_state = read_u16be_inc(&rdptr); /* ENABLE */
+ is_out_enabled = out_state != 0;
+
+ /* Retrieve a set of adjacent registers. */
+ g_mutex_lock(&devc->rw_mutex);
+ ret = rdtech_dps_read_holding_registers(modbus,
+ REG_RD_OVP_THR, 2, registers);
+ g_mutex_unlock(&devc->rw_mutex);
+ if (ret != SR_OK)
+ return ret;
+
+ /* Interpret the registers' raw content. */
+ rdptr = (const void *)registers;
+ ovpset_raw = read_u16be_inc(&rdptr); /* OVP THR */
+ ovp_threshold = ovpset_raw / devc->voltage_multiplier;
+ ocpset_raw = read_u16be_inc(&rdptr); /* OCP THR */
+ ocp_threshold = ocpset_raw / devc->current_multiplier;
- /* Interpret the registers' values. */
- rdptr = (const void *)registers;
- ovpset_raw = read_u16le_inc(&rdptr); /* PRE OVPSET */
- ovp_threshold = ovpset_raw * devc->voltage_multiplier;
- ocpset_raw = read_u16le_inc(&rdptr); /* PRE OCPSET */
- ocp_threshold = ocpset_raw * devc->current_multiplier;
+ /* Details which we cannot query from the device. */
+ is_lock = FALSE;
+
+ break;
+
+ default:
+ /* ShouldNotHappen(TM). Probe should have failed. */
+ return SR_ERR_ARG;
+ }
/* Store gathered details in the high level container. */
memset(state, 0, sizeof(*state));
/* Only a subset of known values is settable. */
if (state->mask & STATE_OUTPUT_ENABLED) {
reg_value = state->output_enabled ? 1 : 0;
- ret = rdtech_dps_set_reg(sdi, REG_ENABLE, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ ret = rdtech_dps_set_reg(sdi, REG_DPS_ENABLE, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ ret = rdtech_rd_set_reg(sdi, REG_RD_ENABLE, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
if (state->mask & STATE_VOLTAGE_TARGET) {
reg_value = state->voltage_target * devc->voltage_multiplier;
- ret = rdtech_dps_set_reg(sdi, REG_USET, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ ret = rdtech_dps_set_reg(sdi, REG_DPS_USET, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ ret = rdtech_rd_set_reg(sdi, REG_RD_VOLT_TGT, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
if (state->mask & STATE_CURRENT_LIMIT) {
reg_value = state->current_limit * devc->current_multiplier;
- ret = rdtech_dps_set_reg(sdi, REG_ISET, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ ret = rdtech_dps_set_reg(sdi, REG_DPS_ISET, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ ret = rdtech_rd_set_reg(sdi, REG_RD_CURR_LIM, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
if (state->mask & STATE_OVP_THRESHOLD) {
reg_value = state->ovp_threshold * devc->voltage_multiplier;
- ret = rdtech_dps_set_reg(sdi, PRE_OVPSET, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ ret = rdtech_dps_set_reg(sdi, PRE_DPS_OVPSET, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ ret = rdtech_rd_set_reg(sdi, REG_RD_OVP_THR, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
if (state->mask & STATE_OCP_THRESHOLD) {
reg_value = state->ocp_threshold * devc->current_multiplier;
- ret = rdtech_dps_set_reg(sdi, PRE_OCPSET, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ ret = rdtech_dps_set_reg(sdi, PRE_DPS_OCPSET, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ ret = rdtech_rd_set_reg(sdi, REG_RD_OCP_THR, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
if (state->mask & STATE_LOCK) {
- reg_value = state->lock ? 1 : 0;
- ret = rdtech_dps_set_reg(sdi, REG_LOCK, reg_value);
- if (ret != SR_OK)
- return ret;
+ switch (devc->model->model_type) {
+ case MODEL_DPS:
+ reg_value = state->lock ? 1 : 0;
+ ret = rdtech_dps_set_reg(sdi, REG_DPS_LOCK, reg_value);
+ if (ret != SR_OK)
+ return ret;
+ break;
+ case MODEL_RD:
+ /* Do nothing, _and_ silently succeed. */
+ break;
+ default:
+ return SR_ERR_ARG;
+ }
}
return SR_OK;