diff --git a/src/knx/application_program_object.cpp b/src/knx/application_program_object.cpp index 4f3993d..37bb2ab 100644 --- a/src/knx/application_program_object.cpp +++ b/src/knx/application_program_object.cpp @@ -47,3 +47,26 @@ uint32_t ApplicationProgramObject::getInt(uint32_t addr) { return ::getInt(TableObject::data() + addr); } + +double ApplicationProgramObject::getFloat(uint32_t addr, ParameterFloatEncodings encoding) +{ + uint8_t buffer[8]; + switch (encoding) + { + case Float_Enc_DPT9: + memcpyInverted(buffer, TableObject::data() + addr, 2); + return Decode_DPT9_Float(*(uint16_t*)buffer); + break; + case Float_Enc_IEEE754Single: + memcpyInverted(buffer, TableObject::data() + addr, 4); + return *(float*)(buffer); + break; + case Float_Enc_IEEE754Double: + memcpyInverted(buffer, TableObject::data() + addr, 8); + return *(double*)(buffer); + break; + default: + return 0; + break; + } +} diff --git a/src/knx/application_program_object.h b/src/knx/application_program_object.h index 071166a..52b743c 100644 --- a/src/knx/application_program_object.h +++ b/src/knx/application_program_object.h @@ -1,6 +1,7 @@ #pragma once #include "table_object.h" +#include "bits.h" class ApplicationProgramObject : public TableObject { @@ -10,4 +11,5 @@ class ApplicationProgramObject : public TableObject uint8_t getByte(uint32_t addr); uint16_t getWord(uint32_t addr); uint32_t getInt(uint32_t addr); + double getFloat(uint32_t addr, ParameterFloatEncodings encoding); }; \ No newline at end of file diff --git a/src/knx/bits.cpp b/src/knx/bits.cpp index a1e5941..4d88b11 100644 --- a/src/knx/bits.cpp +++ b/src/knx/bits.cpp @@ -107,6 +107,31 @@ uint64_t sixBytesToUInt64(uint8_t* data) return l; } +const uint16_t eMask = 0x7800; //01111000 00000000 +const uint16_t mMask = 0x87FF; //10000111 11111111 +const uint16_t sMask = 0x8000; //10000000 00000000 + +float Decode_DPT9_Float(uint16_t n) +{ + uint16_t e = n & eMask; + uint16_t m = n & mMask; + int16_t sm = m; + if (m & sMask) + { + m = (~m & mMask) + 1; + sm = -(int)m; + } + return (0.01 * (float)sm) * pow(2, e); +} + +void memcpyInverted(uint8_t* dst, uint8_t* src, size_t length) +{ + for (int i = 0; i < length; i++) + { + dst[i] = src[length - i - 1]; + } +} + // The CRC of the Memory Control Block Table Property is a CRC16-CCITT with the following // parameters: // Width = 16 bit diff --git a/src/knx/bits.h b/src/knx/bits.h index 54c9712..689d868 100644 --- a/src/knx/bits.h +++ b/src/knx/bits.h @@ -92,3 +92,13 @@ void sixBytesFromUInt64(uint64_t num, uint8_t* toByteArray); uint64_t sixBytesToUInt64(uint8_t* data); uint16_t crc16Ccitt(uint8_t* input, uint16_t length); + +enum ParameterFloatEncodings +{ + Float_Enc_DPT9 = 0, // 2 Byte. See Chapter 3.7.2 section 3.10 (Datapoint Types “2-Octet Float Value”) + Float_Enc_IEEE754Single = 1, // 4 Byte. C++ float + Float_Enc_IEEE754Double = 2, // 8 Byte. C++ double +}; + +float Decode_DPT9_Float(uint16_t n); +void memcpyInverted(uint8_t* dst, uint8_t* src, size_t length); diff --git a/src/knx_facade.h b/src/knx_facade.h index c82f67e..e13cd1b 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -268,6 +268,14 @@ template class KnxFacade : private SaveRestore return _bau.parameters().getInt(addr); } + double paramFloat(uint32_t addr, ParameterFloatEncodings enc) + { + if (!_bau.configured()) + return 0; + + return _bau.parameters().getFloat(addr, enc); + } + #if (MASK_VERSION == 0x07B0) || (MASK_VERSION == 0x27B0) || (MASK_VERSION == 0x57B0) GroupObject& getGroupObject(uint16_t goNr) {