X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=src%2Fhardware%2Fmaynuo-m97%2Fprotocol.c;h=5ef16ac730284da67562252df6ff85fa0930cc24;hb=ffb580cf732f060f167cbb3b910299395dd67aaa;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..5ef16ac7 100644 --- a/src/hardware/maynuo-m97/protocol.c +++ b/src/hardware/maynuo-m97/protocol.c @@ -19,22 +19,193 @@ #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) +{ + struct sr_datafeed_packet packet; + struct sr_datafeed_analog analog; + + analog.channels = g_slist_append(NULL, ch); + analog.num_samples = 1; + analog.data = &value; + analog.mq = mq; + analog.unit = unit; + analog.mqflags = SR_MQFLAG_DC; + + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + g_slist_free(analog.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; + struct sr_datafeed_packet packet; + uint16_t registers[4]; + int64_t t; (void)fd; + (void)revents; if (!(sdi = cb_data)) return TRUE; - if (!(devc = sdi->priv)) + modbus = sdi->conn; + devc = sdi->priv; + + devc->expecting_registers = 0; + if (sr_modbus_read_holding_registers(modbus, -1, 4, registers) == SR_OK) { + packet.type = SR_DF_FRAME_BEGIN; + sr_session_send(cb_data, &packet); + + maynuo_m97_session_send_value(sdi, sdi->channels->data, + RBFL(registers + 0), + SR_MQ_VOLTAGE, SR_UNIT_VOLT); + maynuo_m97_session_send_value(sdi, sdi->channels->next->data, + RBFL(registers + 2), + SR_MQ_CURRENT, SR_UNIT_AMPERE); + + packet.type = SR_DF_FRAME_END; + sr_session_send(cb_data, &packet); + devc->num_samples++; + } + + if (devc->limit_samples && (devc->num_samples >= devc->limit_samples)) { + sr_info("Requested number of samples reached."); + sdi->driver->dev_acquisition_stop(sdi, cb_data); return TRUE; + } - if (revents == G_IO_IN) { - /* TODO */ + if (devc->limit_msec) { + t = (g_get_monotonic_time() - devc->starttime) / 1000; + if (t > (int64_t)devc->limit_msec) { + sr_info("Requested time limit reached."); + sdi->driver->dev_acquisition_stop(sdi, cb_data); + return TRUE; + } } + maynuo_m97_capture_start(sdi); return TRUE; }