Добрый вечер. Пишу кросс-клиент для BTLE железки. Впервые столкнулся с форматом поля SFLOAT.
Кусок из стандарта:
The following information is defined in ISO/IEEE Std.
11073-2060™1-2008 [1]. The SFLOAT-Type data type is defined to
represent numeric values that are not integer in type. The
SFLOAT-Type is defined as a 16-bit value with 12-bit mantissa
and 4-bit exponent. See Annex F.8 of [1] for a thorough
definition of the SFLOAT-Type. This data type is defined as
follows: Exponent Mantissa Size 4 bit 12 bit
16-bit float type; the integer type is a placeholder only
SFLOAT-Type ::= INT-U16 The 16–bit value contains a 4-bit
exponent to base 10, followed by a 12-bit mantissa.
Each is in twos-complement form. Special values are assigned to
express the following:
NaN [exponent 0, mantissa +(2^11 –1) → 0x07FF]
NRes [exponent 0, mantissa –(2^11) → 0x0800]
+ INFINITY [exponent 0, mantissa +(2^11 –2) → 0x07FE]
– INFINITY [exponent 0, mantissa –(2^11 –2) → 0x0802]
Reserved for future use [exponent 0, mantissa –(2^11 –1) → 0x0801]
На просторах сети был найден нужный код и немного обрезан под мои нужды:
typedef enum {
MDER_S_POSITIVE_INFINITY = 0x07FE,
MDER_S_NaN = 0x07FF,
MDER_S_NRes = 0x0800,
MDER_S_RESERVED_VALUE = 0x0801,
MDER_S_NEGATIVE_INFINITY = 0x0802
} ReservedSFloatValues;
static const quint32 FIRST_S_RESERVED_VALUE = MDER_S_POSITIVE_INFINITY;
static const double reserved_float_values[5] = {INFINITY, NAN, NAN, NAN, -INFINITY};
double read_sfloat(quint16 int_data)
{
quint16 mantissa = int_data & 0x0FFF;
quint8 expoent = int_data >> 12;
if (expoent >= 0x0008) {
expoent = -((0x000F + 1) - expoent);
}
float output = 0;
if (mantissa >= FIRST_S_RESERVED_VALUE && mantissa
<= MDER_S_NEGATIVE_INFINITY) {
output = reserved_float_values[mantissa - FIRST_S_RESERVED_VALUE];
} else {
if (mantissa >= 0x0800) {
mantissa = -((0x0FFF + 1) - mantissa);
}
double magnitude = pow(10.0f, expoent);
output = (mantissa * magnitude);
}
return output;
}
Есть контрольные данные из спека к прибору:
Byte:2 Format:SFLOAT, LittleEndian
ex.1) 17.6Kpa -> 0xB0, 0xF0
ex.2) 128mmHg -> 0x80, 0x00
Собственно, вопросы:
не совсем понимаю, где ошибка.
Прогонка первого ex. через парсер — результат inf. Второго — 128 OK