improve crc calculation

* removed TableObject::crc16Citt method and use the one in bits.h

* do not save crc in flash, instead calculate on-the-fly in CallbackProperty when state==LS_LOADED

* use DataProperty to store PID_PROG_VERSION

* WARNING: segmentSize calculation for crc calculation is currently not correct. Need to somehow access size of data in class that inherits from TableObject (e.g. ApplicationObject or RouterObject)
This commit is contained in:
Julius Lipp 2021-04-12 21:36:17 +02:00
parent 83bb83bd56
commit 1cadc320a5
3 changed files with 15 additions and 40 deletions

View File

@ -11,16 +11,7 @@ ApplicationProgramObject::ApplicationProgramObject(Memory& memory)
Property* properties[] = Property* properties[] =
{ {
new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_APPLICATION_PROG), new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_APPLICATION_PROG),
new CallbackProperty<ApplicationProgramObject>(this, PID_PROG_VERSION, true, PDT_GENERIC_05, 1, ReadLv3 | WriteLv3, new DataProperty(PID_PROG_VERSION, true, PDT_GENERIC_05, 1, ReadLv3 | WriteLv3),
[](ApplicationProgramObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
pushByteArray(io->_programVersion, 5, data);
return 1;
},
[](ApplicationProgramObject* io, uint16_t start, uint8_t count, const uint8_t* data) -> uint8_t
{
memcpy(io->_programVersion, data, 5);
return 1;
}),
new CallbackProperty<ApplicationProgramObject>(this, PID_PEI_TYPE, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0, new CallbackProperty<ApplicationProgramObject>(this, PID_PEI_TYPE, false, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv0,
[](ApplicationProgramObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t { [](ApplicationProgramObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
if(start == 0) if(start == 0)
@ -40,6 +31,7 @@ ApplicationProgramObject::ApplicationProgramObject(Memory& memory)
uint8_t* ApplicationProgramObject::save(uint8_t* buffer) uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
{ {
property(PID_PROG_VERSION)->read(_programVersion);
buffer = pushByteArray(_programVersion, 5, buffer); buffer = pushByteArray(_programVersion, 5, buffer);
return TableObject::save(buffer); return TableObject::save(buffer);
@ -48,6 +40,7 @@ uint8_t* ApplicationProgramObject::save(uint8_t* buffer)
const uint8_t* ApplicationProgramObject::restore(const uint8_t* buffer) const uint8_t* ApplicationProgramObject::restore(const uint8_t* buffer)
{ {
buffer = popByteArray(_programVersion, 5, buffer); buffer = popByteArray(_programVersion, 5, buffer);
property(PID_PROG_VERSION)->write(_programVersion);
return TableObject::restore(buffer); return TableObject::restore(buffer);
} }

View File

@ -31,8 +31,6 @@ uint8_t* TableObject::save(uint8_t* buffer)
{ {
buffer = pushByte(_state, buffer); buffer = pushByte(_state, buffer);
buffer = pushWord(_crc, buffer);
if (_data) if (_data)
buffer = pushInt(_memory.toRelative(_data), buffer); buffer = pushInt(_memory.toRelative(_data), buffer);
else else
@ -48,8 +46,6 @@ const uint8_t* TableObject::restore(const uint8_t* buffer)
buffer = popByte(state, buffer); buffer = popByte(state, buffer);
_state = (LoadState)state; _state = (LoadState)state;
buffer = popWord(_crc, buffer);
uint32_t relativeAddress = 0; uint32_t relativeAddress = 0;
buffer = popInt(relativeAddress, buffer); buffer = popInt(relativeAddress, buffer);
@ -137,7 +133,6 @@ void TableObject::loadEventLoading(const uint8_t* data)
case LE_START_LOADING: case LE_START_LOADING:
break; break;
case LE_LOAD_COMPLETED: case LE_LOAD_COMPLETED:
_crc = Crc16Citt(_data, saveSize() - 4 - 1 - 2); // remove 4 (memory) + 1 (state) + 2 (crc) bytes
loadState(LS_LOADED); loadState(LS_LOADED);
break; break;
case LE_UNLOAD: case LE_UNLOAD:
@ -234,7 +229,7 @@ void TableObject::errorCode(ErrorCode errorCode)
uint16_t TableObject::saveSize() uint16_t TableObject::saveSize()
{ {
return 5 + InterfaceObject::saveSize() + sizeof(_crc); return 5 + InterfaceObject::saveSize();
} }
void TableObject::initializeProperties(size_t propertiesSize, Property** properties) void TableObject::initializeProperties(size_t propertiesSize, Property** properties)
@ -272,14 +267,19 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert
pushInt(obj->tableReference(), data); pushInt(obj->tableReference(), data);
return 1; return 1;
}), }),
new CallbackProperty<TableObject>(this, PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0, new CallbackProperty<TableObject>(this, PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0,
[](TableObject* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t { [](TableObject* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t {
uint16_t size = obj->saveSize() - 5 - 2; // need to remove 5+2 extra bytes which were added in saveSize() if (obj->_state != LS_LOADED)
return 0; // need to check return code for invalid
data = pushInt(size, data); // Segment Size (2 bytes) uint32_t segmentSize = obj->saveSize();
data = pushByte(0, data); // CRC Control Byte: CRC always valid (1 byte) uint16_t crc16 = crc16Ccitt(obj->data(), segmentSize);
data = pushByte(0xFF, data); // ReadAccess/WriteAccess (1 byte)
data = pushWord(obj->_crc, data); // CRC checksum according to CRC16-CCITT spec (2 bytes) pushInt(segmentSize, data); // Segment size
pushByte(0x00, data + 4); // CRC control byte -> 0: always valid
pushByte(0xFF, data + 5); // Read access 4 bits + Write access 4 bits (unknown: value taken from real coupler device)
pushWord(crc16, data + 6); // CRC-16 CCITT of filter table
return 1; return 1;
}), }),
new DataProperty(PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT) new DataProperty(PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT)
@ -299,20 +299,4 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert
memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties)); memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties));
InterfaceObject::initializeProperties(sizeof(allProperties), allProperties); InterfaceObject::initializeProperties(sizeof(allProperties), allProperties);
}
uint16_t TableObject::Crc16Citt(uint8_t* data, uint16_t length)
{
uint16_t initialValue = 0x1D0F;
uint16_t Table[] = {0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF, 0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6, 0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE, 0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485, 0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D, 0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4, 0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC, 0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823, 0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B, 0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12, 0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A, 0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41, 0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49, 0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70, 0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78, 0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F, 0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E, 0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256, 0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D, 0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C, 0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634, 0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB, 0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3, 0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A, 0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92, 0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9, 0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1, 0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8, 0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0};
if (data == nullptr)
return 0;
if (length == 0)
return 0;
uint16_t crc = initialValue;
for (int i = 0; i <= length; i++)
{
crc = (uint16_t)((crc << 8) ^ Table[((crc >> 8) ^ (0xff & data[i]))]);
}
return crc;
} }

View File

@ -47,7 +47,6 @@ class TableObject: public InterfaceObject
void errorCode(ErrorCode errorCode); void errorCode(ErrorCode errorCode);
void initializeProperties(size_t propertiesSize, Property** properties) override; void initializeProperties(size_t propertiesSize, Property** properties) override;
static uint16_t Crc16Citt(uint8_t* data, uint16_t length);
private: private:
uint32_t tableReference(); uint32_t tableReference();
@ -69,5 +68,4 @@ class TableObject: public InterfaceObject
LoadState _state = LS_UNLOADED; LoadState _state = LS_UNLOADED;
Memory& _memory; Memory& _memory;
uint8_t *_data = 0; uint8_t *_data = 0;
uint16_t _crc = 0;
}; };