From: Frank Stettner Date: Tue, 9 Apr 2019 17:08:52 +0000 (+0200) Subject: rdtech-dps: Synchronize read and write operations. X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=7c0891b0b82049b4cc3c0dd70b8483d037dab36f;p=libsigrok.git rdtech-dps: Synchronize read and write operations. --- diff --git a/src/hardware/rdtech-dps/api.c b/src/hardware/rdtech-dps/api.c index e321ce36..ccea656e 100644 --- a/src/hardware/rdtech-dps/api.c +++ b/src/hardware/rdtech-dps/api.c @@ -2,6 +2,7 @@ * This file is part of the libsigrok project. * * Copyright (C) 2018 James Churchill + * Copyright (C) 2019 Frank Stettner * * 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 @@ -95,7 +96,6 @@ static struct sr_dev_inst *probe_device(struct sr_modbus_dev_inst *modbus) devc = g_malloc0(sizeof(struct dev_context)); sr_sw_limits_init(&devc->limits); devc->model = model; - devc->expecting_registers = 0; sdi->priv = devc; @@ -142,31 +142,20 @@ static int dev_open(struct sr_dev_inst *sdi) if (sr_modbus_open(modbus) < 0) return SR_ERR; - rdtech_dps_set_reg(modbus, REG_LOCK, 1); + rdtech_dps_set_reg(sdi, REG_LOCK, 1); return SR_OK; } static int dev_close(struct sr_dev_inst *sdi) { - struct dev_context *devc; struct sr_modbus_dev_inst *modbus; modbus = sdi->conn; - if (!modbus) return SR_ERR_BUG; - devc = sdi->priv; - - if (devc->expecting_registers) { - /* Wait for the last data that was requested from the device. */ - uint16_t registers[devc->expecting_registers]; - sr_modbus_read_holding_registers(modbus, -1, - devc->expecting_registers, registers); - } - - rdtech_dps_set_reg(modbus, REG_LOCK, 0); + rdtech_dps_set_reg(sdi, REG_LOCK, 0); return sr_modbus_close(modbus); } @@ -175,13 +164,11 @@ static int config_get(uint32_t key, GVariant **data, const struct sr_dev_inst *sdi, const struct sr_channel_group *cg) { struct dev_context *devc; - struct sr_modbus_dev_inst *modbus; int ret; uint16_t ivalue; (void)cg; - modbus = sdi->conn; devc = sdi->priv; ret = SR_OK; @@ -191,50 +178,50 @@ static int config_get(uint32_t key, GVariant **data, ret = sr_sw_limits_config_get(&devc->limits, key, data); break; case SR_CONF_ENABLED: - if ((ret = rdtech_dps_get_reg(modbus, REG_ENABLE, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_ENABLE, &ivalue)) == SR_OK) *data = g_variant_new_boolean(ivalue); break; case SR_CONF_REGULATION: - if ((ret = rdtech_dps_get_reg(modbus, REG_CV_CC, &ivalue)) != SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_CV_CC, &ivalue)) != SR_OK) break; *data = g_variant_new_string((ivalue == MODE_CC) ? "CC" : "CV"); break; case SR_CONF_VOLTAGE: - if ((ret = rdtech_dps_get_reg(modbus, REG_UOUT, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_UOUT, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 100.0f); break; case SR_CONF_VOLTAGE_TARGET: - if ((ret = rdtech_dps_get_reg(modbus, REG_USET, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_USET, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 100.0f); break; case SR_CONF_CURRENT: - if ((ret = rdtech_dps_get_reg(modbus, REG_IOUT, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_IOUT, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 100.0f); break; case SR_CONF_CURRENT_LIMIT: - if ((ret = rdtech_dps_get_reg(modbus, REG_ISET, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_ISET, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 1000.0f); break; case SR_CONF_OVER_VOLTAGE_PROTECTION_ENABLED: *data = g_variant_new_boolean(TRUE); break; case SR_CONF_OVER_VOLTAGE_PROTECTION_ACTIVE: - if ((ret = rdtech_dps_get_reg(modbus, REG_PROTECT, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_PROTECT, &ivalue)) == SR_OK) *data = g_variant_new_boolean(ivalue == STATE_OVP); break; case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD: - if ((ret = rdtech_dps_get_reg(modbus, PRE_OVPSET, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, PRE_OVPSET, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 100.0f); break; case SR_CONF_OVER_CURRENT_PROTECTION_ENABLED: *data = g_variant_new_boolean(TRUE); break; case SR_CONF_OVER_CURRENT_PROTECTION_ACTIVE: - if ((ret = rdtech_dps_get_reg(modbus, REG_PROTECT, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, REG_PROTECT, &ivalue)) == SR_OK) *data = g_variant_new_boolean(ivalue == STATE_OCP); break; case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD: - if ((ret = rdtech_dps_get_reg(modbus, PRE_OCPSET, &ivalue)) == SR_OK) + if ((ret = rdtech_dps_get_reg(sdi, PRE_OCPSET, &ivalue)) == SR_OK) *data = g_variant_new_double((float)ivalue / 1000.0f); break; default: @@ -248,11 +235,9 @@ 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; - struct sr_modbus_dev_inst *modbus; (void)cg; - modbus = sdi->conn; devc = sdi->priv; switch (key) { @@ -260,15 +245,15 @@ static int config_set(uint32_t key, GVariant *data, case SR_CONF_LIMIT_MSEC: return sr_sw_limits_config_set(&devc->limits, key, data); case SR_CONF_ENABLED: - return rdtech_dps_set_reg(modbus, REG_ENABLE, g_variant_get_boolean(data)); + return rdtech_dps_set_reg(sdi, REG_ENABLE, g_variant_get_boolean(data)); case SR_CONF_VOLTAGE_TARGET: - return rdtech_dps_set_reg(modbus, REG_USET, g_variant_get_double(data) * 100); + return rdtech_dps_set_reg(sdi, REG_USET, g_variant_get_double(data) * 100); case SR_CONF_CURRENT_LIMIT: - return rdtech_dps_set_reg(modbus, REG_ISET, g_variant_get_double(data) * 1000); + return rdtech_dps_set_reg(sdi, REG_ISET, g_variant_get_double(data) * 1000); case SR_CONF_OVER_VOLTAGE_PROTECTION_THRESHOLD: - return rdtech_dps_set_reg(modbus, PRE_OVPSET, g_variant_get_double(data) * 100); + return rdtech_dps_set_reg(sdi, PRE_OVPSET, g_variant_get_double(data) * 100); case SR_CONF_OVER_CURRENT_PROTECTION_THRESHOLD: - return rdtech_dps_set_reg(modbus, PRE_OCPSET, g_variant_get_double(data) * 1000); + return rdtech_dps_set_reg(sdi, PRE_OCPSET, g_variant_get_double(data) * 1000); default: return SR_ERR_NA; } @@ -316,7 +301,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) sr_sw_limits_acquisition_start(&devc->limits); std_session_send_df_header(sdi); - return rdtech_dps_capture_start(sdi); + return SR_OK; } static int dev_acquisition_stop(struct sr_dev_inst *sdi) diff --git a/src/hardware/rdtech-dps/protocol.c b/src/hardware/rdtech-dps/protocol.c index 4df1a701..f01e5742 100644 --- a/src/hardware/rdtech-dps/protocol.c +++ b/src/hardware/rdtech-dps/protocol.c @@ -2,6 +2,7 @@ * This file is part of the libsigrok project. * * Copyright (C) 2018 James Churchill + * Copyright (C) 2019 Frank Stettner * * 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 @@ -20,21 +21,40 @@ #include #include "protocol.h" -SR_PRIV int rdtech_dps_get_reg(struct sr_modbus_dev_inst *modbus, +SR_PRIV int rdtech_dps_get_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 = sr_modbus_read_holding_registers(modbus, address, 1, registers); + int ret; + + devc = sdi->priv; + modbus = sdi->conn; + + g_mutex_lock(&devc->rw_mutex); + ret = sr_modbus_read_holding_registers(modbus, address, 1, registers); + g_mutex_unlock(&devc->rw_mutex); *value = RB16(registers + 0); return ret; } -SR_PRIV int rdtech_dps_set_reg(struct sr_modbus_dev_inst *modbus, +SR_PRIV 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; + + devc = sdi->priv; + modbus = sdi->conn; + WB16(registers, value); - return sr_modbus_write_multiple_registers(modbus, address, 1, registers); + g_mutex_lock(&devc->rw_mutex); + ret = sr_modbus_write_multiple_registers(modbus, address, 1, registers); + g_mutex_unlock(&devc->rw_mutex); + return ret; } SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus, @@ -42,6 +62,11 @@ SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus, { uint16_t registers[2]; int ret; + + /* + * No mutex here, because there is no sr_dev_inst when this function + * is called. + */ ret = sr_modbus_read_holding_registers(modbus, REG_MODEL, 2, registers); if (ret == SR_OK) { *model = RB16(registers + 0); @@ -74,20 +99,6 @@ static void send_value(const struct sr_dev_inst *sdi, struct sr_channel *ch, g_slist_free(analog.meaning->channels); } -SR_PRIV int rdtech_dps_capture_start(const struct sr_dev_inst *sdi) -{ - struct dev_context *devc; - struct sr_modbus_dev_inst *modbus; - int ret; - - modbus = sdi->conn; - devc = sdi->priv; - - if ((ret = sr_modbus_read_holding_registers(modbus, REG_UOUT, 3, NULL)) == SR_OK) - devc->expecting_registers = 2; - return ret; -} - SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data) { struct sr_dev_inst *sdi; @@ -95,6 +106,7 @@ SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data) struct sr_modbus_dev_inst *modbus; struct sr_datafeed_packet packet; uint16_t registers[3]; + int ret; (void)fd; (void)revents; @@ -105,8 +117,11 @@ SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data) modbus = sdi->conn; devc = sdi->priv; - devc->expecting_registers = 0; - if (sr_modbus_read_holding_registers(modbus, -1, 3, registers) == SR_OK) { + g_mutex_lock(&devc->rw_mutex); + ret = sr_modbus_read_holding_registers(modbus, REG_UOUT, 3, registers); + g_mutex_unlock(&devc->rw_mutex); + + if (ret == SR_OK) { packet.type = SR_DF_FRAME_BEGIN; sr_session_send(sdi, &packet); @@ -130,6 +145,5 @@ SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data) return TRUE; } - rdtech_dps_capture_start(sdi); return TRUE; } diff --git a/src/hardware/rdtech-dps/protocol.h b/src/hardware/rdtech-dps/protocol.h index 3224e1b5..9e2b23f3 100644 --- a/src/hardware/rdtech-dps/protocol.h +++ b/src/hardware/rdtech-dps/protocol.h @@ -2,6 +2,7 @@ * This file is part of the libsigrok project. * * Copyright (C) 2018 James Churchill + * Copyright (C) 2019 Frank Stettner * * 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 @@ -38,7 +39,7 @@ struct rdtech_dps_model { struct dev_context { const struct rdtech_dps_model *model; struct sr_sw_limits limits; - int expecting_registers; + GMutex rw_mutex; }; enum rdtech_dps_register { @@ -84,13 +85,12 @@ enum rdtech_dps_mode { MODE_CC = 1, }; -SR_PRIV int rdtech_dps_get_reg(struct sr_modbus_dev_inst *modbus, uint16_t address, uint16_t *value); -SR_PRIV int rdtech_dps_set_reg(struct sr_modbus_dev_inst *modbus, uint16_t address, uint16_t value); +SR_PRIV int rdtech_dps_get_reg(const struct sr_dev_inst *sdi, uint16_t address, uint16_t *value); +SR_PRIV int rdtech_dps_set_reg(const struct sr_dev_inst *sdi, uint16_t address, uint16_t value); SR_PRIV int rdtech_dps_get_model_version(struct sr_modbus_dev_inst *modbus, uint16_t *model, uint16_t *version); -SR_PRIV int rdtech_dps_capture_start(const struct sr_dev_inst *sdi); SR_PRIV int rdtech_dps_receive_data(int fd, int revents, void *cb_data); #endif