From: Alexandru Gagniuc Date: Tue, 30 Oct 2012 04:42:10 +0000 (-0500) Subject: tekpower-dmm: Use generic fs9721 parser X-Git-Tag: dsupstream~606 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=be5c1d3b52a4c774bdd182ba54225a234d55336f;p=libsigrok.git tekpower-dmm: Use generic fs9721 parser Replace the parser with the fs9721 parser, which is just an adapted version of this parser. Signed-off-by: Alexandru Gagniuc --- diff --git a/hardware/tekpower-dmm/api.c b/hardware/tekpower-dmm/api.c index 2e449166..d9671100 100644 --- a/hardware/tekpower-dmm/api.c +++ b/hardware/tekpower-dmm/api.c @@ -95,7 +95,7 @@ static GSList *lcd14_scan(const char *conn, const char *serialcomm) struct drv_context *drvc; struct dev_context *devc; struct sr_probe *probe; - struct lcd14_packet *packet; + struct fs9721_packet *packet; GSList *devices; int i, len, fd, retry, good_packets = 0, dropped, ret; char buf[128], *b; @@ -128,29 +128,29 @@ static GSList *lcd14_scan(const char *conn, const char *serialcomm) /* Let's get a bit of data and see if we can find a packet. */ len = sizeof(buf); serial_readline(fd, &b, &len, 500); - if ((len == 0) || (len < LCD14_PACKET_SIZE)) { + if ((len == 0) || (len < FS9721_PACKET_SIZE)) { /* Not enough data received, is the DMM connected? */ continue; } /* Let's treat our buffer like a stream, and find any * valid packets */ - for (i = 0; i < len - LCD14_PACKET_SIZE + 1;) { + for (i = 0; i < len - FS9721_PACKET_SIZE + 1;) { packet = (void *)(&buf[i]); - if (!lcd14_is_packet_valid(packet, NULL)) { + if (!fs9721_is_packet_valid(packet, NULL)) { i++; continue; } good_packets++; - i += LCD14_PACKET_SIZE; + i += FS9721_PACKET_SIZE; } /* * If we dropped more than two packets worth of data, * something is wrong. */ - dropped = len - (good_packets * LCD14_PACKET_SIZE); - if (dropped > 2 * LCD14_PACKET_SIZE) + dropped = len - (good_packets * FS9721_PACKET_SIZE); + if (dropped > 2 * FS9721_PACKET_SIZE) continue; /* Let's see if we have anything good. */ diff --git a/hardware/tekpower-dmm/protocol.c b/hardware/tekpower-dmm/protocol.c index 7f501959..bb52e00c 100644 --- a/hardware/tekpower-dmm/protocol.c +++ b/hardware/tekpower-dmm/protocol.c @@ -26,199 +26,11 @@ #include "libsigrok-internal.h" #include "protocol.h" -static gboolean lcd14_is_sync_valid(const struct lcd14_packet *packet) -{ - int i; - uint8_t sync; - - /* Check the syncronization nibbles, and make sure they all match. */ - for (i = 0; i < LCD14_PACKET_SIZE; i++) { - sync = (packet->raw[i] & LCD14_SYNC_MASK) >> 4; - if (sync != (i + 1)) - return FALSE; - } - return TRUE; -} - -static gboolean lcd14_is_selection_good(const struct lcd14_data *data) -{ - int n_postfix = 0, n_type = 0; - - /* Does the packet have more than one multiplier? */ - if (data->flags & LCD14_NANO) - n_postfix++; - if (data->flags & LCD14_MICRO) - n_postfix++; - if (data->flags & LCD14_MILLI) - n_postfix++; - if (data->flags & LCD14_KILO) - n_postfix++; - if (data->flags & LCD14_MEGA) - n_postfix++; - - if (n_postfix > 1) - return FALSE; - - /* Does the packet "measure" more than one type of value? */ - if (data->flags & LCD14_HZ) - n_type++; - if (data->flags & LCD14_OHM) - n_type++; - if (data->flags & LCD14_FARAD) - n_type++; - if (data->flags & LCD14_AMP) - n_type++; - if (data->flags & LCD14_VOLT) - n_type++; - if (data->flags & LCD14_DUTY) - n_type++; - if (data->flags & LCD14_CELSIUS) - n_type++; - /* Do not test for hFE. hFE is not implemented and always '1'. */ - if (n_type > 1) - return FALSE; - - /* Both AC and DC? */ - if ((data->flags & LCD14_AC) && (data->flags & LCD14_DC)) - return FALSE; - - /* OK, no duplicates. */ - return TRUE; -} - -/* We "cook" a raw lcd14_pcaket into a more pallatable form, lcd14_data. */ -static void lcd14_cook_raw(const struct lcd14_packet *packet, - struct lcd14_data *data) -{ - int i, j; - - /* Get the digits out. */ - for (i = 0; i < 4; i++) { - j = (i << 1) + 1; - data->digit[i] = ((packet->raw[j] & ~LCD14_SYNC_MASK) << 4) | - ((packet->raw[j + 1] & ~LCD14_SYNC_MASK)); - } - - /* Now extract the flags. */ - data->flags = ((packet->raw[0] & ~LCD14_SYNC_MASK) << 20) | - ((packet->raw[9] & ~LCD14_SYNC_MASK) << 16) | - ((packet->raw[10] & ~LCD14_SYNC_MASK) << 12) | - ((packet->raw[11] & ~LCD14_SYNC_MASK) << 8) | - ((packet->raw[12] & ~LCD14_SYNC_MASK) << 4) | - ((packet->raw[13] & ~LCD14_SYNC_MASK)); -} - -/* - * Since the DMM does not identify itself in any way shape, or form, we really - * don't know for sure who is sending the data. We must use every possible - * check to filter out bad packets, especially since the detection mechanism - * depends on how well we can filter out bad packets packets. - */ -SR_PRIV gboolean lcd14_is_packet_valid(const struct lcd14_packet *packet, - struct lcd14_data *data) -{ - struct lcd14_data placeholder; - - /* Callers not interested in the data, pass NULL. */ - if (data == NULL) - data = &placeholder; - - if (!lcd14_is_sync_valid(packet)) - return FALSE; - - lcd14_cook_raw(packet, data); - - if (!lcd14_is_selection_good(data)) - return FALSE; - - /* If we made it here, this looks to be a valid packet. */ - return TRUE; -} - -static uint8_t lcd14_to_digit(uint8_t raw_digit) -{ - /* Take out the decimal point, so we can use a simple switch(). */ - raw_digit &= ~LCD14_DP_MASK; - - switch (raw_digit) { - case 0x00: - case LCD14_LCD_0: - return 0; - case LCD14_LCD_1: - return 1; - case LCD14_LCD_2: - return 2; - case LCD14_LCD_3: - return 3; - case LCD14_LCD_4: - return 4; - case LCD14_LCD_5: - return 5; - case LCD14_LCD_6: - return 6; - case LCD14_LCD_7: - return 7; - case LCD14_LCD_8: - return 8; - case LCD14_LCD_9: - return 9; - default: - return LCD14_LCD_INVALID; - } -} - -/* Get a raw floating point value from the data. */ -static double lcdraw_to_double(struct lcd14_data *data) -{ - double rawval; - double multiplier = 1; - uint8_t digit, raw_digit; - gboolean dp_reached = FALSE; - int i; - - /* We have 4 digits, and we start from the most significant. */ - for (i = 0; i < 4; i++) { - raw_digit = data->digit[i]; - digit = lcd14_to_digit(raw_digit); - if (digit == LCD14_LCD_INVALID) { - rawval = NAN; - break; - } - - /* - * Digit 1 does not have a decimal point. Instead, the decimal - * point is used to indicate MAX, so we must avoid testing it. - */ - if ((i > 0) && (raw_digit & LCD14_DP_MASK)) - dp_reached = TRUE; - if (dp_reached) - multiplier /= 10; - rawval = rawval * 10 + digit; - } - rawval *= multiplier; - if (data->digit[0] & LCD14_D0_NEG) - rawval *= -1; - - /* See if we need to multiply our raw value by anything. */ - if (data->flags & LCD14_NANO) - rawval *= 1E-9; - else if (data->flags & LCD14_MICRO) - rawval *= 1E-6; - else if (data->flags & LCD14_MILLI) - rawval *= 1E-3; - else if (data->flags & LCD14_KILO) - rawval *= 1E3; - else if (data->flags & LCD14_MEGA) - rawval *= 1E6; - - return rawval; -} - /* Now see what the value means, and pass that on. */ -static void lcd14_handle_packet(struct lcd14_data *data, - struct dev_context *devc) +static void fs9721_serial_handle_packet(const struct fs9721_data *data, + struct dev_context *devc) { - double rawval; + float rawval; struct sr_datafeed_packet packet; struct sr_datafeed_analog *analog; @@ -233,74 +45,21 @@ static void lcd14_handle_packet(struct lcd14_data *data, return; } - rawval = lcdraw_to_double(data); - analog->num_samples = 1; - *analog->data = (float)rawval; - analog->mq = -1; - /* What does the data mean? */ - if (data->flags & LCD14_VOLT) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - if (data->flags & LCD14_AC) - analog->mqflags |= SR_MQFLAG_AC; - else - analog->mqflags |= SR_MQFLAG_DC; - } else if (data->flags & LCD14_AMP) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - if (data->flags & LCD14_AC) - analog->mqflags |= SR_MQFLAG_AC; - else - analog->mqflags |= SR_MQFLAG_DC; - } else if (data->flags & LCD14_OHM) { - if (data->flags & LCD14_BEEP) - analog->mq = SR_MQ_CONTINUITY; - else - analog->mq = SR_MQ_RESISTANCE; - if (!isnan(rawval)) - analog->unit = SR_UNIT_OHM; - else { - analog->unit = SR_UNIT_BOOLEAN; - *analog->data = FALSE; - } - } else if (data->flags & LCD14_FARAD) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } else if (data->flags & LCD14_CELSIUS) { + sr_dmm_smart_parse_fs9721(data, &rawval, analog); + *analog->data = rawval; + + if (data->flags & FLAG_TEMP_CELSIUS) { analog->mq = SR_MQ_TEMPERATURE; /* No Kelvin or Fahrenheit from the device, just Celsius. */ analog->unit = SR_UNIT_CELSIUS; - } else if (data->flags & LCD14_HZ) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } else if (data->flags & LCD14_DUTY) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } else if (data->flags & LCD14_HFE) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - } else if (data->flags & LCD14_DIODE) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; - } else { - sr_warn("Unable to identify measurement mode."); } - /* What other flags are associated with the data? */ - if (data->flags & LCD14_HOLD) - analog->mqflags |= SR_MQFLAG_HOLD; - if (data->flags & LCD14_AUTO) - analog->mqflags |= SR_MQFLAG_AUTORANGE; - if (data->flags & LCD14_REL) - analog->mqflags |= SR_MQFLAG_RELATIVE; if (analog->mq != -1) { /* Got a measurement. */ - sr_spew("Measurement value is %f.", rawval); packet.type = SR_DF_ANALOG; packet.payload = analog; sr_session_send(devc->cb_data, &packet); @@ -314,8 +73,8 @@ static void lcd14_handle_packet(struct lcd14_data *data, static void handle_new_data(struct dev_context *devc, int fd) { int len, i, offset = 0; - struct lcd14_packet *packet; - struct lcd14_data data; + struct fs9721_packet *packet; + struct fs9721_data data; /* Try to get as much data as the buffer can hold. */ len = DMM_BUFSIZE - devc->buflen; @@ -327,11 +86,11 @@ static void handle_new_data(struct dev_context *devc, int fd) devc->buflen += len; /* Now look for packets in that data. */ - while ((devc->buflen - offset) >= LCD14_PACKET_SIZE) { + while ((devc->buflen - offset) >= FS9721_PACKET_SIZE) { packet = (void *)(devc->buf + offset); - if (lcd14_is_packet_valid(packet, &data)) { - lcd14_handle_packet(&data, devc); - offset += LCD14_PACKET_SIZE; + if (fs9721_is_packet_valid(packet, &data)) { + fs9721_serial_handle_packet(&data, devc); + offset += FS9721_PACKET_SIZE; } else { offset++; } diff --git a/hardware/tekpower-dmm/protocol.h b/hardware/tekpower-dmm/protocol.h index 7a66e019..e4c7cbd4 100644 --- a/hardware/tekpower-dmm/protocol.h +++ b/hardware/tekpower-dmm/protocol.h @@ -20,6 +20,8 @@ #ifndef LIBSIGROK_HARDWARE_TEKPOWER_DMM_PROTOCOL_H #define LIBSIGROK_HARDWARE_TEKPOWER_DMM_PROTOCOL_H +#include "hardware/common/dmm/fs9721.h" + /* Message logging helpers with driver-specific prefix string. */ #define DRIVER_LOG_DOMAIN "tekpower-dmm: " #define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) @@ -31,65 +33,7 @@ #define DMM_BUFSIZE 256 -/* Flags present in the packet */ -#define LCD14_AC (1 << 23) -#define LCD14_DC (1 << 22) -#define LCD14_AUTO (1 << 21) -#define LCD14_RS232 (1 << 20) -#define LCD14_MICRO (1 << 19) -#define LCD14_NANO (1 << 18) -#define LCD14_KILO (1 << 17) -#define LCD14_DIODE (1 << 16) -#define LCD14_MILLI (1 << 15) -#define LCD14_DUTY (1 << 14) -#define LCD14_MEGA (1 << 13) -#define LCD14_BEEP (1 << 12) -#define LCD14_FARAD (1 << 11) -#define LCD14_OHM (1 << 10) -#define LCD14_REL (1 << 9) -#define LCD14_HOLD (1 << 8) -#define LCD14_AMP (1 << 7) -#define LCD14_VOLT (1 << 6) -#define LCD14_HZ (1 << 5) -#define LCD14_LOW_BATT (1 << 4) -#define LCD14_HFE (1 << 3) -#define LCD14_CELSIUS (1 << 2) -#define LCD14_RSVD1 (1 << 1) -#define LCD14_RSVD0 (0 << 0) - -/* Mask used to remove the decimal point from a digit. */ -#define LCD14_DP_MASK 0x80 -#define LCD14_D0_NEG LCD14_DP_MASK -/* Mask used to remove the syncronization nibble. */ -#define LCD14_SYNC_MASK 0xf0 - -/* What the LCD values represent */ -#define LCD14_LCD_0 0x7d -#define LCD14_LCD_1 0x05 -#define LCD14_LCD_2 0x5b -#define LCD14_LCD_3 0x1f -#define LCD14_LCD_4 0x27 -#define LCD14_LCD_5 0x3e -#define LCD14_LCD_6 0x7e -#define LCD14_LCD_7 0x15 -#define LCD14_LCD_8 0x7f -#define LCD14_LCD_9 0x3f - -#define LCD14_LCD_INVALID 0xff - -#define LCD14_PACKET_SIZE 14 - -struct lcd14_packet { - uint8_t raw[LCD14_PACKET_SIZE]; -}; - -struct lcd14_data { - uint8_t digit[4]; - uint32_t flags; -}; - -SR_PRIV gboolean lcd14_is_packet_valid(const struct lcd14_packet *packet, - struct lcd14_data *data); +#define FLAG_TEMP_CELSIUS FS9721_USR2 /** Private, per-device-instance driver context. */ struct dev_context {