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" - ] -} 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(); 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 07ab432..ae9fded 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -60,6 +60,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 @@ -138,11 +140,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(")"); @@ -294,7 +296,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"); @@ -412,8 +420,8 @@ void TpUartDataLinkLayer::processRxFrameByte(uint8_t byte) // Of course, this is only allowed if I am not sending myself, as you cannot ACK your own frames if (_txState == TX_IDLE) { - // Save that tracking should take place - _rxFrame->addFlags(TP_FRAME_FLAG_ACKING); + // Save that Acking should take place + _rxFrame->addFlags(TP_FRAME_FLAG_ACK); // and in the TPUart so that it can send the ACK _platform.writeUart(U_ACK_REQ | U_ACK_REQ_ADRESSED); @@ -468,8 +476,8 @@ void TpUartDataLinkLayer::processRxFrameComplete() // When a frame has been sent if (_txState == TX_FRAME) { - // check whether the reception corresponds to this - if (!memcmp(_rxFrame->data(), _txFrame->data(), _txFrame->size())) + // check whether the receive corresponds to this: comparison of the source address and destination address and start byte without taking the retry bit into account + if(!((_rxFrame->data(0) ^ _txFrame->data(0)) & ~0x20) && _rxFrame->destination() == _txFrame->destination() && _rxFrame->source() == _txFrame->source()) { // and mark this accordingly // println("MATCH"); @@ -563,7 +571,6 @@ void TpUartDataLinkLayer::pushTxFrameQueue(TpFrame *tpFrame) } _txQueueCount++; - _txFrameCounter++; } void TpUartDataLinkLayer::setRepetitions(uint8_t nack, uint8_t busy) @@ -579,12 +586,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; } @@ -691,6 +701,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"); @@ -704,11 +725,7 @@ bool TpUartDataLinkLayer::reset() isrLock(true); // Reset - _rxIgnoredFrameCounter = 0; - _rxInvalidFrameCounter = 0; - _rxInvalidFrameCounter = 0; - _rxUnkownControlCounter = 0; - + resetStats(); clearTxFrame(); clearTxFrameQueue(); @@ -791,6 +808,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(); 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); diff --git a/src/rp2040_arduino_platform.cpp b/src/rp2040_arduino_platform.cpp index ffd2cb0..ad88b43 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);