Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 134 additions & 18 deletions src/hardware/rdtech-dps/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

#include <config.h>

#include <math.h>
#include <string.h>

#include "protocol.h"
Expand Down Expand Up @@ -52,18 +51,94 @@ static const uint32_t devopts[] = {
SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
};

/* Model ID, model name, max current/voltage/power, current/voltage digits. */
static const uint32_t devopts_w_range[] = {
SR_CONF_CONTINUOUS,
SR_CONF_LIMIT_SAMPLES | SR_CONF_GET | SR_CONF_SET,
SR_CONF_LIMIT_MSEC | SR_CONF_GET | SR_CONF_SET,
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,
SR_CONF_REGULATION | SR_CONF_GET,
SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE | SR_CONF_GET,
SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE | SR_CONF_GET,
SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD | SR_CONF_GET | SR_CONF_SET,
SR_CONF_RANGE | SR_CONF_GET | SR_CONF_SET | SR_CONF_LIST,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd create a new devopts array, e.g. devopts_rd6012p or devopts_w_range only for this model (and other models with multiple ranges in the future), because the other existing models don't have this feature and therefore shouldn't expose it via the api.

But maybe that's something to discuss on IRC, to get an opinion of other devs.

};

/* range name, max current/voltage/power, current/voltage digits */
static struct rdtech_dps_range ranges_dps3005[] = {
{ "5A", 5, 30, 160, 3, 2 }
};

static struct rdtech_dps_range ranges_dps5005[] = {
{ "5A", 5, 50, 250, 3, 2 }
};

static struct rdtech_dps_range ranges_dps5015[] = {
{ "15A", 15, 50, 750, 2, 2 }
};

static struct rdtech_dps_range ranges_dps5020[] = {
{ "20A", 20, 50, 1000, 2, 2 }
};

static struct rdtech_dps_range ranges_dps8005[] = {
{ "5A", 5, 80, 408, 3, 2 }
};

static struct rdtech_dps_range ranges_rd6006[] = {
{ "6A", 6, 60, 360, 3, 2 }
};

static struct rdtech_dps_range ranges_rd6006p[] = {
{ "6A", 6, 60, 360, 4, 3 }
};

static struct rdtech_dps_range ranges_rd6012[] = {
{ "12A", 12, 60, 720, 2, 2 }
};

/*
* Current digits for RD6012P is 4 for the 6A range (RTU reg 20 = 0) and
* 3 for the 12A range (RTU reg 20 = 1)
*/
static struct rdtech_dps_range ranges_rd6012p[] = {
{ "6A", 6, 60, 360, 4, 3 },
{ "12A", 12, 60, 720, 3, 3 }
};

static struct rdtech_dps_range ranges_rd6018[] = {
{ "18A", 18, 60, 1080, 2, 2 }
};

static struct rdtech_dps_range ranges_rd6024[] = {
{ "24A", 24, 60, 1440, 2, 2 }
};

/* model ID, model name, range */
static const struct rdtech_dps_model supported_models[] = {
{ 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 },
{ MODEL_DPS, 3005, "DPS3005", ARRAY_AND_SIZE(ranges_dps3005) },
{ MODEL_DPS, 5005, "DPS5005", ARRAY_AND_SIZE(ranges_dps5005) },
{ MODEL_DPS, 5205, "DPH5005", ARRAY_AND_SIZE(ranges_dps5005) },
{ MODEL_DPS, 5015, "DPS5015", ARRAY_AND_SIZE(ranges_dps5015) },
{ MODEL_DPS, 5020, "DPS5020", ARRAY_AND_SIZE(ranges_dps5020) },
{ MODEL_DPS, 8005, "DPS8005", ARRAY_AND_SIZE(ranges_dps8005) },
/*
* Specs for models RD60nn taken from the 2020.12.2 instruction manual,
* specs for RD6006P from the 2021.2.26 (english) manual,
* specs for RD6012P from the 2021.10.26 (english) manual,
* and specs for RD6024P from the 2021.1.7 (english) manual.
*/
{ MODEL_RD, 60061, "RD6006" , ARRAY_AND_SIZE(ranges_rd6006) },
{ MODEL_RD, 60062, "RD6006" , ARRAY_AND_SIZE(ranges_rd6006) },
{ MODEL_RD, 60065, "RD6006P", ARRAY_AND_SIZE(ranges_rd6006p) },
{ MODEL_RD, 60121, "RD6012" , ARRAY_AND_SIZE(ranges_rd6012) },
{ MODEL_RD, 60125, "RD6012P", ARRAY_AND_SIZE(ranges_rd6012p) },
{ MODEL_RD, 60181, "RD6018" , ARRAY_AND_SIZE(ranges_rd6018) },
{ MODEL_RD, 60241, "RD6024" , ARRAY_AND_SIZE(ranges_rd6024) },
};

