76 lines
2.6 KiB
C++
76 lines
2.6 KiB
C++
#include "icsneo/communication/livedata.h"
|
|
namespace icsneo {
|
|
|
|
namespace LiveDataUtil {
|
|
|
|
LiveDataHandle getNewHandle() {
|
|
static LiveDataHandle currentHandle = 0;
|
|
++currentHandle;
|
|
if(currentHandle == std::numeric_limits<LiveDataHandle>::max()) {
|
|
EventManager::GetInstance().add(APIEvent::Type::LiveDataInvalidHandle, APIEvent::Severity::Error);
|
|
currentHandle = 1;
|
|
}
|
|
return currentHandle;
|
|
}
|
|
|
|
double liveDataValueToDouble(const LiveDataValue& val) {
|
|
constexpr double liveDataFixedPointToDouble = 0.00000000023283064365386962890625;
|
|
return val.value * liveDataFixedPointToDouble;
|
|
}
|
|
|
|
int liveDataDoubleToValue(LiveDataValue& value, const double& dFloat) {
|
|
union {
|
|
struct
|
|
{
|
|
uint32_t ValueFractionPart;
|
|
int32_t ValueInt32;
|
|
} parts;
|
|
int64_t ValueLarge;
|
|
} CminiFixedPt;
|
|
constexpr double CM_FIXED_POINT_TO_DOUBLEVALUE = (1.0 / (double)(1ULL << 32)); // 2^-32
|
|
constexpr double CM_DOUBLEVALUE_TO_FIXED_POINT = ((double)(1ULL << 32)); // 2^32
|
|
// Use const for limits (C++98 compatible)
|
|
const double INT32_MAX_DOUBLE =
|
|
static_cast<double>(std::numeric_limits<int32_t>::max()) + (1.0 - std::numeric_limits<double>::epsilon());
|
|
const double INT32_MIN_DOUBLE = static_cast<double>(std::numeric_limits<int32_t>::min());
|
|
const double MIN_FIXED_POINT_DOUBLE = (double)(1ull * CM_FIXED_POINT_TO_DOUBLEVALUE);
|
|
|
|
// This needs to be assigned separately, otherwise, for dFloat >= 2^31,
|
|
// long double dBigFloat = dFloat * CM_DOUBLEVALUE_TO_FIXED_POINT overflows
|
|
// long long (value is >= 2^63) and so the assignment ValueLarge = dBigFloat is undefined
|
|
|
|
int32_t intPart; //creating temp variable due to static analysis warning about writing and reading to different union members
|
|
if (dFloat < 0.0)
|
|
intPart = (int32_t)floor(dFloat);
|
|
else
|
|
intPart = (int32_t)dFloat;
|
|
|
|
//using temp varialbes to avoid static analysis warning about read/write to different union members
|
|
double frac = dFloat - (double)(intPart);
|
|
uint32_t fracPart = (uint32_t)floor((frac * CM_DOUBLEVALUE_TO_FIXED_POINT) + 0.5);
|
|
|
|
//write temp vars back into the union
|
|
CminiFixedPt.parts.ValueInt32 = intPart;
|
|
CminiFixedPt.parts.ValueFractionPart = fracPart;
|
|
value.value = CminiFixedPt.ValueLarge;
|
|
|
|
if (dFloat == (double)0.0)
|
|
return 0;
|
|
|
|
//check if double can be stored as 32.32
|
|
// 0x1 0000 0000 0000 0000 * CM_FIXED_POINT_TO_DOUBLEVALUE = 0x1 0000 0000
|
|
if (dFloat > INT32_MAX_DOUBLE)
|
|
return 1;
|
|
if (dFloat < INT32_MIN_DOUBLE)
|
|
return -1;
|
|
|
|
// Use absolute value for minimum fixed point check
|
|
double absFloat = (dFloat < 0.0) ? -dFloat : dFloat;
|
|
if (absFloat < MIN_FIXED_POINT_DOUBLE)
|
|
return -2;
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // namespace LiveDataUtil
|
|
} // namespace icsneo
|