diff --git a/knx-linux/CMakeLists.txt b/knx-linux/CMakeLists.txt index ee4e468..553d5c0 100644 --- a/knx-linux/CMakeLists.txt +++ b/knx-linux/CMakeLists.txt @@ -24,10 +24,14 @@ add_executable(knx-linux ../src/knx/bau_systemB.h ../src/knx/bits.cpp ../src/knx/bits.h + ../src/knx/callback_property.cpp + ../src/knx/callback_property.h ../src/knx/cemi_frame.cpp ../src/knx/cemi_frame.h ../src/knx/data_link_layer.cpp ../src/knx/data_link_layer.h + ../src/knx/data_property.cpp + ../src/knx/data_property.h ../src/knx/device_object.cpp ../src/knx/device_object.h ../src/knx/dpt.cpp @@ -60,6 +64,8 @@ add_executable(knx-linux ../src/knx/rf_medium_object.h ../src/knx/rf_physical_layer.cpp ../src/knx/rf_physical_layer.h + ../src/knx/property.cpp + ../src/knx/property.h ../src/knx/table_object.cpp ../src/knx/table_object.h ../src/knx/tpdu.cpp diff --git a/knx-linux/knx-linux.vcxproj b/knx-linux/knx-linux.vcxproj index b2cdfb6..2b8de26 100644 --- a/knx-linux/knx-linux.vcxproj +++ b/knx-linux/knx-linux.vcxproj @@ -82,11 +82,13 @@ + + @@ -134,11 +136,13 @@ + + @@ -153,6 +157,7 @@ + diff --git a/knx-linux/knx-linux.vcxproj.filters b/knx-linux/knx-linux.vcxproj.filters index 5cd6a8b..9666012 100644 --- a/knx-linux/knx-linux.vcxproj.filters +++ b/knx-linux/knx-linux.vcxproj.filters @@ -164,6 +164,12 @@ Header files\knx + + Header files\knx + + + Header files\knx + @@ -289,5 +295,14 @@ Source files\knx + + Source files\knx + + + Source files\knx + + + Source files\knx + \ No newline at end of file diff --git a/src/knx/callback_property.cpp b/src/knx/callback_property.cpp new file mode 100644 index 0000000..12737d8 --- /dev/null +++ b/src/knx/callback_property.cpp @@ -0,0 +1,23 @@ +#include "callback_property.h" + +CallbackProperty::CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type, + uint16_t maxElements, uint8_t access, + PropertyCallback readCallback, PropertyCallback writeCallback) + : Property(id, writeEnable, type, maxElements, access), _readCallback(), _writeCallback() +{} + +uint8_t CallbackProperty::read(uint16_t start, uint8_t count, uint8_t* data) +{ + if (count == 0 || _readCallback == nullptr) + return 0; + + return _readCallback(start, count, data); +} + +uint8_t CallbackProperty::write(uint16_t start, uint8_t count, uint8_t* data) +{ + if (count == 0 || start > _maxElements || !_writeEnable || start + count > _maxElements + 1 + || _writeCallback == nullptr) + return 0; + return _writeCallback(start, count, data); +} diff --git a/src/knx/callback_property.h b/src/knx/callback_property.h new file mode 100644 index 0000000..4119aac --- /dev/null +++ b/src/knx/callback_property.h @@ -0,0 +1,17 @@ +#pragma once + +#include "property.h" + +typedef uint8_t (*PropertyCallback)(uint16_t start, uint8_t count, uint8_t* data); + +class CallbackProperty : public Property +{ + public: + CallbackProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, + uint8_t access, PropertyCallback readCallback, PropertyCallback writeCallback); + virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override; + virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override; + private: + PropertyCallback _readCallback = nullptr; + PropertyCallback _writeCallback = nullptr; +}; diff --git a/src/knx/data_property.cpp b/src/knx/data_property.cpp new file mode 100644 index 0000000..62fcc34 --- /dev/null +++ b/src/knx/data_property.cpp @@ -0,0 +1,83 @@ +#include "data_property.h" +#include "bits.h" + +#include + +uint8_t DataProperty::read(uint16_t start, uint8_t count, uint8_t* data) +{ + if (count == 0 || _currentElements == 0 || start > _currentElements || count > _currentElements - start + 1) + return 0; + + if (start == 0) + { + pushWord(_currentElements, data); + return 1; + } + + // we start counting with zero + start -= 1; + + // data is already big enough to hold the data + memcpy(data, _data + start, count * ElementSize()); + + return count; +} + +uint8_t DataProperty::write(uint16_t start, uint8_t count, uint8_t* data) +{ + if (count == 0 || start > _maxElements || !_writeEnable || start + count > _maxElements + 1) + return 0; + + if (start == 0) + { + if (count == 1 && data[0] == 0 && data[1] == 0) + { + // reset _data + _currentElements = 0; + if (_data) + { + delete[] _data; + _data = nullptr; + } + return 1; + } + else + return 0; + } + + // we start counting with zero + start -= 1; + if (start + count > _currentElements) + { + //reallocate memory for _data + uint8_t* oldData = _data; + size_t oldDataSize = _currentElements * ElementSize(); + + size_t newDataSize = (start + count) * ElementSize(); + _data = new uint8_t[newDataSize]; + memset(_data, 0, newDataSize); + + if (oldData != nullptr) + { + memcpy(_data, oldData, oldDataSize); + delete[] oldData; + } + + _currentElements = start + count; + } + + memcpy(_data + start, data, count * ElementSize()); + + return count; +} + +DataProperty::DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, + uint16_t maxElements, uint8_t access) + : Property(id, writeEnable, type, maxElements, access) +{} + +DataProperty::~DataProperty() +{ + if (_data) + delete[] _data; +} diff --git a/src/knx/data_property.h b/src/knx/data_property.h new file mode 100644 index 0000000..f952fc7 --- /dev/null +++ b/src/knx/data_property.h @@ -0,0 +1,15 @@ +#pragma once + +#include "property.h" + +class DataProperty : public Property +{ + public: + DataProperty(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access); + virtual ~DataProperty() override; + virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) override; + virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) override; + private: + uint16_t _currentElements = 0; + uint8_t* _data = nullptr; +}; diff --git a/src/knx/property.cpp b/src/knx/property.cpp new file mode 100644 index 0000000..f72cd63 --- /dev/null +++ b/src/knx/property.cpp @@ -0,0 +1,113 @@ +#include "property.h" +#include "bits.h" + +#include + +PropertyID Property::Id() +{ + return _id; +} + +bool Property::WriteEnable() +{ + return _writeEnable; +} + +PropertyDataType Property::Type() +{ + return _type; +} + +uint16_t Property::MaxElements() +{ + return _maxElements; +} + +uint8_t Property::Access() +{ + return _access; +} + +uint8_t Property::ElementSize() +{ + switch (_type) + { + case PDT_CHAR: + case PDT_CONTROL: // is actually 10 if written, but this is always handled with a callback + case PDT_GENERIC_01: + case PDT_UNSIGNED_CHAR: + return 1; + case PDT_GENERIC_02: + case PDT_INT: + case PDT_KNX_FLOAT: + case PDT_UNSIGNED_INT: + return 2; + case PDT_ALARM_INFO: + case PDT_BINARY_INFORMATION: + case PDT_BITSET16: + case PDT_BITSET8: + case PDT_DATE: + case PDT_ENUM8: + case PDT_ESCAPE: + case PDT_FUNCTION: + case PDT_GENERIC_03: + case PDT_NE_FL: + case PDT_NE_VL: + case PDT_POLL_GROUP_SETTING: + case PDT_SCALING: + case PDT_TIME: + case PDT_UTF8: + case PDT_VERSION: + return 3; + case PDT_FLOAT: + case PDT_GENERIC_04: + case PDT_LONG: + case PDT_UNSIGNED_LONG: + return 4; + case PDT_GENERIC_05: + case PDT_SHORT_CHAR_BLOCK: + return 5; + case PDT_GENERIC_06: + return 6; + case PDT_GENERIC_07: + return 7; + case PDT_DATE_TIME: + case PDT_DOUBLE: + case PDT_GENERIC_08: + return 8; + case PDT_GENERIC_09: + return 9; + case PDT_CHAR_BLOCK: + case PDT_GENERIC_10: + return 10; + case PDT_GENERIC_11: + return 11; + case PDT_GENERIC_12: + return 12; + case PDT_GENERIC_13: + return 13; + case PDT_GENERIC_14: + return 14; + case PDT_GENERIC_15: + return 15; + case PDT_GENERIC_16: + return 16; + case PDT_GENERIC_17: + return 17; + case PDT_GENERIC_18: + return 18; + case PDT_GENERIC_19: + return 19; + case PDT_GENERIC_20: + return 20; + } + return 0; +} + +Property::Property(PropertyID id, bool writeEnable, PropertyDataType type, + uint16_t maxElements, uint8_t access) + : _id(id), _writeEnable(writeEnable), _type(type), _maxElements(maxElements), _access(access) +{} + +Property::~Property() +{} diff --git a/src/knx/property.h b/src/knx/property.h index 402ae66..aa4b4ef 100644 --- a/src/knx/property.h +++ b/src/knx/property.h @@ -224,15 +224,25 @@ struct PropertyDescription uint8_t Access; }; +typedef uint8_t (*PropertyCallback)(uint16_t start, uint8_t count, uint8_t* data); + class Property { public: + Property(PropertyID id, bool writeEnable, PropertyDataType type, uint16_t maxElements, uint8_t access); + virtual ~Property(); PropertyID Id(); bool WriteEnable(); PropertyDataType Type(); uint16_t MaxElements(); uint8_t Access(); - uint16_t CurrentElements(); uint8_t ElementSize(); - void read(uint32_t start, uint32_t& count, uint8_t* data); + virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) = 0; + virtual uint8_t write(uint16_t start, uint8_t count, uint8_t* data) = 0; + protected: + PropertyID _id; + bool _writeEnable; + PropertyDataType _type; + uint16_t _maxElements; + uint8_t _access; }; \ No newline at end of file diff --git a/src/knx_facade.h b/src/knx_facade.h index 0fed8e9..5b26981 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -26,7 +26,7 @@ #endif void buttonUp(); -typedef uint8_t* (*saveRestoreCallback)(uint8_t* buffer); +typedef uint8_t* (*SaveRestoreCallback)(uint8_t* buffer); template class KnxFacade : private SaveRestore { @@ -221,12 +221,12 @@ template class KnxFacade : private SaveRestore enabled(true); } - void setSaveCallback(saveRestoreCallback func) + void setSaveCallback(SaveRestoreCallback func) { _saveCallback = func; } - void setRestoreCallback(saveRestoreCallback func) + void setRestoreCallback(SaveRestoreCallback func) { _restoreCallback = func; } @@ -281,8 +281,8 @@ template class KnxFacade : private SaveRestore uint32_t _ledPin = LED_BUILTIN; uint32_t _buttonPinInterruptOn = RISING; uint32_t _buttonPin = 0; - saveRestoreCallback _saveCallback = 0; - saveRestoreCallback _restoreCallback = 0; + SaveRestoreCallback _saveCallback = 0; + SaveRestoreCallback _restoreCallback = 0; bool _toogleProgMode = false; bool _progLedState = false; uint16_t _saveSize = 0;