X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fmaynuo-m97%2Fprotocol.c;h=3a4c2d4631473ce4692e774232257dcdb37a8107;hb=0dc27cd1dbc961366d14607526e54992078e9d5c;hp=e6bc0294f393a5b927d28feb2a2a61b66a98d9f5;hpb=e1ccfb191062d13b98bb7536d162a044e0758678;p=libsigrok.git diff --git a/src/hardware/maynuo-m97/protocol.c b/src/hardware/maynuo-m97/protocol.c index e6bc0294..3a4c2d46 100644 --- a/src/hardware/maynuo-m97/protocol.c +++ b/src/hardware/maynuo-m97/protocol.c @@ -17,24 +17,186 @@ * along with this program. If not, see . */ +#include #include "protocol.h" +SR_PRIV int maynuo_m97_get_bit(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_coil address, int *value) +{ + uint8_t coil; + int ret = sr_modbus_read_coils(modbus, address, 1, &coil); + *value = coil & 1; + return ret; +} + +SR_PRIV int maynuo_m97_set_bit(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_coil address, int value) +{ + return sr_modbus_write_coil(modbus, address, value); +} + +SR_PRIV int maynuo_m97_get_float(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_register address, float *value) +{ + uint16_t registers[2]; + int ret = sr_modbus_read_holding_registers(modbus, address, 2, registers); + if (ret == SR_OK) + *value = RBFL(registers); + return ret; +} + +SR_PRIV int maynuo_m97_set_float(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_register address, float value) +{ + uint16_t registers[2]; + WBFL(registers, value); + return sr_modbus_write_multiple_registers(modbus, address, 2, registers); +} + + +static int maynuo_m97_cmd(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_mode cmd) +{ + uint16_t registers[1]; + WB16(registers, cmd); + return sr_modbus_write_multiple_registers(modbus, CMD, 1, registers); +} + +SR_PRIV int maynuo_m97_get_mode(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_mode *mode) +{ + uint16_t registers[1]; + int ret; + ret = sr_modbus_read_holding_registers(modbus, SETMODE, 1, registers); + *mode = RB16(registers) & 0xFF; + return ret; +} + +SR_PRIV int maynuo_m97_set_mode(struct sr_modbus_dev_inst *modbus, + enum maynuo_m97_mode mode) +{ + return maynuo_m97_cmd(modbus, mode); +} + +SR_PRIV int maynuo_m97_set_input(struct sr_modbus_dev_inst *modbus, int enable) +{ + enum maynuo_m97_mode mode; + int ret; + if ((ret = maynuo_m97_get_mode(modbus, &mode)) != SR_OK) + return ret; + if ((ret = maynuo_m97_cmd(modbus, enable ? INPUT_ON : INPUT_OFF)) != SR_OK) + return ret; + return maynuo_m97_set_mode(modbus, mode); +} + +SR_PRIV int maynuo_m97_get_model_version(struct sr_modbus_dev_inst *modbus, + uint16_t *model, uint16_t *version) +{ + uint16_t registers[2]; + int ret; + ret = sr_modbus_read_holding_registers(modbus, MODEL, 2, registers); + *model = RB16(registers + 0); + *version = RB16(registers + 1); + return ret; +} + + +SR_PRIV const char *maynuo_m97_mode_to_str(enum maynuo_m97_mode mode) +{ + switch (mode) { + case CC: return "CC"; + case CV: return "CV"; + case CW: return "CP"; + case CR: return "CR"; + case CC_SOFT_START: return "CC Soft Start"; + case DYNAMIC: return "Dynamic"; + case SHORT_CIRCUIT: return "Short Circuit"; + case LIST: return "List Mode"; + case CC_L_AND_UL: return "CC Loading and Unloading"; + case CV_L_AND_UL: return "CV Loading and Unloading"; + case CW_L_AND_UL: return "CP Loading and Unloading"; + case CR_L_AND_UL: return "CR Loading and Unloading"; + case CC_TO_CV: return "CC + CV"; + case CR_TO_CV: return "CR + CV"; + case BATTERY_TEST: return "Battery Test"; + case CV_SOFT_START: return "CV Soft Start"; + default: return "UNKNOWN"; + } +} + + +static void maynuo_m97_session_send_value(const struct sr_dev_inst *sdi, struct sr_channel *ch, float value, enum sr_mq mq, enum sr_unit unit, int digits) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_analog analog; + struct sr_analog_encoding encoding; + struct sr_analog_meaning meaning; + struct sr_analog_spec spec; + + sr_analog_init(&analog, &encoding, &meaning, &spec, digits); + analog.meaning->channels = g_slist_append(NULL, ch); + analog.num_samples = 1; + analog.data = &value; + analog.meaning->mq = mq; + analog.meaning->unit = unit; + analog.meaning->mqflags = SR_MQFLAG_DC; + + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + g_slist_free(analog.meaning->channels); +} + +SR_PRIV int maynuo_m97_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, U, 4, NULL)) == SR_OK) + devc->expecting_registers = 4; + return ret; +} + SR_PRIV int maynuo_m97_receive_data(int fd, int revents, void *cb_data) { - const struct sr_dev_inst *sdi; + struct sr_dev_inst *sdi; struct dev_context *devc; + struct sr_modbus_dev_inst *modbus; + uint16_t registers[4]; (void)fd; + (void)revents; if (!(sdi = cb_data)) return TRUE; - if (!(devc = sdi->priv)) - return TRUE; + modbus = sdi->conn; + devc = sdi->priv; + + devc->expecting_registers = 0; + if (sr_modbus_read_holding_registers(modbus, -1, 4, registers) == SR_OK) { + std_session_send_df_frame_begin(sdi); + + maynuo_m97_session_send_value(sdi, sdi->channels->data, + RBFL(registers + 0), + SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3); + maynuo_m97_session_send_value(sdi, sdi->channels->next->data, + RBFL(registers + 2), + SR_MQ_CURRENT, SR_UNIT_AMPERE, 4); - if (revents == G_IO_IN) { - /* TODO */ + std_session_send_df_frame_end(sdi); + sr_sw_limits_update_samples_read(&devc->limits, 1); + } + + if (sr_sw_limits_check(&devc->limits)) { + sr_dev_acquisition_stop(sdi); + return TRUE; } + maynuo_m97_capture_start(sdi); return TRUE; }