diff --git a/src/knx/application_program_object.cpp b/src/knx/application_program_object.cpp index e6628d2..598d0fe 100644 --- a/src/knx/application_program_object.cpp +++ b/src/knx/application_program_object.cpp @@ -29,6 +29,29 @@ ApplicationProgramObject::ApplicationProgramObject(Memory& memory) TableObject::initializeProperties(sizeof(properties), properties); } +uint8_t* ApplicationProgramObject::save(uint8_t* buffer) +{ + uint8_t programVersion[5]; + property(PID_PROG_VERSION)->read(programVersion); + buffer = pushByteArray(programVersion, 5, buffer); + + return TableObject::save(buffer); +} + +const uint8_t* ApplicationProgramObject::restore(const uint8_t* buffer) +{ + uint8_t programVersion[5]; + buffer = popByteArray(programVersion, 5, buffer); + property(PID_PROG_VERSION)->write(programVersion); + + return TableObject::restore(buffer); +} + +uint16_t ApplicationProgramObject::saveSize() +{ + return TableObject::saveSize() + 5; // sizeof(programVersion) +} + uint8_t * ApplicationProgramObject::data(uint32_t addr) { return TableObject::data() + addr; diff --git a/src/knx/application_program_object.h b/src/knx/application_program_object.h index 87b743d..c989a1c 100644 --- a/src/knx/application_program_object.h +++ b/src/knx/application_program_object.h @@ -7,6 +7,9 @@ class ApplicationProgramObject : public TableObject { public: ApplicationProgramObject(Memory& memory); + uint8_t* save(uint8_t* buffer) override; + const uint8_t* restore(const uint8_t* buffer) override; + uint16_t saveSize() override; uint8_t* data(uint32_t addr); uint8_t getByte(uint32_t addr); uint16_t getWord(uint32_t addr); diff --git a/src/knx/router_object.cpp b/src/knx/router_object.cpp index 1bc1d5b..b7c7b62 100644 --- a/src/knx/router_object.cpp +++ b/src/knx/router_object.cpp @@ -84,7 +84,6 @@ void RouterObject::initialize(CouplerModel model, uint8_t objIndex, DptMedium me Property* tableProperties[] = { new DataProperty( PID_COUPLER_SERVICES_CONTROL, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint8_t) 0), // written by ETS TODO: implement - new DataProperty( PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0), // TODO: improve: move to TableObject once segment size handling is clear new DataProperty( PID_FILTER_TABLE_USE, true, PDT_BINARY_INFORMATION, 1, ReadLv3 | WriteLv0, (uint16_t) 0 ), // default: invalid filter table, do not use, written by ETS new FunctionProperty(this, PID_ROUTETABLE_CONTROL, // Command Callback of PID_ROUTETABLE_CONTROL @@ -452,27 +451,9 @@ void RouterObject::beforeStateChange(LoadState& newState) if (newState != LS_LOADED) return; - // calculate crc16-ccitt for PID_MCB_TABLE - updateMcb(); - _filterTableGroupAddresses = (uint16_t*)data(); } -void RouterObject::updateMcb() -{ - uint8_t mcb[propertySize(PID_MCB_TABLE)]; - - static constexpr uint32_t segmentSize = kFilterTableSize; - uint16_t crc16 = crc16Ccitt(data(), segmentSize); - - pushInt(segmentSize, &mcb[0]); // Segment size - pushByte(0x00, &mcb[4]); // CRC control byte -> 0: always valid -> according to coupler spec. it shall always be a valid CRC - pushByte(0xFF, &mcb[5]); // Read access 4 bits + Write access 4 bits (unknown: value taken from real coupler device) - pushWord(crc16, &mcb[6]); // CRC-16 CCITT of filter table - - property(PID_MCB_TABLE)->write(mcb); -} - void RouterObject::masterReset(EraseCode eraseCode, uint8_t channel) { if (eraseCode == FactoryReset) diff --git a/src/knx/router_object.h b/src/knx/router_object.h index 22faa56..e43838d 100644 --- a/src/knx/router_object.h +++ b/src/knx/router_object.h @@ -52,8 +52,6 @@ private: void commandClearSetGroupAddress(uint16_t startAddress, uint16_t endAddress, bool bitIsSet); bool statusClearSetGroupAddress(uint16_t startAddress, uint16_t endAddress, bool bitIsSet); - void updateMcb(); - bool _rfSbcRoutingEnabled = false; bool _ipSbcRoutingEnabled = false; uint16_t* _filterTableGroupAddresses = 0; diff --git a/src/knx/table_object.cpp b/src/knx/table_object.cpp index d1be31c..909337a 100644 --- a/src/knx/table_object.cpp +++ b/src/knx/table_object.cpp @@ -31,6 +31,8 @@ uint8_t* TableObject::save(uint8_t* buffer) { buffer = pushByte(_state, buffer); + buffer = pushInt(_size, buffer); + if (_data) buffer = pushInt(_memory.toRelative(_data), buffer); else @@ -46,6 +48,8 @@ const uint8_t* TableObject::restore(const uint8_t* buffer) buffer = popByte(state, buffer); _state = (LoadState)state; + buffer = popInt(_size, buffer); + uint32_t relativeAddress = 0; buffer = popInt(relativeAddress, buffer); @@ -80,6 +84,8 @@ bool TableObject::allocTable(uint32_t size, bool doFill, uint8_t fillByte) if (doFill) memset(_data, fillByte, size); + _size = size; + return true; } @@ -229,7 +235,7 @@ void TableObject::errorCode(ErrorCode errorCode) uint16_t TableObject::saveSize() { - return 5 + InterfaceObject::saveSize(); + return 5 + InterfaceObject::saveSize() + sizeof(_size); } void TableObject::initializeProperties(size_t propertiesSize, Property** properties) @@ -267,6 +273,21 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert pushInt(obj->tableReference(), data); return 1; }), + new CallbackProperty(this, PID_MCB_TABLE, false, PDT_GENERIC_08, 1, ReadLv3 | WriteLv0, + [](TableObject* obj, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t { + if (obj->_state != LS_LOADED) + return 0; // need to check return code for invalid + + uint32_t segmentSize = obj->_size; + uint16_t crc16 = crc16Ccitt(obj->data(), segmentSize); + + 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 + pushWord(crc16, data + 6); // CRC-16 CCITT of data + + return 1; + }), new DataProperty(PID_ERROR_CODE, false, PDT_ENUM8, 1, ReadLv3 | WriteLv0, (uint8_t)E_NO_FAULT) }; //TODO: missing @@ -284,4 +305,4 @@ void TableObject::initializeProperties(size_t propertiesSize, Property** propert memcpy(allProperties + propertyCount, ownProperties, sizeof(ownProperties)); InterfaceObject::initializeProperties(sizeof(allProperties), allProperties); -} +} \ No newline at end of file diff --git a/src/knx/table_object.h b/src/knx/table_object.h index fc487e9..c4213b3 100644 --- a/src/knx/table_object.h +++ b/src/knx/table_object.h @@ -28,7 +28,7 @@ class TableObject: public InterfaceObject uint8_t* save(uint8_t* buffer) override; const uint8_t* restore(const uint8_t* buffer) override; uint16_t saveSize() override; -protected: + protected: /** * This method is called before the interface object enters a new ::LoadState. * If there is a error changing the state newState should be set to ::LS_ERROR and errorCode() @@ -47,7 +47,7 @@ protected: void errorCode(ErrorCode errorCode); void initializeProperties(size_t propertiesSize, Property** properties) override; - + private: uint32_t tableReference(); bool allocTable(uint32_t size, bool doFill, uint8_t fillByte); @@ -68,4 +68,11 @@ protected: LoadState _state = LS_UNLOADED; Memory& _memory; uint8_t *_data = 0; + + /** + * used to store size of data() in allocTable(), needed for calculation of crc in PID_MCB_TABLE. + * This value is also saved and restored. + * The size of the memory block cannot be used because it is changed during alignment to page size. + */ + uint32_t _size = 0; };