From 2adac5e4afbc3f54dda821e856822d7f61631ccb Mon Sep 17 00:00:00 2001 From: Marco Scholl Date: Thu, 23 May 2024 09:35:07 +0200 Subject: [PATCH 1/8] fix: resets stats --- src/knx/tpuart_data_link_layer.cpp | 22 ++++++++++++++++------ src/knx/tpuart_data_link_layer.h | 1 + 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index e74df73..67e9e25 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -564,7 +564,6 @@ void TpUartDataLinkLayer::pushTxFrameQueue(TpFrame *tpFrame) } _txQueueCount++; - _txFrameCounter++; } void TpUartDataLinkLayer::setRepetitions(uint8_t nack, uint8_t busy) @@ -580,12 +579,15 @@ void TpUartDataLinkLayer::setFrameRepetition(uint8_t nack, uint8_t busy) bool TpUartDataLinkLayer::sendFrame(CemiFrame &cemiFrame) { + _txFrameCounter++; + if (!_connected || _monitoring || _txQueueCount > MAX_TX_QUEUE) { if (_txQueueCount > MAX_TX_QUEUE) { println("Ignore frame because transmit queue is full!"); } + dataConReceived(cemiFrame, false); return false; } @@ -692,6 +694,17 @@ void TpUartDataLinkLayer::connected(bool state /* = true */) _connected = state; } +void TpUartDataLinkLayer::resetStats() +{ + _rxProcessdFrameCounter = 0; + _rxIgnoredFrameCounter = 0; + _rxInvalidFrameCounter = 0; + _rxInvalidFrameCounter = 0; + _rxUnkownControlCounter = 0; + _txFrameCounter = 0; + _txProcessdFrameCounter = 0; +} + bool TpUartDataLinkLayer::reset() { // println("Reset TP"); @@ -705,11 +718,7 @@ bool TpUartDataLinkLayer::reset() isrLock(true); // Reset - _rxIgnoredFrameCounter = 0; - _rxInvalidFrameCounter = 0; - _rxInvalidFrameCounter = 0; - _rxUnkownControlCounter = 0; - + resetStats(); clearTxFrame(); clearTxFrameQueue(); @@ -792,6 +801,7 @@ void TpUartDataLinkLayer::monitor() // println("busmonitor"); _monitoring = true; _platform.writeUart(U_BUSMON_REQ); + resetStats(); } void TpUartDataLinkLayer::enabled(bool value) diff --git a/src/knx/tpuart_data_link_layer.h b/src/knx/tpuart_data_link_layer.h index 729e7be..7dd0d55 100644 --- a/src/knx/tpuart_data_link_layer.h +++ b/src/knx/tpuart_data_link_layer.h @@ -57,6 +57,7 @@ class TpUartDataLinkLayer : public DataLinkLayer bool isMonitoring(); bool isStopped(); bool isBusy(); + void resetStats(); #ifdef USE_TP_RX_QUEUE void processRxISR(); From a645575a72fe04d18b6657ca7ceca6a1dbee5ce0 Mon Sep 17 00:00:00 2001 From: Marco Scholl Date: Thu, 23 May 2024 15:38:31 +0200 Subject: [PATCH 2/8] support detect acks with busy + nack and show in monitoring --- src/knx/tp_frame.h | 13 ++++++++----- src/knx/tpuart_data_link_layer.cpp | 22 +++++++++++++++------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/knx/tp_frame.h b/src/knx/tp_frame.h index a7475c5..cd900a6 100644 --- a/src/knx/tp_frame.h +++ b/src/knx/tp_frame.h @@ -19,13 +19,16 @@ #define TP_FRAME_FLAG_ECHO 0b00010000 // Means that the frame is processed by this device -#define TP_FRAME_FLAG_ADDRESSED 0b00000100 +#define TP_FRAME_FLAG_ADDRESSED 0b00001000 -// Means that the frame has been acked by this device. -#define TP_FRAME_FLAG_ACKING 0b00000010 +// Means that the frame has been acked with BUSY +#define TP_FRAME_FLAG_ACK_BUSY 0b00000100 -// Means that the frame has been acked by other (Busmontior) -#define TP_FRAME_FLAG_ACKED 0b00000001 +// Means that the frame has been acked with NACK +#define TP_FRAME_FLAG_ACK_NACK 0b00000010 + +// Means that the frame has been acked +#define TP_FRAME_FLAG_ACK 0b00000001 class TpFrame { diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index 67e9e25..a011454 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -61,6 +61,8 @@ // acknowledge services (device is transparent in bus monitor mode) #define L_ACKN_IND 0x00 #define L_ACKN_MASK 0x33 +#define L_ACKN_BUSY_MASK 0x0C +#define L_ACKN_NACK_MASK 0xC0 #define L_DATA_CON 0x0B #define L_DATA_CON_MASK 0x7F #define SUCCESS 0x80 @@ -139,11 +141,11 @@ void printFrame(TpFrame *tpframe) print((tpframe->flags() & TP_FRAME_FLAG_INVALID) ? 'I' : '_'); // Invalid print((tpframe->flags() & TP_FRAME_FLAG_EXTENDED) ? 'E' : '_'); // Extended print((tpframe->flags() & TP_FRAME_FLAG_REPEATED) ? 'R' : '_'); // Repeat - print((tpframe->flags() & TP_FRAME_FLAG_ECHO) ? 'O' : '_'); // My own - print((tpframe->flags() & 0b00001000) ? 'x' : '_'); // Reserve - print((tpframe->flags() & TP_FRAME_FLAG_ADDRESSED) ? 'D' : '_'); // For me - print((tpframe->flags() & TP_FRAME_FLAG_ACKING) ? 'A' : '_'); // ACK recevied - print((tpframe->flags() & TP_FRAME_FLAG_ACKED) ? 'A' : '_'); // ACK sent + print((tpframe->flags() & TP_FRAME_FLAG_ECHO) ? 'T' : '_'); // Send by me + print((tpframe->flags() & TP_FRAME_FLAG_ADDRESSED) ? 'D' : '_'); // Recv for me + print((tpframe->flags() & TP_FRAME_FLAG_ACK_NACK) ? 'N' : '_'); // ACK + NACK + print((tpframe->flags() & TP_FRAME_FLAG_ACK_BUSY) ? 'B' : '_'); // ACK + BUSY + print((tpframe->flags() & TP_FRAME_FLAG_ACK) ? 'A' : '_'); // ACK print("] "); printHex("( ", tpframe->data(), tpframe->size(), false); print(")"); @@ -295,7 +297,13 @@ void TpUartDataLinkLayer::processRxByte() */ if (_rxFrame->size() > 0) { - _rxFrame->addFlags(TP_FRAME_FLAG_ACKED); + if (!(byte & L_ACKN_BUSY_MASK)) + _rxFrame->addFlags(TP_FRAME_FLAG_ACK_BUSY); + + if (!(byte & L_ACKN_NACK_MASK)) + _rxFrame->addFlags(TP_FRAME_FLAG_ACK_NACK); + + _rxFrame->addFlags(TP_FRAME_FLAG_ACK); processRxFrameComplete(); } // println("L_ACKN_IND"); @@ -414,7 +422,7 @@ void TpUartDataLinkLayer::processRxFrameByte(uint8_t byte) if (_txState == TX_IDLE) { // Speichere das ein Acking erfolgen soll - _rxFrame->addFlags(TP_FRAME_FLAG_ACKING); + _rxFrame->addFlags(TP_FRAME_FLAG_ACK); // und im TPUart damit dieser das ACK schicken kann _platform.writeUart(U_ACK_REQ | U_ACK_REQ_ADRESSED); From 6eb7af74a0d54663d2d14b34bacab8bd106d1ca8 Mon Sep 17 00:00:00 2001 From: Ing-Dom Date: Sun, 2 Jun 2024 23:45:54 +0200 Subject: [PATCH 3/8] flag also repeated telegrams as echoed / own telegrams --- src/knx/tpuart_data_link_layer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index a011454..627daf0 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -477,8 +477,8 @@ void TpUartDataLinkLayer::processRxFrameComplete() // Wenn ein Frame gesendet wurde if (_txState == TX_FRAME) { - // prüfe ob das Empfangen diesem entspricht - if (!memcmp(_rxFrame->data(), _txFrame->data(), _txFrame->size())) + // prüfe ob das Empfangen diesem entspricht: Vergleich der Quelladresse und Zieladresse sowie Startbyte ohne Berücksichtigung des Retry-Bits + if(!((_rxFrame->data(0) ^ _txFrame->data(0)) & ~0x20) && _rxFrame->destination() == _txFrame->destination() && _rxFrame->source() == _txFrame->source()) { // und markiere das entsprechend // println("MATCH"); From 4f0e47f809ebcc535652b01f7e60798f96f1b336 Mon Sep 17 00:00:00 2001 From: Marco Scholl Date: Mon, 3 Jun 2024 10:36:39 +0200 Subject: [PATCH 4/8] drop unexpected udp data packet length --- src/rp2040_arduino_platform.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/rp2040_arduino_platform.cpp b/src/rp2040_arduino_platform.cpp index 691d768..96c13c9 100644 --- a/src/rp2040_arduino_platform.cpp +++ b/src/rp2040_arduino_platform.cpp @@ -517,11 +517,10 @@ int RP2040ArduinoPlatform::readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) if (len > maxLen) { - print("udp buffer to small. was "); - print(maxLen); - print(", needed "); - println(len); - fatalError(); + println("Unexpected UDP data packet length - drop packet"); + for (size_t i = 0; i < len; i++) + _udp.read(); + return 0; } _udp.read(buffer, len); From acf4a0b6e4d2a0b713c7661fd2f203828223b4c3 Mon Sep 17 00:00:00 2001 From: Mike <45664417+thewhobox@users.noreply.github.com> Date: Mon, 3 Jun 2024 13:03:41 +0200 Subject: [PATCH 5/8] remove annoying file --- .vscode/extensions.json | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 080e70d..0000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - // See http://go.microsoft.com/fwlink/?LinkId=827846 - // for the documentation about the extensions.json format - "recommendations": [ - "platformio.platformio-ide" - ], - "unwantedRecommendations": [ - "ms-vscode.cpptools-extension-pack" - ] -} From e69f63611a27eac41d48c8fa1d5a0e1e8755374d Mon Sep 17 00:00:00 2001 From: Ing-Dom Date: Wed, 3 Jul 2024 11:27:25 +0200 Subject: [PATCH 6/8] Release V2.1.0 --- README.md | 57 ++++++++++++---------------------------------- library.json | 23 +++++++++++++++++++ library.properties | 4 ++-- 3 files changed, 40 insertions(+), 44 deletions(-) create mode 100644 library.json diff --git a/README.md b/README.md index 953cfa8..8f84371 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,26 @@ # knx +This is a fork of the thelsing/knx stack from Thomas Kunze for and by the OpenKNX Team. + +While we did not remove support for any plattform, the testing focus is on RP2040 (main), ESP32 (experimental) and SAMD21(deprecated). + This projects provides a knx-device stack for arduino (ESP8266, ESP32, SAMD21, RP2040, STM32), CC1310 and linux. (more are quite easy to add) It implements most of System-B specification and can be configured with ETS. The necessary knxprod-files can be generated with the [Kaenx-Creator](https://github.com/OpenKNX/Kaenx-Creator) tool. -For ESP8266 and ESP32 [WifiManager](https://github.com/tzapu/WiFiManager) is used to configure wifi. -Don't forget to reset ESP8266 manually (disconnect power) after flashing. The reboot doen't work during configuration with ETS otherwise. +## Usage +See the examples for basic usage options -Generated documentation can be found [here](https://knx.readthedocs.io/en/latest/). -## Stack configuration possibilities +## Changelog -Specify prog button GPIO other then `GPIO0`: -```C++ -knx.buttonPin(3); // Use GPIO3 Pin -``` +### V2.1.0 - 2024-07-03 +- complete rework of the TPUart DataLinkLayer with support interrupt-based handling and optimized queue handling +- added DMA support for RP2040 platform +- fix some issues with continous integration causing github actions to fail +- added rp2040 plattform to knx-demo example +- added bool GroupObject::valueCompare method for only sending the value when it has changed -Specify a LED GPIO for programming mode other then the `LED_BUILTIN`: -```C++ -knx.ledPin(5); -``` - -Use a custom function instead of a LED connected to GPIO to indicate the programming mode: -```C++ -#include -#include -#include -// create a pixel strand with 1 pixel on PIN_NEOPIXEL -Adafruit_NeoPixel pixels(1, PIN_NEOPIXEL); - -void progLedOff() -{ - pixels.clear(); - pixels.show(); -} - -void progLedOn() -{ - pixels.setPixelColor(0, pixels.Color(20, 0, 0)); - pixels.show(); -} - -void main () -{ - knx.setProgLedOffCallback(progLedOff); - knx.setProgLedOnCallback(progLedOn); - [...] -} -``` - -More configuration options can be found in the examples. +### V2.0.0 - 2024-02-13 +- first OpenKNX version \ No newline at end of file diff --git a/library.json b/library.json new file mode 100644 index 0000000..a8ff4f3 --- /dev/null +++ b/library.json @@ -0,0 +1,23 @@ +{ + "name": "knx", + "version": "2.1.0", + "dependencies": { + }, + "description": "knx stack", + "homepage": "https://openknx.de", + "authors": [ + { + "name": "Thomas Kunze" + }, + { + "name": "OpenKNX", + "email": "info@openknx.de", + "url": "https://openknx.de", + "maintainer": true + } + ], + "repository": { + "type": "git", + "url": "https://github.com/OpenKNX/knx" + } +} \ No newline at end of file diff --git a/library.properties b/library.properties index 980e8ea..8a6dcf8 100644 --- a/library.properties +++ b/library.properties @@ -1,6 +1,6 @@ name=knx -version=2.0.0 -author=Thomas Kunze et al. +version=2.1.0 +author=Thomas Kunze, the OpenKNX Team, et. al. maintainer=OpenKNX Team sentence=knx stack paragraph= From 12fb67cc63df03ddafedfd7759eaf0e51ac92abd Mon Sep 17 00:00:00 2001 From: Ing-Dom Date: Wed, 17 Jul 2024 22:22:58 +0200 Subject: [PATCH 7/8] fix: only set pinMode of Prog button pin when pin is >= 0 and isr function is defined otherwise it is useless anyway and causes warnings. --- src/knx_facade.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx_facade.h b/src/knx_facade.h index 75d8fdb..3f1c60b 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -286,10 +286,10 @@ template class KnxFacade : private SaveRestore pinMode(ledPin(), OUTPUT); progLedOff(); - pinMode(buttonPin(), INPUT_PULLUP); - + if (_progButtonISRFuncPtr && _buttonPin >= 0) { + pinMode(buttonPin(), INPUT_PULLUP); // Workaround for https://github.com/arduino/ArduinoCore-samd/issues/587 #if (ARDUINO_API_VERSION >= 10200) attachInterrupt(_buttonPin, _progButtonISRFuncPtr, (PinStatus)CHANGE); From 093ae425b0040796e742ad8f74b8155b988fe4bd Mon Sep 17 00:00:00 2001 From: Michael Geramb Date: Sat, 20 Jul 2024 16:27:47 +0200 Subject: [PATCH 8/8] String \0 terminated in group objects (#25) * String \0 terminated in group objects * Remove copy constructor, fix bugs in setting buffer to 0 * Remove copy constructor in GroupObject --- src/knx/dptconvert.cpp | 8 +++----- src/knx/group_object.cpp | 27 +++++++++++++-------------- src/knx/group_object.h | 11 ++++++----- src/knx/group_object_table_object.cpp | 7 ++++--- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index 1954d2d..9f05fb2 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -517,15 +517,13 @@ int busValueToAccess(const uint8_t* payload, size_t payload_length, const Dpt& d int busValueToString(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value) { ASSERT_PAYLOAD(14); - char strValue[15]; - strValue[14] = '\0'; for (int n = 0; n < 14; ++n) { - strValue[n] = signed8FromPayload(payload, n); - if (!datatype.subGroup && (strValue[n] & 0x80)) + auto value = signed8FromPayload(payload, n); + if (!datatype.subGroup && (value & 0x80)) return false; } - value = strValue; + value = (const char*) payload; return true; } diff --git a/src/knx/group_object.cpp b/src/knx/group_object.cpp index 5a9ad28..7b172d5 100644 --- a/src/knx/group_object.cpp +++ b/src/knx/group_object.cpp @@ -20,18 +20,6 @@ GroupObject::GroupObject() #endif } -GroupObject::GroupObject(const GroupObject& other) -{ - _data = new uint8_t[other._dataLength]; - _commFlagEx = other._commFlagEx; - _dataLength = other._dataLength; - _asap = other._asap; -#ifndef SMALL_GROUPOBJECT - _updateHandler = other._updateHandler; -#endif - memcpy(_data, other._data, _dataLength); -} - GroupObject::~GroupObject() { if (_data) @@ -114,12 +102,12 @@ size_t GroupObject::goSize() size_t size = sizeInTelegram(); if (size == 0) return 1; - + return size; } // see knxspec 3.5.1 p. 178 -size_t GroupObject::asapValueSize(uint8_t code) +size_t GroupObject::asapValueSize(uint8_t code) const { if (code < 7) return 0; @@ -194,6 +182,17 @@ size_t GroupObject::sizeInTelegram() return asapValueSize(code); } +size_t GroupObject::sizeInMemory() const +{ + uint8_t code = lowByte(ntohs(_table->_tableData[_asap])); + size_t result = asapValueSize(code); + if (code == 0) + return 1; + if (code == 14) + return 14 + 1; + return result; +} + #ifdef SMALL_GROUPOBJECT GroupObjectUpdatedHandler GroupObject::classCallback() { diff --git a/src/knx/group_object.h b/src/knx/group_object.h index 02bd0c3..244fab6 100644 --- a/src/knx/group_object.h +++ b/src/knx/group_object.h @@ -57,10 +57,6 @@ class GroupObject * The constructor. */ GroupObject(); - /** - * The copy constructor. - */ - GroupObject(const GroupObject& other); /** * The destructor. */ @@ -139,6 +135,11 @@ class GroupObject * will return 0. */ size_t sizeInTelegram(); + /** + * returns the size of the group object in the heap memory of the group object. The function returns the same value as goSize(), + * exept fot the 14 byte string type to reserve one byte of a \0 terminator character. + */ + size_t sizeInMemory() const; /** * returns the pointer to the value of the group object. This can be used if a datapoint type is not supported or if you want do * your own conversion. @@ -274,7 +275,7 @@ class GroupObject static GroupObjectUpdatedHandler _updateHandlerStatic; #endif - size_t asapValueSize(uint8_t code); + size_t asapValueSize(uint8_t code) const; size_t goSize(); uint16_t _asap = 0; ComFlagEx _commFlagEx; diff --git a/src/knx/group_object_table_object.cpp b/src/knx/group_object_table_object.cpp index bdcf8dd..8d931ce 100644 --- a/src/knx/group_object_table_object.cpp +++ b/src/knx/group_object_table_object.cpp @@ -107,10 +107,11 @@ bool GroupObjectTableObject::initGroupObjects() GroupObject& go = _groupObjects[asap - 1]; go._asap = asap; go._table = this; - + go._dataLength = go.goSize(); - go._data = new uint8_t[go._dataLength]; - memset(go._data, 0, go._dataLength); + size_t sizeInMemory = go.sizeInMemory(); + go._data = new uint8_t[sizeInMemory]; + memset(go._data, 0, sizeInMemory); if (go.valueReadOnInit()) go.requestObjectRead();