Merge commit '093ae42' into openknx-merge

This commit is contained in:
Thomas Kunze 2024-08-09 20:14:40 +02:00
commit 5ddbff2d16
10 changed files with 75 additions and 65 deletions

View File

@ -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"
]
}

View File

@ -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) int busValueToString(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value)
{ {
ASSERT_PAYLOAD(14); ASSERT_PAYLOAD(14);
char strValue[15];
strValue[14] = '\0';
for (int n = 0; n < 14; ++n) for (int n = 0; n < 14; ++n)
{ {
strValue[n] = signed8FromPayload(payload, n); auto value = signed8FromPayload(payload, n);
if (!datatype.subGroup && (strValue[n] & 0x80)) if (!datatype.subGroup && (value & 0x80))
return false; return false;
} }
value = strValue; value = (const char*) payload;
return true; return true;
} }

View File

@ -20,18 +20,6 @@ GroupObject::GroupObject()
#endif #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() GroupObject::~GroupObject()
{ {
if (_data) if (_data)
@ -114,12 +102,12 @@ size_t GroupObject::goSize()
size_t size = sizeInTelegram(); size_t size = sizeInTelegram();
if (size == 0) if (size == 0)
return 1; return 1;
return size; return size;
} }
// see knxspec 3.5.1 p. 178 // 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) if (code < 7)
return 0; return 0;
@ -194,6 +182,17 @@ size_t GroupObject::sizeInTelegram()
return asapValueSize(code); 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 #ifdef SMALL_GROUPOBJECT
GroupObjectUpdatedHandler GroupObject::classCallback() GroupObjectUpdatedHandler GroupObject::classCallback()
{ {

View File

@ -57,10 +57,6 @@ class GroupObject
* The constructor. * The constructor.
*/ */
GroupObject(); GroupObject();
/**
* The copy constructor.
*/
GroupObject(const GroupObject& other);
/** /**
* The destructor. * The destructor.
*/ */
@ -139,6 +135,11 @@ class GroupObject
* will return 0. * will return 0.
*/ */
size_t sizeInTelegram(); 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 * 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. * your own conversion.
@ -274,7 +275,7 @@ class GroupObject
static GroupObjectUpdatedHandler _updateHandlerStatic; static GroupObjectUpdatedHandler _updateHandlerStatic;
#endif #endif
size_t asapValueSize(uint8_t code); size_t asapValueSize(uint8_t code) const;
size_t goSize(); size_t goSize();
uint16_t _asap = 0; uint16_t _asap = 0;
ComFlagEx _commFlagEx; ComFlagEx _commFlagEx;

View File

@ -107,10 +107,11 @@ bool GroupObjectTableObject::initGroupObjects()
GroupObject& go = _groupObjects[asap - 1]; GroupObject& go = _groupObjects[asap - 1];
go._asap = asap; go._asap = asap;
go._table = this; go._table = this;
go._dataLength = go.goSize(); go._dataLength = go.goSize();
go._data = new uint8_t[go._dataLength]; size_t sizeInMemory = go.sizeInMemory();
memset(go._data, 0, go._dataLength); go._data = new uint8_t[sizeInMemory];
memset(go._data, 0, sizeInMemory);
if (go.valueReadOnInit()) if (go.valueReadOnInit())
go.requestObjectRead(); go.requestObjectRead();

View File

@ -19,13 +19,16 @@
#define TP_FRAME_FLAG_ECHO 0b00010000 #define TP_FRAME_FLAG_ECHO 0b00010000
// Means that the frame is processed by this device // 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. // Means that the frame has been acked with BUSY
#define TP_FRAME_FLAG_ACKING 0b00000010 #define TP_FRAME_FLAG_ACK_BUSY 0b00000100
// Means that the frame has been acked by other (Busmontior) // Means that the frame has been acked with NACK
#define TP_FRAME_FLAG_ACKED 0b00000001 #define TP_FRAME_FLAG_ACK_NACK 0b00000010
// Means that the frame has been acked
#define TP_FRAME_FLAG_ACK 0b00000001
class TpFrame class TpFrame
{ {

View File

@ -60,6 +60,8 @@
// acknowledge services (device is transparent in bus monitor mode) // acknowledge services (device is transparent in bus monitor mode)
#define L_ACKN_IND 0x00 #define L_ACKN_IND 0x00
#define L_ACKN_MASK 0x33 #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 0x0B
#define L_DATA_CON_MASK 0x7F #define L_DATA_CON_MASK 0x7F
#define SUCCESS 0x80 #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_INVALID) ? 'I' : '_'); // Invalid
print((tpframe->flags() & TP_FRAME_FLAG_EXTENDED) ? 'E' : '_'); // Extended print((tpframe->flags() & TP_FRAME_FLAG_EXTENDED) ? 'E' : '_'); // Extended
print((tpframe->flags() & TP_FRAME_FLAG_REPEATED) ? 'R' : '_'); // Repeat print((tpframe->flags() & TP_FRAME_FLAG_REPEATED) ? 'R' : '_'); // Repeat
print((tpframe->flags() & TP_FRAME_FLAG_ECHO) ? 'O' : '_'); // My own print((tpframe->flags() & TP_FRAME_FLAG_ECHO) ? 'T' : '_'); // Send by me
print((tpframe->flags() & 0b00001000) ? 'x' : '_'); // Reserve print((tpframe->flags() & TP_FRAME_FLAG_ADDRESSED) ? 'D' : '_'); // Recv for me
print((tpframe->flags() & TP_FRAME_FLAG_ADDRESSED) ? 'D' : '_'); // For me print((tpframe->flags() & TP_FRAME_FLAG_ACK_NACK) ? 'N' : '_'); // ACK + NACK
print((tpframe->flags() & TP_FRAME_FLAG_ACKING) ? 'A' : '_'); // ACK recevied print((tpframe->flags() & TP_FRAME_FLAG_ACK_BUSY) ? 'B' : '_'); // ACK + BUSY
print((tpframe->flags() & TP_FRAME_FLAG_ACKED) ? 'A' : '_'); // ACK sent print((tpframe->flags() & TP_FRAME_FLAG_ACK) ? 'A' : '_'); // ACK
print("] "); print("] ");
printHex("( ", tpframe->data(), tpframe->size(), false); printHex("( ", tpframe->data(), tpframe->size(), false);
print(")"); print(")");
@ -294,7 +296,13 @@ void TpUartDataLinkLayer::processRxByte()
*/ */
if (_rxFrame->size() > 0) 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(); processRxFrameComplete();
} }
// println("L_ACKN_IND"); // 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 // Of course, this is only allowed if I am not sending myself, as you cannot ACK your own frames
if (_txState == TX_IDLE) if (_txState == TX_IDLE)
{ {
// Save that tracking should take place // Save that Acking should take place
_rxFrame->addFlags(TP_FRAME_FLAG_ACKING); _rxFrame->addFlags(TP_FRAME_FLAG_ACK);
// and in the TPUart so that it can send the ACK // and in the TPUart so that it can send the ACK
_platform.writeUart(U_ACK_REQ | U_ACK_REQ_ADRESSED); _platform.writeUart(U_ACK_REQ | U_ACK_REQ_ADRESSED);
@ -468,8 +476,8 @@ void TpUartDataLinkLayer::processRxFrameComplete()
// When a frame has been sent // When a frame has been sent
if (_txState == TX_FRAME) if (_txState == TX_FRAME)
{ {
// check whether the reception corresponds to this // 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 (!memcmp(_rxFrame->data(), _txFrame->data(), _txFrame->size())) if(!((_rxFrame->data(0) ^ _txFrame->data(0)) & ~0x20) && _rxFrame->destination() == _txFrame->destination() && _rxFrame->source() == _txFrame->source())
{ {
// and mark this accordingly // and mark this accordingly
// println("MATCH"); // println("MATCH");
@ -563,7 +571,6 @@ void TpUartDataLinkLayer::pushTxFrameQueue(TpFrame *tpFrame)
} }
_txQueueCount++; _txQueueCount++;
_txFrameCounter++;
} }
void TpUartDataLinkLayer::setRepetitions(uint8_t nack, uint8_t busy) 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) bool TpUartDataLinkLayer::sendFrame(CemiFrame &cemiFrame)
{ {
_txFrameCounter++;
if (!_connected || _monitoring || _txQueueCount > MAX_TX_QUEUE) if (!_connected || _monitoring || _txQueueCount > MAX_TX_QUEUE)
{ {
if (_txQueueCount > MAX_TX_QUEUE) if (_txQueueCount > MAX_TX_QUEUE)
{ {
println("Ignore frame because transmit queue is full!"); println("Ignore frame because transmit queue is full!");
} }
dataConReceived(cemiFrame, false); dataConReceived(cemiFrame, false);
return false; return false;
} }
@ -691,6 +701,17 @@ void TpUartDataLinkLayer::connected(bool state /* = true */)
_connected = state; _connected = state;
} }
void TpUartDataLinkLayer::resetStats()
{
_rxProcessdFrameCounter = 0;
_rxIgnoredFrameCounter = 0;
_rxInvalidFrameCounter = 0;
_rxInvalidFrameCounter = 0;
_rxUnkownControlCounter = 0;
_txFrameCounter = 0;
_txProcessdFrameCounter = 0;
}
bool TpUartDataLinkLayer::reset() bool TpUartDataLinkLayer::reset()
{ {
// println("Reset TP"); // println("Reset TP");
@ -704,11 +725,7 @@ bool TpUartDataLinkLayer::reset()
isrLock(true); isrLock(true);
// Reset // Reset
_rxIgnoredFrameCounter = 0; resetStats();
_rxInvalidFrameCounter = 0;
_rxInvalidFrameCounter = 0;
_rxUnkownControlCounter = 0;
clearTxFrame(); clearTxFrame();
clearTxFrameQueue(); clearTxFrameQueue();
@ -791,6 +808,7 @@ void TpUartDataLinkLayer::monitor()
// println("busmonitor"); // println("busmonitor");
_monitoring = true; _monitoring = true;
_platform.writeUart(U_BUSMON_REQ); _platform.writeUart(U_BUSMON_REQ);
resetStats();
} }
void TpUartDataLinkLayer::enabled(bool value) void TpUartDataLinkLayer::enabled(bool value)

View File

@ -57,6 +57,7 @@ class TpUartDataLinkLayer : public DataLinkLayer
bool isMonitoring(); bool isMonitoring();
bool isStopped(); bool isStopped();
bool isBusy(); bool isBusy();
void resetStats();
#ifdef USE_TP_RX_QUEUE #ifdef USE_TP_RX_QUEUE
void processRxISR(); void processRxISR();

View File

@ -286,10 +286,10 @@ template <class P, class B> class KnxFacade : private SaveRestore
pinMode(ledPin(), OUTPUT); pinMode(ledPin(), OUTPUT);
progLedOff(); progLedOff();
pinMode(buttonPin(), INPUT_PULLUP);
if (_progButtonISRFuncPtr && _buttonPin >= 0) if (_progButtonISRFuncPtr && _buttonPin >= 0)
{ {
pinMode(buttonPin(), INPUT_PULLUP);
// Workaround for https://github.com/arduino/ArduinoCore-samd/issues/587 // Workaround for https://github.com/arduino/ArduinoCore-samd/issues/587
#if (ARDUINO_API_VERSION >= 10200) #if (ARDUINO_API_VERSION >= 10200)
attachInterrupt(_buttonPin, _progButtonISRFuncPtr, (PinStatus)CHANGE); attachInterrupt(_buttonPin, _progButtonISRFuncPtr, (PinStatus)CHANGE);

View File

@ -517,11 +517,10 @@ int RP2040ArduinoPlatform::readBytesMultiCast(uint8_t* buffer, uint16_t maxLen)
if (len > maxLen) if (len > maxLen)
{ {
print("udp buffer to small. was "); println("Unexpected UDP data packet length - drop packet");
print(maxLen); for (size_t i = 0; i < len; i++)
print(", needed "); _udp.read();
println(len); return 0;
fatalError();
} }
_udp.read(buffer, len); _udp.read(buffer, len);