diff --git a/src/dmm/metex14.c b/src/dmm/metex14.c index 687df906..2d0a70d6 100644 --- a/src/dmm/metex14.c +++ b/src/dmm/metex14.c @@ -313,6 +313,25 @@ SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf) return TRUE; } +SR_PRIV gboolean sr_metex14_4packets_valid(const uint8_t *buf) +{ + struct metex14_info info; + size_t ch_idx; + const uint8_t *ch_buf; + + ch_buf = buf; + for (ch_idx = 0; ch_idx < 4; ch_idx++) { + if (ch_buf[13] != '\r') + return FALSE; + memset(&info, 0x00, sizeof(info)); + parse_flags((const char *)ch_buf, &info); + if (!flags_valid(&info)) + return FALSE; + ch_buf += METEX14_PACKET_SIZE; + } + return TRUE; +} + /** * Parse a protocol packet. * @@ -354,3 +373,34 @@ SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, return SR_OK; } + +/** + * Parse one out of four values of a four-display Metex14 variant. + * + * The caller's 'info' parameter can be used to track the channel index, + * as long as the information is kept across calls to the 14-byte packet + * parse routine (which clears the 'info' container). + * + * Since analog values have further details in the 'analog' parameter, + * passing multiple values per parse routine call is problematic. So we + * prefer the approach of passing one value per call, which is most + * reliable and shall fit every similar device with multiple displays. + * + * The meters which use this parse routine send one 14-byte packet per + * display. Each packet has the regular Metex14 layout. + */ +SR_PRIV int sr_metex14_4packets_parse(const uint8_t *buf, float *floatval, + struct sr_datafeed_analog *analog, void *info) +{ + struct metex14_info *info_local; + size_t ch_idx; + const uint8_t *ch_buf; + int rc; + + info_local = info; + ch_idx = info_local->ch_idx; + ch_buf = buf + ch_idx * METEX14_PACKET_SIZE; + rc = sr_metex14_parse(ch_buf, floatval, analog, info); + info_local->ch_idx = ch_idx + 1; + return rc; +} diff --git a/src/hardware/serial-dmm/api.c b/src/hardware/serial-dmm/api.c index eb453c78..2611aa6f 100644 --- a/src/hardware/serial-dmm/api.c +++ b/src/hardware/serial-dmm/api.c @@ -56,6 +56,8 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) int dropped, ret; size_t len; uint8_t buf[128]; + size_t ch_idx; + char ch_name[12]; dmm = (struct dmm_info *)di; @@ -131,7 +133,13 @@ static GSList *scan(struct sr_dev_driver *di, GSList *options) sdi->inst_type = SR_INST_SERIAL; sdi->conn = serial; sdi->priv = devc; - sr_channel_new(sdi, 0, SR_CHANNEL_ANALOG, TRUE, "P1"); + dmm->channel_count = 1; + if (dmm->packet_parse == sr_metex14_4packets_parse) + dmm->channel_count = 4; + for (ch_idx = 0; ch_idx < dmm->channel_count; ch_idx++) { + snprintf(ch_name, sizeof(ch_name), "P%zu", ch_idx); + sr_channel_new(sdi, ch_idx, SR_CHANNEL_ANALOG, TRUE, ch_name); + } devices = g_slist_append(devices, sdi); scan_cleanup: @@ -197,7 +205,7 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) .context = NULL, \ }, \ VENDOR, MODEL, CONN, BAUDRATE, PACKETSIZE, TIMEOUT, DELAY, \ - REQUEST, VALID, PARSE, DETAILS, sizeof(struct CHIPSET##_info) \ + REQUEST, 1, VALID, PARSE, DETAILS, sizeof(struct CHIPSET##_info) \ }).di SR_REGISTER_DEV_DRIVER_LIST(serial_dmm_drivers, @@ -440,8 +448,8 @@ SR_REGISTER_DEV_DRIVER_LIST(serial_dmm_drivers, DMM( "metex-m3860m", metex14, "Metex", "M-3860M", "9600/7n2/rts=0/dtr=1", 9600, - METEX14_PACKET_SIZE, 0, 0, sr_metex14_packet_request, - sr_metex14_packet_valid, sr_metex14_parse, + 4 * METEX14_PACKET_SIZE, 0, 0, sr_metex14_packet_request, + sr_metex14_4packets_valid, sr_metex14_4packets_parse, NULL ), DMM( @@ -475,8 +483,8 @@ SR_REGISTER_DEV_DRIVER_LIST(serial_dmm_drivers, DMM( "peaktech-4390a", metex14, "PeakTech", "4390A", "9600/7n2/rts=0/dtr=1", 9600, - METEX14_PACKET_SIZE, 0, 0, sr_metex14_packet_request, - sr_metex14_packet_valid, sr_metex14_parse, + 4 * METEX14_PACKET_SIZE, 0, 0, sr_metex14_packet_request, + sr_metex14_4packets_valid, sr_metex14_4packets_parse, NULL ), DMM( diff --git a/src/hardware/serial-dmm/protocol.c b/src/hardware/serial-dmm/protocol.c index 9d3bc916..e5f50ff7 100644 --- a/src/hardware/serial-dmm/protocol.c +++ b/src/hardware/serial-dmm/protocol.c @@ -49,31 +49,42 @@ static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi, struct sr_analog_meaning meaning; struct sr_analog_spec spec; struct dev_context *devc; + gboolean sent_sample; + size_t ch_idx; dmm = (struct dmm_info *)sdi->driver; log_dmm_packet(buf); devc = sdi->priv; - /* Note: digits/spec_digits will be overridden by the DMM parsers. */ - sr_analog_init(&analog, &encoding, &meaning, &spec, 0); + sent_sample = FALSE; + memset(info, 0, dmm->info_size); + for (ch_idx = 0; ch_idx < dmm->channel_count; ch_idx++) { + /* Note: digits/spec_digits will be overridden by the DMM parsers. */ + sr_analog_init(&analog, &encoding, &meaning, &spec, 0); - analog.meaning->channels = sdi->channels; - analog.num_samples = 1; - analog.meaning->mq = 0; + analog.meaning->channels = + g_slist_append(NULL, g_slist_nth_data(sdi->channels, ch_idx)); + analog.num_samples = 1; + analog.meaning->mq = 0; - dmm->packet_parse(buf, &floatval, &analog, info); - analog.data = &floatval; + dmm->packet_parse(buf, &floatval, &analog, info); + analog.data = &floatval; - /* If this DMM needs additional handling, call the resp. function. */ - if (dmm->dmm_details) - dmm->dmm_details(&analog, info); + /* If this DMM needs additional handling, call the resp. function. */ + if (dmm->dmm_details) + dmm->dmm_details(&analog, info); - if (analog.meaning->mq != 0) { - /* Got a measurement. */ - packet.type = SR_DF_ANALOG; - packet.payload = &analog; - sr_session_send(sdi, &packet); + if (analog.meaning->mq != 0) { + /* Got a measurement. */ + packet.type = SR_DF_ANALOG; + packet.payload = &analog; + sr_session_send(sdi, &packet); + sent_sample = TRUE; + } + } + + if (sent_sample) { sr_sw_limits_update_samples_read(&devc->limits, 1); } } diff --git a/src/hardware/serial-dmm/protocol.h b/src/hardware/serial-dmm/protocol.h index c80180ce..696f6b6e 100644 --- a/src/hardware/serial-dmm/protocol.h +++ b/src/hardware/serial-dmm/protocol.h @@ -47,6 +47,8 @@ struct dmm_info { int64_t req_delay_ms; /** Packet request function. */ int (*packet_request)(struct sr_serial_dev_inst *); + /** Number of channels / displays. */ + size_t channel_count; /** Packet validation function. */ gboolean (*packet_valid)(const uint8_t *); /** Packet parsing function. */ diff --git a/src/libsigrok-internal.h b/src/libsigrok-internal.h index 9fdd81da..98f224b4 100644 --- a/src/libsigrok-internal.h +++ b/src/libsigrok-internal.h @@ -1273,6 +1273,7 @@ SR_PRIV int sr_m2110_parse(const uint8_t *buf, float *floatval, #define METEX14_PACKET_SIZE 14 struct metex14_info { + size_t ch_idx; gboolean is_ac, is_dc, is_resistance, is_capacity, is_temperature; gboolean is_diode, is_frequency, is_ampere, is_volt, is_farad; gboolean is_hertz, is_ohm, is_celsius, is_pico, is_nano, is_micro; @@ -1286,6 +1287,9 @@ SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial); SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf); SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, struct sr_datafeed_analog *analog, void *info); +SR_PRIV gboolean sr_metex14_4packets_valid(const uint8_t *buf); +SR_PRIV int sr_metex14_4packets_parse(const uint8_t *buf, float *floatval, + struct sr_datafeed_analog *analog, void *info); /*--- hardware/dmm/rs9lcd.c -------------------------------------------------*/