mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
Merge pull request #171 from mptei/tx_throttle_rx_wait_addr
More tpuart fixes
This commit is contained in:
commit
d26771c432
@ -89,17 +89,23 @@ enum {
|
|||||||
//rx states
|
//rx states
|
||||||
enum {
|
enum {
|
||||||
RX_WAIT_START,
|
RX_WAIT_START,
|
||||||
|
RX_L_ADDR,
|
||||||
RX_L_DATA,
|
RX_L_DATA,
|
||||||
RX_WAIT_EOP
|
RX_WAIT_EOP
|
||||||
};
|
};
|
||||||
|
|
||||||
#define EOP_TIMEOUT 2 //milli seconds; end of layer-2 packet gap
|
#define EOP_TIMEOUT 2 //milli seconds; end of layer-2 packet gap
|
||||||
|
#define EOPR_TIMEOUT 8 //ms; relaxed EOP timeout; usally to trigger after NAK
|
||||||
#define CONFIRM_TIMEOUT 500 //milli seconds
|
#define CONFIRM_TIMEOUT 500 //milli seconds
|
||||||
#define RESET_TIMEOUT 100 //milli seconds
|
#define RESET_TIMEOUT 100 //milli seconds
|
||||||
|
#define TX_TIMEPAUSE 0 // 0 means 1 milli seconds
|
||||||
|
|
||||||
|
// If this threshold is reached loop() goes into
|
||||||
|
// "hog mode" where it stays in loop() while L2 address reception
|
||||||
|
#define HOGMODE_THRESHOLD 3 // milli seconds
|
||||||
|
|
||||||
void TpUartDataLinkLayer::loop()
|
void TpUartDataLinkLayer::loop()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
{
|
{
|
||||||
if (millis() - _lastResetChipTime > 1000)
|
if (millis() - _lastResetChipTime > 1000)
|
||||||
@ -113,15 +119,32 @@ void TpUartDataLinkLayer::loop()
|
|||||||
if (!_enabled)
|
if (!_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// Loop once and repeat as long we have rx data available
|
||||||
|
do {
|
||||||
// Signals to communicate from rx part with the tx part
|
// Signals to communicate from rx part with the tx part
|
||||||
bool isEchoComplete = false; // Flag that a complete echo is received
|
bool isEchoComplete = false; // Flag that a complete echo is received
|
||||||
uint8_t dataConnMsg = 0; // The DATA_CONN message just seen or 0
|
uint8_t dataConnMsg = 0; // The DATA_CONN message just seen or 0
|
||||||
|
|
||||||
|
#ifdef KNX_WAIT_FOR_ADDR
|
||||||
|
// After seeing a L2 packet start, stay in loop until address bytes are
|
||||||
|
// received and the AK/NAK packet is sent
|
||||||
|
bool stayInRx = true;
|
||||||
|
#elif defined(KNX_AUTO_ADAPT)
|
||||||
|
// After seeing a L2 packet start, stay in loop until address bytes are
|
||||||
|
// received and the AK/NAK packet is sent, when last loop call delayed
|
||||||
|
// by more than HOGMODE_THRESHOLD
|
||||||
|
bool stayInRx = millis() - _lastLoopTime > HOGMODE_THRESHOLD;
|
||||||
|
_lastLoopTime = millis();
|
||||||
|
#else
|
||||||
|
// After seeing a L2 packet start, leave loop and hope the loop
|
||||||
|
// is called early enough to do further processings
|
||||||
|
bool stayInRx = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Loop once and repeat as long we are in the receive phase for the L2 address
|
||||||
do {
|
do {
|
||||||
_receiveBuffer[0] = 0x29;
|
|
||||||
_receiveBuffer[1] = 0;
|
|
||||||
uint8_t* buffer = _receiveBuffer + 2;
|
uint8_t* buffer = _receiveBuffer + 2;
|
||||||
uint8_t rxByte;
|
uint8_t rxByte;
|
||||||
bool isEOP = (millis() - _lastByteRxTime > EOP_TIMEOUT); // Flag that an EOP gap is seen
|
|
||||||
switch (_rxState)
|
switch (_rxState)
|
||||||
{
|
{
|
||||||
case RX_WAIT_START:
|
case RX_WAIT_START:
|
||||||
@ -142,7 +165,7 @@ void TpUartDataLinkLayer::loop()
|
|||||||
_xorSum ^= rxByte;
|
_xorSum ^= rxByte;
|
||||||
_RxByteCnt++; //convert to L_DATA_EXTENDED
|
_RxByteCnt++; //convert to L_DATA_EXTENDED
|
||||||
_convert = true;
|
_convert = true;
|
||||||
_rxState = RX_L_DATA;
|
_rxState = RX_L_ADDR;
|
||||||
#ifdef DBG_TRACE
|
#ifdef DBG_TRACE
|
||||||
println("RLS");
|
println("RLS");
|
||||||
#endif
|
#endif
|
||||||
@ -153,7 +176,7 @@ void TpUartDataLinkLayer::loop()
|
|||||||
buffer[_RxByteCnt++] = rxByte;
|
buffer[_RxByteCnt++] = rxByte;
|
||||||
_xorSum ^= rxByte;
|
_xorSum ^= rxByte;
|
||||||
_convert = false;
|
_convert = false;
|
||||||
_rxState = RX_L_DATA;
|
_rxState = RX_L_ADDR;
|
||||||
#ifdef DBG_TRACE
|
#ifdef DBG_TRACE
|
||||||
println("RLX");
|
println("RLX");
|
||||||
#endif
|
#endif
|
||||||
@ -231,12 +254,11 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RX_L_DATA:
|
case RX_L_ADDR:
|
||||||
if (isEOP)
|
if (millis() - _lastByteRxTime > EOPR_TIMEOUT)
|
||||||
{
|
{
|
||||||
_rxState = RX_WAIT_START;
|
_rxState = RX_WAIT_START;
|
||||||
print("EOP inside RX_L_DATA");
|
print("EOPR inside RX_L_ADDR");
|
||||||
printHex(" => ", buffer, _RxByteCnt);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!_platform.uartAvailable())
|
if (!_platform.uartAvailable())
|
||||||
@ -246,20 +268,12 @@ void TpUartDataLinkLayer::loop()
|
|||||||
#ifdef DBG_TRACE
|
#ifdef DBG_TRACE
|
||||||
print(rxByte, HEX);
|
print(rxByte, HEX);
|
||||||
#endif
|
#endif
|
||||||
if (_RxByteCnt == MAX_KNX_TELEGRAM_SIZE)
|
|
||||||
{
|
|
||||||
_rxState = RX_WAIT_EOP;
|
|
||||||
println("invalid telegram size");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buffer[_RxByteCnt++] = rxByte;
|
buffer[_RxByteCnt++] = rxByte;
|
||||||
}
|
_xorSum ^= rxByte;
|
||||||
|
|
||||||
if (_RxByteCnt == 7)
|
if (_RxByteCnt == 7)
|
||||||
{
|
{
|
||||||
//Destination Address + payload available
|
//Destination Address + payload available
|
||||||
_xorSum ^= rxByte;
|
|
||||||
//check if echo
|
//check if echo
|
||||||
if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5)))
|
if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5)))
|
||||||
{ //ignore repeated bit of control byte
|
{ //ignore repeated bit of control byte
|
||||||
@ -295,10 +309,31 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hint: We can send directly here, this doesn't disturb other transmissions
|
// Hint: We can send directly here, this doesn't disturb other transmissions
|
||||||
|
// We don't have to update _lastByteTxTime because after ACK the timing is not so tight
|
||||||
_platform.writeUart(c);
|
_platform.writeUart(c);
|
||||||
}
|
}
|
||||||
|
_rxState = RX_L_DATA;
|
||||||
}
|
}
|
||||||
else if (_RxByteCnt == buffer[6] + 7 + 2)
|
break;
|
||||||
|
case RX_L_DATA:
|
||||||
|
if (!_platform.uartAvailable())
|
||||||
|
break;
|
||||||
|
_lastByteRxTime = millis();
|
||||||
|
rxByte = _platform.readUart();
|
||||||
|
#ifdef DBG_TRACE
|
||||||
|
print(rxByte, HEX);
|
||||||
|
#endif
|
||||||
|
if (_RxByteCnt == MAX_KNX_TELEGRAM_SIZE)
|
||||||
|
{
|
||||||
|
_rxState = RX_WAIT_EOP;
|
||||||
|
println("invalid telegram size");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
buffer[_RxByteCnt++] = rxByte;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_RxByteCnt == buffer[6] + 7 + 2)
|
||||||
{
|
{
|
||||||
//complete Frame received, payloadLength+1 for TCPI +1 for CRC
|
//complete Frame received, payloadLength+1 for TCPI +1 for CRC
|
||||||
if (rxByte == (uint8_t)(~_xorSum))
|
if (rxByte == (uint8_t)(~_xorSum))
|
||||||
@ -318,6 +353,8 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
_receiveBuffer[0] = 0x29;
|
||||||
|
_receiveBuffer[1] = 0;
|
||||||
frameBytesReceived(_receiveBuffer, _RxByteCnt + 2);
|
frameBytesReceived(_receiveBuffer, _RxByteCnt + 2);
|
||||||
}
|
}
|
||||||
_rxState = RX_WAIT_START;
|
_rxState = RX_WAIT_START;
|
||||||
@ -337,7 +374,7 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case RX_WAIT_EOP:
|
case RX_WAIT_EOP:
|
||||||
if (isEOP)
|
if (millis() - _lastByteRxTime > EOP_TIMEOUT)
|
||||||
{
|
{
|
||||||
_RxByteCnt = 0;
|
_RxByteCnt = 0;
|
||||||
_rxState = RX_WAIT_START;
|
_rxState = RX_WAIT_START;
|
||||||
@ -357,7 +394,7 @@ void TpUartDataLinkLayer::loop()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (_rxState == RX_L_DATA);
|
} while (_rxState == RX_L_ADDR && (stayInRx || _platform.uartAvailable()));
|
||||||
|
|
||||||
// Check for spurios DATA_CONN message
|
// Check for spurios DATA_CONN message
|
||||||
if (dataConnMsg && _txState != TX_WAIT_CONN && _txState != TX_WAIT_ECHO) {
|
if (dataConnMsg && _txState != TX_WAIT_CONN && _txState != TX_WAIT_ECHO) {
|
||||||
@ -377,6 +414,8 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TX_FRAME:
|
case TX_FRAME:
|
||||||
|
if (millis() - _lastByteTxTime > TX_TIMEPAUSE)
|
||||||
|
{
|
||||||
if (sendSingleFrameByte() == false)
|
if (sendSingleFrameByte() == false)
|
||||||
{
|
{
|
||||||
_waitConfirmStartTime = millis();
|
_waitConfirmStartTime = millis();
|
||||||
@ -385,6 +424,11 @@ void TpUartDataLinkLayer::loop()
|
|||||||
println("TX_WAIT_ECHO");
|
println("TX_WAIT_ECHO");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_lastByteTxTime = millis();
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TX_WAIT_ECHO:
|
case TX_WAIT_ECHO:
|
||||||
case TX_WAIT_CONN:
|
case TX_WAIT_CONN:
|
||||||
@ -425,6 +469,7 @@ void TpUartDataLinkLayer::loop()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} while (_platform.uartAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame)
|
bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame)
|
||||||
|
@ -43,6 +43,8 @@ class TpUartDataLinkLayer : public DataLinkLayer
|
|||||||
bool _convert = false;
|
bool _convert = false;
|
||||||
uint8_t _xorSum = 0;
|
uint8_t _xorSum = 0;
|
||||||
uint32_t _lastByteRxTime;
|
uint32_t _lastByteRxTime;
|
||||||
|
uint32_t _lastByteTxTime;
|
||||||
|
uint32_t _lastLoopTime;
|
||||||
uint32_t _waitConfirmStartTime;
|
uint32_t _waitConfirmStartTime;
|
||||||
uint32_t _lastResetChipTime = 0;
|
uint32_t _lastResetChipTime = 0;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user