X-Git-Url: http://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Fcommon%2Fdmm%2Fmetex14.c;h=4e66c97c6ae77edb8820c5d0fd4b3e8ea94a200f;hb=3544f848e0d7f67af8e11ce7ec344b34cd797df3;hp=e6b9b98309c791b6e56b8ea12362b90b7aeeaad3;hpb=76b55dfa8a5318a0495d3f2cfb29d6cd229ce5dc;p=libsigrok.git diff --git a/hardware/common/dmm/metex14.c b/hardware/common/dmm/metex14.c index e6b9b983..4e66c97c 100644 --- a/hardware/common/dmm/metex14.c +++ b/hardware/common/dmm/metex14.c @@ -1,7 +1,7 @@ /* - * This file is part of the sigrok project. + * This file is part of the libsigrok project. * - * Copyright (C) 2012 Uwe Hermann + * Copyright (C) 2012-2013 Uwe Hermann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -34,89 +34,50 @@ #include "libsigrok.h" #include "libsigrok-internal.h" -/* Message logging helpers with driver-specific prefix string. */ -#define DRIVER_LOG_DOMAIN "metex14: " -#define sr_log(l, s, args...) sr_log(l, DRIVER_LOG_DOMAIN s, ## args) -#define sr_spew(s, args...) sr_spew(DRIVER_LOG_DOMAIN s, ## args) -#define sr_dbg(s, args...) sr_dbg(DRIVER_LOG_DOMAIN s, ## args) -#define sr_info(s, args...) sr_info(DRIVER_LOG_DOMAIN s, ## args) -#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args) -#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args) +#define LOG_PREFIX "metex14" static int parse_value(const uint8_t *buf, float *result) { - int i, sign, intval = 0, factor, decimal_point = 0, is_ol; - float floatval; - uint8_t digit; - - /* Byte 3: Sign (' ' or '-') */ - if (buf[3] == ' ') { - sign = 1; - } else if (buf[3] == '-') { - sign = -1; - } else { - sr_err("Invalid sign byte: 0x%02x.", buf[3]); - return SR_ERR; + int i, is_ol, cnt; + char valstr[7 + 1]; + + /* Strip all spaces from bytes 2-8. */ + memset(&valstr, 0, 7 + 1); + for (i = 0, cnt = 0; i < 7; i++) { + if (buf[2 + i] != ' ') + valstr[cnt++] = buf[2 + i]; } /* Bytes 5-7: Over limit (various forms) */ is_ol = 0; - is_ol += !strncmp((char *)&buf[5], ".OL", 3); - is_ol += !strncmp((char *)&buf[5], "O.L", 3); - is_ol += !strncmp((char *)&buf[5], "OL.", 3); - is_ol += !strncmp((char *)&buf[5], " OL", 3); + is_ol += (!strcasecmp((const char *)&valstr, ".OL")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "O.L")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "OL.")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "OL")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "-.OL")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "-O.L")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "-OL.")) ? 1 : 0; + is_ol += (!strcasecmp((const char *)&valstr, "-OL")) ? 1 : 0; if (is_ol != 0) { sr_spew("Over limit."); *result = INFINITY; return SR_OK; } - /* Bytes 4-8: Value (up to 4 digits) and decimal point */ - factor = 1000; - for (i = 0; i < 5; i++) { - digit = buf[4 + i]; - /* Convert spaces to '0', so that we can parse them. */ - if (digit == ' ') - digit = '0'; - if (digit == '.') { - decimal_point = i; - } else if (isdigit(digit)) { - intval += (digit - '0') * factor; - factor /= 10; - } else { - sr_err("Invalid digit byte: 0x%02x.", digit); - return SR_ERR; - } - } - - floatval = (float)intval; - - /* Decimal point position */ - if (decimal_point == 0 || decimal_point == 4) { - /* TODO: Doesn't happen? */ - } else if (decimal_point == 1) { - floatval /= 1000; - } else if (decimal_point == 2) { - floatval /= 100; - } else if (decimal_point == 3) { - floatval /= 10; - } else { - sr_err("Invalid decimal point position: %d.", decimal_point); - return SR_ERR; - } - - /* Apply sign. */ - floatval *= sign; + /* Bytes 2-8: Sign, value (up to 5 digits) and decimal point */ + sscanf((const char *)&valstr, "%f", result); - sr_spew("The display value is %f.", floatval); - - *result = floatval; + sr_spew("The display value is %f.", *result); return SR_OK; } static void parse_flags(const char *buf, struct metex14_info *info) { + int i, cnt; + char unit[4 + 1]; + const char *u; + /* Bytes 0-1: Measurement mode */ /* Note: Protocol doesn't distinguish "resistance" from "beep" mode. */ info->is_ac = !strncmp(buf, "AC", 2); @@ -126,37 +87,58 @@ static void parse_flags(const char *buf, struct metex14_info *info) info->is_temperature = !strncmp(buf, "TE", 2); info->is_diode = !strncmp(buf, "DI", 2); info->is_frequency = !strncmp(buf, "FR", 2); + info->is_gain = !strncmp(buf, "DB", 2); + info->is_hfe = !strncmp(buf, "HF", 2); + + /* + * Note: "DB" shows the logarithmic ratio of input voltage to a + * pre-stored (user-changeable) value in the DMM. + */ if (info->is_dc || info->is_ac) info->is_volt = TRUE; - /* Byte 2: Always space (0x20). */ + /* Bytes 2-8: See parse_value(). */ - /* Bytes 3-8: See parse_value(). */ + /* Strip all spaces from bytes 9-12. */ + memset(&unit, 0, 4 + 1); + for (i = 0, cnt = 0; i < 4; i++) { + if (buf[9 + i] != ' ') + unit[cnt++] = buf[9 + i]; + } /* Bytes 9-12: Unit */ - if (!strcmp(buf + 9, " A")) + u = (const char *)&unit; + if (!strcasecmp(u, "A")) info->is_ampere = TRUE; - else if (!strcmp(buf + 9, " mA")) + else if (!strcasecmp(u, "mA")) info->is_milli = info->is_ampere = TRUE; - else if (!strcmp(buf + 9, " V")) + else if (!strcasecmp(u, "uA")) + info->is_micro = info->is_ampere = TRUE; + else if (!strcasecmp(u, "V")) info->is_volt = TRUE; - else if (!strcmp(buf + 9, " mV")) + else if (!strcasecmp(u, "mV")) info->is_milli = info->is_volt = TRUE; - else if (!strcmp(buf + 9, " Ohm")) + else if (!strcasecmp(u, "Ohm")) info->is_ohm = TRUE; - else if (!strcmp(buf + 9, "KOhm")) + else if (!strcasecmp(u, "KOhm")) info->is_kilo = info->is_ohm = TRUE; - else if (!strcmp(buf + 9, "MOhm")) + else if (!strcasecmp(u, "MOhm")) info->is_mega = info->is_ohm = TRUE; - else if (!strcmp(buf + 9, " nF")) + else if (!strcasecmp(u, "pF")) + info->is_pico = info->is_farad = TRUE; + else if (!strcasecmp(u, "nF")) info->is_nano = info->is_farad = TRUE; - else if (!strcmp(buf + 9, " uF")) + else if (!strcasecmp(u, "uF")) info->is_micro = info->is_farad = TRUE; - else if (!strcmp(buf + 9, " KHz")) + else if (!strcasecmp(u, "KHz")) info->is_kilo = info->is_hertz = TRUE; - else if (!strcmp(buf + 9, " C")) + else if (!strcasecmp(u, "C")) info->is_celsius = TRUE; + else if (!strcasecmp(u, "DB")) + info->is_decibel = TRUE; + else if (!strcasecmp(u, "")) + info->is_unitless = TRUE; /* Byte 13: Always '\r' (carriage return, 0x0d, 13) */ } @@ -165,6 +147,8 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval, const struct metex14_info *info) { /* Factors */ + if (info->is_pico) + *floatval /= 1000000000000ULL; if (info->is_nano) *floatval /= 1000000000; if (info->is_micro) @@ -205,12 +189,22 @@ static void handle_flags(struct sr_datafeed_analog *analog, float *floatval, analog->mq = SR_MQ_VOLTAGE; analog->unit = SR_UNIT_VOLT; } + if (info->is_gain) { + analog->mq = SR_MQ_GAIN; + analog->unit = SR_UNIT_DECIBEL_VOLT; + } + if (info->is_hfe) { + analog->mq = SR_MQ_GAIN; + analog->unit = SR_UNIT_UNITLESS; + } /* Measurement related flags */ if (info->is_ac) analog->mqflags |= SR_MQFLAG_AC; if (info->is_dc) analog->mqflags |= SR_MQFLAG_DC; + if (info->is_diode) + analog->mqflags |= SR_MQFLAG_DIODE; } static gboolean flags_valid(const struct metex14_info *info) @@ -219,6 +213,7 @@ static gboolean flags_valid(const struct metex14_info *info) /* Does the packet have more than one multiplier? */ count = 0; + count += (info->is_pico) ? 1 : 0; count += (info->is_nano) ? 1 : 0; count += (info->is_micro) ? 1 : 0; count += (info->is_milli) ? 1 : 0; @@ -252,6 +247,17 @@ static gboolean flags_valid(const struct metex14_info *info) return TRUE; } +#ifdef HAVE_LIBSERIALPORT +SR_PRIV int sr_metex14_packet_request(struct sr_serial_dev_inst *serial) +{ + const uint8_t wbuf = 'D'; + + sr_spew("Requesting DMM packet."); + + return (serial_write(serial, &wbuf, 1) == 1) ? SR_OK : SR_ERR; +} +#endif + SR_PRIV gboolean sr_metex14_packet_valid(const uint8_t *buf) { struct metex14_info info; @@ -291,6 +297,9 @@ SR_PRIV int sr_metex14_parse(const uint8_t *buf, float *floatval, info_local = (struct metex14_info *)info; + /* Don't print byte 13. That one contains the carriage return. */ + sr_dbg("DMM packet: \"%.13s\"", buf); + if ((ret = parse_value(buf, floatval)) != SR_OK) { sr_err("Error parsing value: %d.", ret); return ret;