* This file is part of the libsigrok project.
*
* Copyright (C) 2012-2013 Uwe Hermann <uwe@hermann-uwe.de>
- * Copyright (C) 2018 Matthias Schulz <matthschulz@arcor.de>
+ * Copyright (C) 2018 Matthias Schulz <matthias.schulz@mailbox.org>
*
* 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
/*
* Voltcraft 13-bytes ASCII protocol parser.
+ * derived from metex14.c
*
* Bytes 1-3 measuring mode, byte 4 '-' for negative,
* bytes 5-9 value, bytes 10-11 unit, bytes 12-13 CRLF 0d 0a.
#define LOG_PREFIX "vc96"
/** Parse value from buf, byte 3-8. */
-static int parse_value(const uint8_t *buf, struct vc96_info *info,
+static int parse_value(const uint8_t *buf,
float *result, int *exponent)
{
- int i, is_ol, cnt, dot_pos;
- char valstr[8 + 1];
-
- (void)info;
+ int i, is_ol, cnt, dot_pos, ret;
+ ret = SR_ERR; // to be overwritten with SR_OK
+ char valstr[6 + 1];
+ sr_spew("parse_value buf still with spaces \"%.12s\".", buf);
/* Strip all spaces from bytes 3-8. */
memset(&valstr, 0, 6 + 1);
for (i = 0, cnt = 0; i < 6; i++) {
if (buf[3 + i] != ' ')
valstr[cnt++] = buf[3 + i];
}
+ sr_spew("parse_value valstr without spaces \"%.7s\".", valstr);
/* Bytes 5-7: Over limit (various forms) */
is_ol = 0;
is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-OL.")) ? 1 : 0;
is_ol += (!g_ascii_strcasecmp((const char *)&valstr, "-OL")) ? 1 : 0;
if (is_ol != 0) {
- sr_spew("Over limit.");
*result = INFINITY;
- return SR_OK;
- }
-
- /* Bytes 3-10: Sign, value (up to 5 digits) and decimal point */
- sr_atof_ascii((const char *)&valstr, result);
-
- dot_pos = strcspn(valstr, ".");
- if (dot_pos < cnt)
- *exponent = -(cnt - dot_pos - 1);
- else
- *exponent = 0;
-
- sr_spew("The display value is %f.", *result);
-
- return SR_OK;
+ sr_spew("parse_value Over limit.");
+ ret = SR_OK;
+ }else{
+ /* Bytes 3-10: Sign, value (up to 5 digits including decimal point) */
+ if ((ret = sr_atof_ascii((const char *)&valstr, result)) != SR_OK)
+ sr_dbg("parse_value Error sr_atof_ascii: %d.", ret);
+ sr_spew("parse_value value %f.", *result);
+
+ dot_pos = strcspn(valstr, ".");
+ if (dot_pos < cnt)
+ *exponent = -(cnt - dot_pos - 1);
+ else
+ *exponent = 0;
+ sr_spew("parse_value Exponent %i", *exponent);
+ };
+ return ret;
}
+
static void parse_flags(const char *buf, struct vc96_info *info)
{
int i, cnt;
info->is_ac = !strncmp(buf, "AC", 2);
info->is_dc = !strncmp(buf, "DC", 2);
- /* Bytes 0-2: Measurement mode DIO, OHM */
- info->is_ohm = !strncmp(buf, "OHM", 3);
+ /*
+ * Note:
+ * - Protocol doesn't distinguish "resistance" from "beep" mode.
+ */
+ /* Bytes 0-2: Measurement mode, except AC/DC */
+ info->is_ohm = !strncmp(buf, "OHM", 3) || !strncmp(buf, "BEP", 3);
info->is_diode = !strncmp(buf, "DIO", 3);
info->is_hfe = !strncmp(buf, "hfe", 3);
/* Bytes 3-8: See parse_value(). */
+ sr_spew("parse_flags buf still with spaces \"%.12s\".", buf);
/* Strip all spaces from bytes 9-10. */
memset(&unit, 0, 2 + 1);
for (i = 0, cnt = 0; i < 2; i++) {
if (buf[9 + i] != ' ')
unit[cnt++] = buf[9 + i];
}
- sr_spew("Bytes 9..10 without spaces \"%.4s\".", unit);
+ sr_spew("parse_flags Bytes 9..10 (unit) without spaces \"%.4s\".", unit);
/* Bytes 9-10: Unit */
u = (const char *)&unit;
- if (!g_ascii_strcasecmp(u, "A"))
- info->is_ampere = TRUE;
- else if (!g_ascii_strcasecmp(u, "mA"))
+
+ if (!g_ascii_strcasecmp(u, "mA"))
info->is_milli = info->is_ampere = TRUE;
else if (!g_ascii_strcasecmp(u, "uA"))
info->is_micro = info->is_ampere = TRUE;
- else if (!g_ascii_strcasecmp(u, "V"))
- info->is_volt = TRUE;
+ else if (!g_ascii_strcasecmp(u, "A"))
+ info->is_ampere = TRUE;
else if (!g_ascii_strcasecmp(u, "mV"))
info->is_milli = info->is_volt = TRUE;
- else if (!g_ascii_strcasecmp(u, "K"))
+ else if (!g_ascii_strcasecmp(u, "V"))
+ info->is_volt = TRUE;
+ /* VC96 sends wrong upper case "K", ignore case, for devices maybe doing this correct */
+ else if (!g_ascii_strncasecmp(u, "K", 1))
info->is_kilo = TRUE;
- else if (!g_ascii_strcasecmp(u, "M"))
+ else if (strchr(u, (int)'M'))
info->is_mega = TRUE;
- else if (!g_ascii_strcasecmp(u, ""))
+ else if (!g_ascii_strcasecmp(u, " "))
info->is_unitless = TRUE;
- /* Bytes 0-2: Measurement mode, except AC/DC */
- info->is_resistance = !strncmp(buf, "OHM", 3) ||
- (!strncmp(buf, " ", 3) && info->is_ohm);
- info->is_diode = !strncmp(buf, "DIO", 3) ||
- (!strncmp(buf, " ", 3) && info->is_volt && info->is_milli);
- info->is_hfe = !strncmp(buf, "hfe", 3) ||
- (!strncmp(buf, " ", 3) && !info->is_ampere && !info->is_volt &&
- !info->is_resistance && !info->is_diode);
-
- /*
- * Note:
- * - Protocol doesn't distinguish "resistance" from "beep" mode.
- */
-
/* Byte 12: Always '\r' (carriage return, 0x0d, 12) */
/* Byte 13: Always '\n' (carriage return, 0x0a, 13) */
}
(void)exponent;
- /* Factors */
+ /* Factors representing the exponent of 123Exx */
factor = 0;
if (info->is_micro)
factor -= 6;
factor += 3;
if (info->is_mega)
factor += 6;
+
*floatval *= powf(10, factor);
+ *exponent += factor;
/* Measurement modes */
if (info->is_volt) {
memset(info_local, 0x00, sizeof(struct vc96_info));
- if ((ret = parse_value(buf, info_local, floatval, &exponent)) < 0) {
+ if ((ret = parse_value(buf, floatval, &exponent)) != SR_OK) {
sr_dbg("Error parsing value: %d.", ret);
return ret;
}
parse_flags((const char *)buf, info_local);
handle_flags(analog, floatval, &exponent, info_local);
+ sr_spew("sr_vc96_parse Exponent %i", exponent);
analog->encoding->digits = -exponent;
analog->spec->spec_digits = -exponent;