From 1f2695d4280d322f92211af4e246239c8055c91a Mon Sep 17 00:00:00 2001 From: Stefan Wahren Date: Fri, 6 Apr 2012 17:42:55 +0200 Subject: [PATCH] Added support for 4 byte floating point numbers --- mbus/mbus-protocol.c | 60 +++++++++++++++++++++++++++++++++++++++++++- mbus/mbus-protocol.h | 2 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/mbus/mbus-protocol.c b/mbus/mbus-protocol.c index 3cb9b46..2cbd014 100644 --- a/mbus/mbus-protocol.c +++ b/mbus/mbus-protocol.c @@ -10,6 +10,7 @@ //------------------------------------------------------------------------------ #include +#include #include #include @@ -438,6 +439,53 @@ mbus_data_int_encode(u_char *int_data, size_t int_data_size, int value) return -1; } +//------------------------------------------------------------------------------ +/// +/// Decode float data +/// +/// see also http://en.wikipedia.org/wiki/Single-precision_floating-point_format +/// +//------------------------------------------------------------------------------ +float +mbus_data_float_decode(u_char *float_data) +{ + float val = 0.0f; + long temp = 0, fraction; + int sign,exponent; + size_t i; + + if (float_data) + { + for (i = 4; i > 0; i--) + { + temp = (temp << 8) + float_data[i-1]; + } + + // first bit = sign bit + sign = (temp >> 31) ? -1 : 1; + + // decode 8 bit exponent + exponent = ((temp & 0x7F800000) >> 23) - 127; + + // decode explicit 23 bit fraction + fraction = temp & 0x007FFFFF; + + if ((exponent != -127) && + (exponent != 128)) + { + // normalized value, add bit 24 + fraction |= 0x800000; + } + + // calculate float value + val = (float) sign * fraction * pow(2.0f, -23.0f) * (1 << exponent); + + return val; + } + + return -1.0; +} + //------------------------------------------------------------------------------ /// /// Decode string data. @@ -1626,6 +1674,7 @@ mbus_data_record_decode(mbus_data_record *record) { int val; long val2; + float val3; struct tm time; switch (record->drh.dib.dif & 0x0F) @@ -1710,7 +1759,16 @@ mbus_data_record_decode(mbus_data_record *record) break; - // case 0x05: + case 0x05: // 4 Byte Real (32 bit) + + val3 = mbus_data_float_decode(record->data); + + snprintf(buff, sizeof(buff), "%f", val3); + + if (debug) + printf("%s: DIF 0x%.2x was decoded using 4 byte Real\n", __PRETTY_FUNCTION__, record->drh.dib.dif); + + break; case 0x06: // 6 byte integer (48 bit) diff --git a/mbus/mbus-protocol.h b/mbus/mbus-protocol.h index f5b2fa5..c66cd5d 100644 --- a/mbus/mbus-protocol.h +++ b/mbus/mbus-protocol.h @@ -512,6 +512,8 @@ long mbus_data_bcd_decode(u_char *bcd_data, size_t bcd_data_size); int mbus_data_int_decode(u_char *int_data, size_t int_data_size); long mbus_data_long_decode(u_char *int_data, size_t int_data_size); +float mbus_data_float_decode(u_char *float_data); + void mbus_data_tm_decode(struct tm *t, u_char *t_data, size_t t_data_size); void mbus_data_str_decode(u_char *dst, const u_char *src, size_t len);