libiec61850
libiec61850 copied to clipboard
MmsValue_getUtcTimeInMs
Incorrect parsing
for (var remainder = 0; remainder < 1000; remainder += 1) {
var fractionOfSecond = ((remainder) * 16777 + ((remainder * 216) / 1000)) & 0xffc000; // 10 significant bits
var decoded = fractionOfSecond / 16777;
Debug.WriteLine("remainder={0} encoded={1} decoded={2}", remainder, fractionOfSecond, decoded);
}
Correct parsing
for (var remainder = 0; remainder < 1000; remainder += 1) {
var fractionOfSecond = ((remainder) * 16777 + ((remainder * 216) / 1000)) & 0xffc000; // 10 significant bits
var decoded = (int)(fractionOfSecond / 16777F + 0.5F);
Debug.WriteLine("remainder={0} encoded={1} decoded={2}", remainder, fractionOfSecond, decoded);
}
uint64_t
MmsValue_getUtcTimeInMs(const MmsValue* self)
{
uint32_t timeval32;
const uint8_t* valueArray = self->value.utcTime;
#if (ORDER_LITTLE_ENDIAN == 1)
memcpyReverseByteOrder((uint8_t*) &timeval32, valueArray, 4);
#else
memcpy((uint8_t*) &timeval32, valueArray, 4);
#endif
uint32_t fractionOfSecond = 0;
fractionOfSecond = (valueArray[4] << 16);
fractionOfSecond += (valueArray[5] << 8);
fractionOfSecond += (valueArray[6]);
uint32_t remainder = fractionOfSecond / 16777.0 + 0.5;
uint64_t msVal = (timeval32 * 1000LL) + remainder;
return msVal;
}
MmsValue*
MmsValue_setUtcTimeMs(MmsValue* self, uint64_t timeval)
{
uint32_t timeval32 = (timeval / 1000LL);
uint8_t* timeArray = (uint8_t*) &timeval32;
uint8_t* valueArray = self->value.utcTime;
#if (ORDER_LITTLE_ENDIAN == 1)
memcpyReverseByteOrder(valueArray, timeArray, 4);
#else
memcpy(valueArray, timeArray, 4);
#endif
uint32_t remainder = (timeval % 1000LL);
uint32_t fractionOfSecond = ((remainder) * 16777 + ((remainder * 216) / 1000)) & 0xffc000; // 10 significant bits;
/* encode fraction of second */
valueArray[4] = ((fractionOfSecond >> 16) & 0xff);
valueArray[5] = ((fractionOfSecond >> 8) & 0xff);
valueArray[6] = (fractionOfSecond & 0xff);
/* encode time quality */
valueArray[7] = 0x0a; /* 10 bit sub-second time accuracy */
return self;
}
Care to create a pull request or close if already fixed? I fail to see your exact edits as there's no formatted diff. An why do you think it's appropriate to use floats in uint32_t arithmetic?
It's possible to calculate without floats: uint32_t remainder = (fractionOfSecond + 16777 / 2) / 16777;
But encoding also needs rounding before drop insignificant bits: fractionOfSecond = ((remainder) * 16777 + ((remainder * 216) / 1000) + 0x2000) & 0xffc000;