From 68d05f37554b750b7957385b1f6419923a748998 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 24 Dec 2023 10:53:58 +0100 Subject: [PATCH] use nan for float replacement value --- src/lib/ebus/datatype.cpp | 6 ++-- src/lib/ebus/test/test_data.cpp | 52 +++++++++++++++++++++++++++++++-- 2 files changed, 52 insertions(+), 6 deletions(-) diff --git a/src/lib/ebus/datatype.cpp b/src/lib/ebus/datatype.cpp index 160b01a9..c301aab6 100755 --- a/src/lib/ebus/datatype.cpp +++ b/src/lib/ebus/datatype.cpp @@ -100,7 +100,7 @@ float uint16ToFloat(uint16_t val) { return 0; } if (val == 0x7fff) { - return static_cast(0xffffffff); // NaN + return NAN; } bool negative = val&0x8000; int exp = (val>>11)&0xf; @@ -1275,9 +1275,9 @@ DataTypeList::DataTypeList() { // signed number (fraction 1/1000), -32.767 - +32.767, big endian add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian - add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0xfeffffff, 0x7effffff, 1)); + add(new NumberDataType("EXP", 32, SIG|EXP, 0x7fc00000, 0xfeffffff, 0x7effffff, 1)); // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian - add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0xfeffffff, 0x7effffff, 1)); + add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7fc00000, 0xfeffffff, 0x7effffff, 1)); // unsigned integer, 0 - 65534, little endian add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1)); // unsigned integer, 0 - 65534, big endian diff --git a/src/lib/ebus/test/test_data.cpp b/src/lib/ebus/test/test_data.cpp index d4110ad8..44f7d8e0 100755 --- a/src/lib/ebus/test/test_data.cpp +++ b/src/lib/ebus/test/test_data.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include "lib/ebus/data.h" @@ -25,6 +26,8 @@ using namespace ebusd; using std::cout; using std::endl; +using std::isnan; +using std::setprecision; static bool error = false; @@ -87,6 +90,12 @@ class TestReader : public MappedFileReader { const DataField* m_fields; }; +typedef struct floatCheck_t { + float encval; + float decval; + uint16_t ival; +} floatCheck_t; + int main() { // entry: definition, decoded value, master data, slave data, flags @@ -421,18 +430,17 @@ int main() { {"x,,exp", "-0.09", "10feffff04ec51b8bd", "00", ""}, {"x,,exp", "0.0", "10feffff0400000000", "00", ""}, {"x,,exp", "-0.001", "10feffff046f1283ba", "00", ""}, - {"x,,exp", "-", "10feffff040000807f", "00", ""}, + {"x,,exp", "-", "10feffff040000c07f", "00", ""}, {"x,,exp", "-32.767", "10feffff04681103c2", "00", ""}, {"x,,exp,1000", "-0.000090000", "10feffff04ec51b8bd", "00", ""}, {"x,,exp,-100", "-9", "10feffff04ec51b8bd", "00", ""}, {"x,,exp", "0.25", "10feffff040000803e", "00", ""}, - {"x,,exp", "-", "10feffff040000c07f", "00", "W"}, {"x,,exp", "0.95", "10feffff043333733f", "00", ""}, {"x,,exp", "0.65", "10feffff046666263f", "00", ""}, {"x,,exr", "-0.09", "10feffff04bdb851ec", "00", ""}, {"x,,exr", "0.0", "10feffff0400000000", "00", ""}, {"x,,exr", "-0.001", "10feffff04ba83126f", "00", ""}, - {"x,,exr", "-", "10feffff047f800000", "00", ""}, + {"x,,exr", "-", "10feffff047fc00000", "00", ""}, {"x,,exr", "-32.767", "10feffff04c2031168", "00", ""}, {"x,,exr,1000", "-0.000090000", "10feffff04bdb851ec", "00", ""}, {"x,,exr,-100", "-9", "10feffff04bdb851ec", "00", ""}, @@ -750,5 +758,43 @@ int main() { delete templates; + const floatCheck_t floatChecks[] = { + {0.0f, 0.0f, 0}, + {0.01f, 0.01f, 1}, + {-0.01f, -0.01f, 0x8000|(0x800-1)}, + {0.09f, 0.09f, 9}, + {-0.09f, -0.09f, 0x8000|(0x800-9)}, + {0.99f, 0.99f, 99}, + {-0.99f, -0.99f, 0x8000|(0x800-99)}, + {1.0f, 1.0f, 100}, + {-1.0f, -1.0f, 0x8000|(0x800-100)}, + {670433.25f, 670433.5f, 0x7ffe}, + {-670760.94f, -671088.62f, 0xf801}, + {NAN, NAN, 0x7fff}, + // some extra tests: + {-30.0f, -30.0f, 0x8A24}, + {-327.68f, -327.68f, 0xAC00}, + {46039.04f, 46039.04f, 0x6464}, + {-9461.76f, -9461.76f, 0xC8C8}, + }; + for (unsigned int i = 0; i < sizeof(floatChecks) / sizeof(floatChecks[0]); i++) { + floatCheck_t check = floatChecks[i]; + float value = uint16ToFloat(check.ival); + cout << " parse 0x" << hex << check.ival; + if (isnan(value) ? !isnan(check.encval) : value != check.encval) { + cout << " invalid: " << setprecision(8) << value << " instead of " << setprecision(8) << check.encval << endl; + error = true; + } else { + cout << ": OK" << endl; + } + uint32_t ivalue = floatToUint16(check.decval); + cout << " format " << setprecision(8) << check.decval; + if (ivalue != check.ival) { + cout << " invalid: " << ivalue << " instead of " << check.ival << endl; + error = true; + } else { + cout << ": OK" << endl; + } + } return error ? 1 : 0; }