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.
*
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;
+}
int dropped, ret;
size_t len;
uint8_t buf[128];
+ size_t ch_idx;
+ char ch_name[12];
dmm = (struct dmm_info *)di;
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:
.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,
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(
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(
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);
-
- analog.meaning->channels = sdi->channels;
- analog.num_samples = 1;
- analog.meaning->mq = 0;
-
- 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);
+ 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 =
+ 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;
+
+ /* 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);
+ sent_sample = TRUE;
+ }
+ }
- if (analog.meaning->mq != 0) {
- /* Got a measurement. */
- packet.type = SR_DF_ANALOG;
- packet.payload = &analog;
- sr_session_send(sdi, &packet);
+ if (sent_sample) {
sr_sw_limits_update_samples_read(&devc->limits, 1);
}
}
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. */
#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;
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 -------------------------------------------------*/