static struct sr_dev_driver rdtech_dps_driver_info;
Expand Down Expand Up @@ -139,10 +214,10 @@ static struct sr_dev_inst *probe_device(struct sr_modbus_dev_inst *modbus,
devc = g_malloc0(sizeof(*devc));
sr_sw_limits_init(&devc->limits);
devc->model = model;
devc->current_multiplier = pow(10.0, model->current_digits);
devc->voltage_multiplier = pow(10.0, model->voltage_digits);

sdi->priv = devc;
ret = rdtech_dps_update_range(sdi);
if (ret != SR_OK)
return NULL;

return sdi;
}
Expand Down Expand Up @@ -375,6 +450,15 @@ static int config_get(uint32_t key, GVariant **data,
return SR_ERR_DATA;
*data = g_variant_new_double(state.ocp_threshold);
break;
case SR_CONF_RANGE:
ret = rdtech_dps_get_state(sdi, &state, ST_CTX_CONFIG);
if (ret != SR_OK)
return ret;
if (!(state.mask & STATE_RANGE))
return SR_ERR_DATA;
*data = g_variant_new_string(
devc->model->ranges[state.range].range_str);
break;
default:
return SR_ERR_NA;
}
Expand All @@ -387,6 +471,8 @@ static int config_set(uint32_t key, GVariant *data,
{
struct dev_context *devc;
struct rdtech_dps_state state;
const char *range_str;
size_t i;

(void)cg;

Expand Down Expand Up @@ -417,6 +503,17 @@ static int config_set(uint32_t key, GVariant *data,
state.ocp_threshold = g_variant_get_double(data);
state.mask |= STATE_OCP_THRESHOLD;
return rdtech_dps_set_state(sdi, &state);
case SR_CONF_RANGE:
range_str = g_variant_get_string(data, NULL);
for (i = 0; i < devc->model->n_ranges; ++i) {
if (g_strcmp0(devc->model->ranges[i].range_str, range_str)
== 0) {
state.range = i;
state.mask |= STATE_RANGE;
return rdtech_dps_set_state(sdi, &state);
}
}
return SR_ERR_NA;
default:
return SR_ERR_NA;
}
Expand All @@ -428,21 +525,40 @@ static int config_list(uint32_t key, GVariant **data,
const struct sr_dev_inst *sdi, const struct sr_channel_group *cg)
{
struct dev_context *devc;
struct rdtech_dps_range *range;
GVariantBuilder gvb;
size_t i;

devc = (sdi) ? sdi->priv : NULL;

switch (key) {
case SR_CONF_SCAN_OPTIONS:
case SR_CONF_DEVICE_OPTIONS:
return STD_CONFIG_LIST(key, data, sdi, cg, scanopts, drvopts, devopts);
if (devc->model->n_ranges > 1)
return STD_CONFIG_LIST(key, data, sdi, cg, scanopts,
drvopts, devopts_w_range);
else
return STD_CONFIG_LIST(key, data, sdi, cg, scanopts,
drvopts, devopts);
case SR_CONF_VOLTAGE_TARGET:
*data = std_gvar_min_max_step(0.0, devc->model->max_voltage,
rdtech_dps_update_range(sdi);
range = &devc->model->ranges[devc->curr_range];
*data = std_gvar_min_max_step(0.0, range->max_voltage,
1 / devc->voltage_multiplier);
break;
case SR_CONF_CURRENT_LIMIT:
*data = std_gvar_min_max_step(0.0, devc->model->max_current,
rdtech_dps_update_range(sdi);
range = &devc->model->ranges[devc->curr_range];
*data = std_gvar_min_max_step(0.0, range->max_current,
1 / devc->current_multiplier);
break;
case SR_CONF_RANGE:
g_variant_builder_init(&gvb, G_VARIANT_TYPE_ARRAY);
for (i = 0; i < devc->model->n_ranges; ++i)
g_variant_builder_add(&gvb, "s",
devc->model->ranges[i].range_str);
*data = g_variant_builder_end(&gvb);
break;
default:
return SR_ERR_NA;
}
Expand Down
Loading