mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
Merge commit '093ae42' into openknx-merge
This commit is contained in:
commit
5ddbff2d16
10
.vscode/extensions.json
vendored
10
.vscode/extensions.json
vendored
@ -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"
|
|
||||||
]
|
|
||||||
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
|
@ -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
|
||||||
{
|
{
|
||||||
|
@ -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)
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user