better rounding and avoid to loose precision, move 16 bit float to datatype
This commit is contained in:
@@ -317,42 +317,6 @@ result_t getFieldLength(const SingleDataField *field, dtlf_t *length) {
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t floatToInt16(float val) {
|
|
||||||
// (0.01*m)(2^e) format with sign, 12 bits mantissa (incl. sign), 4 bits exponent
|
|
||||||
if (val == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
bool negative = val < 0;
|
|
||||||
if (negative) {
|
|
||||||
val = -val;
|
|
||||||
}
|
|
||||||
val = roundf(val*100.0f);
|
|
||||||
int exp = ilogb(val)-10;
|
|
||||||
if (exp < -10 || exp > 15) {
|
|
||||||
return 0x7fff; // invalid value DPT 9
|
|
||||||
}
|
|
||||||
auto shift = exp > 0 ? exp : 0;
|
|
||||||
auto sig = static_cast<uint32_t>(val * exp2(-shift));
|
|
||||||
uint32_t value = static_cast<uint32_t>(shift << 11) | (negative ? 0x800-sig : sig);
|
|
||||||
if (negative) {
|
|
||||||
return value | 0x8000;
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
float int16ToFloat(uint16_t val) {
|
|
||||||
if (val == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (val == 0x7fff) {
|
|
||||||
return static_cast<float>(0xffffffff); // NaN
|
|
||||||
}
|
|
||||||
bool negative = val&0x8000;
|
|
||||||
int exp = (val>>11)&0xf;
|
|
||||||
int sig = val&0x7ff;
|
|
||||||
return static_cast<float>((negative ? sig-0x800 : sig) * exp2(exp) * 0.01);
|
|
||||||
}
|
|
||||||
|
|
||||||
result_t KnxHandler::sendGroupValue(knx_addr_t dest, apci_t apci, dtlf_t& lengthFlag, unsigned int value,
|
result_t KnxHandler::sendGroupValue(knx_addr_t dest, apci_t apci, dtlf_t& lengthFlag, unsigned int value,
|
||||||
const SingleDataField *field) const {
|
const SingleDataField *field) const {
|
||||||
if (!m_con || !m_con->isConnected() || !m_con->getAddress()) {
|
if (!m_con || !m_con->isConnected() || !m_con->getAddress()) {
|
||||||
@@ -382,7 +346,7 @@ const SingleDataField *field) const {
|
|||||||
return ret;
|
return ret;
|
||||||
} else if (lengthFlag.length == 2) {
|
} else if (lengthFlag.length == 2) {
|
||||||
// convert to (0.01*m)(2^e) format with sign, 12 bits mantissa (incl. sign), 4 bits exponent
|
// convert to (0.01*m)(2^e) format with sign, 12 bits mantissa (incl. sign), 4 bits exponent
|
||||||
value = floatToInt16(fval);
|
value = floatToUint16(fval);
|
||||||
} else if (lengthFlag.length == 4) {
|
} else if (lengthFlag.length == 4) {
|
||||||
// convert to IEEE 754
|
// convert to IEEE 754
|
||||||
value = floatToUint(fval);
|
value = floatToUint(fval);
|
||||||
@@ -686,8 +650,8 @@ void KnxHandler::handleGroupTelegram(knx_addr_t src, knx_addr_t dest, int len, c
|
|||||||
if (lengthFlag.isFloat || lengthFlag.hasDivisor) {
|
if (lengthFlag.isFloat || lengthFlag.hasDivisor) {
|
||||||
float fval;
|
float fval;
|
||||||
if (lengthFlag.length == 2) {
|
if (lengthFlag.length == 2) {
|
||||||
// convert from (0.01*m)(2^e) format with sign, 12 bits mantissa (incl. sign), 4 bits exponent
|
// convert from (0.01*m)(2^e) format
|
||||||
fval = int16ToFloat(static_cast<uint16_t>(value));
|
fval = uint16ToFloat(static_cast<uint16_t>(value));
|
||||||
} else if (lengthFlag.length == 4) {
|
} else if (lengthFlag.length == 4) {
|
||||||
// convert from IEEE 754
|
// convert from IEEE 754
|
||||||
bool negative = (value & (1u << 31)) != 0;
|
bool negative = (value & (1u << 31)) != 0;
|
||||||
|
|||||||
@@ -95,6 +95,34 @@ uint32_t floatToUint(float val) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float uint16ToFloat(uint16_t val) {
|
||||||
|
if (val == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (val == 0x7fff) {
|
||||||
|
return static_cast<float>(0xffffffff); // NaN
|
||||||
|
}
|
||||||
|
bool negative = val&0x8000;
|
||||||
|
int exp = (val>>11)&0xf;
|
||||||
|
int sig = val&0x7ff;
|
||||||
|
return static_cast<float>((negative ? sig-0x800 : sig) * exp2(exp) * 0.01);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t floatToUint16(float value) {
|
||||||
|
// (0.01*m)(2^e) format with sign, 12 bits mantissa (incl. sign), 4 bits exponent
|
||||||
|
if (value == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
bool negative = value < 0;
|
||||||
|
double val = round(value*(negative ? -100.0 : 100.0));
|
||||||
|
int exp = ilogb(val)-10;
|
||||||
|
if (exp < -10 || exp > 15) {
|
||||||
|
return 0x7fff; // invalid value DPT 9
|
||||||
|
}
|
||||||
|
auto shift = exp > 0 ? exp : 0;
|
||||||
|
auto sig = static_cast<uint16_t>(val * exp2(-shift));
|
||||||
|
return static_cast<uint16_t>((shift << 11) | (negative ? 0x8000 | (0x800-sig) : sig));
|
||||||
|
}
|
||||||
|
|
||||||
bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
|
bool DataType::dump(OutputFormat outputFormat, size_t length, bool appendDivisor, ostream* output) const {
|
||||||
if (outputFormat & OF_JSON) {
|
if (outputFormat & OF_JSON) {
|
||||||
|
|||||||
+18
-2
@@ -194,10 +194,26 @@ float uintToFloat(unsigned int value, bool negative);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a float value to the 32 bit representation (IEEE 754).
|
* Format a float value to the 32 bit representation (IEEE 754).
|
||||||
* @param val the float value.
|
* @param value the float value.
|
||||||
* @return the 32 bit representation of the float value, or 0xffffffff if NaN.
|
* @return the 32 bit representation of the float value, or 0xffffffff if NaN.
|
||||||
*/
|
*/
|
||||||
uint32_t floatToUint(float val);
|
uint32_t floatToUint(float value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a float value with precision of 2 decimal from 16 bit format with
|
||||||
|
* sign, 11 bit mantissa, 4 bit exponent as (0.01*m)(2^e).
|
||||||
|
* @param value the 16 bit representation of the float value.
|
||||||
|
* @return the float value.
|
||||||
|
*/
|
||||||
|
float uint16ToFloat(uint16_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format a float value with precision of 2 decimal from 16 bit format with
|
||||||
|
* sign, 11 bit mantissa, 4 bit exponent as (0.01*m)(2^e).
|
||||||
|
* @param value the float value.
|
||||||
|
* @return the 16 bit representation of the float value, or 0xffff if NaN.
|
||||||
|
*/
|
||||||
|
uint16_t floatToUint16(float value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all kinds of data types.
|
* Base class for all kinds of data types.
|
||||||
|
|||||||
Reference in New Issue
Block a user