mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +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,318 +119,357 @@ void TpUartDataLinkLayer::loop() | |||||||
|     if (!_enabled) |     if (!_enabled) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     // Signals to communicate from rx part with the tx part
 |     // Loop once and repeat as long we have rx data available
 | ||||||
|     bool isEchoComplete = false;    // Flag that a complete echo is received
 |  | ||||||
|     uint8_t dataConnMsg = 0;  // The DATA_CONN message just seen or 0
 |  | ||||||
|     do { |     do { | ||||||
|         _receiveBuffer[0] = 0x29; |         // Signals to communicate from rx part with the tx part
 | ||||||
|         _receiveBuffer[1] = 0; |         bool isEchoComplete = false;    // Flag that a complete echo is received
 | ||||||
|         uint8_t* buffer = _receiveBuffer + 2; |         uint8_t dataConnMsg = 0;  // The DATA_CONN message just seen or 0
 | ||||||
|         uint8_t rxByte; | 
 | ||||||
|         bool isEOP = (millis() - _lastByteRxTime > EOP_TIMEOUT); // Flag that an EOP gap is seen
 | #ifdef KNX_WAIT_FOR_ADDR | ||||||
|         switch (_rxState) |         // After seeing a L2 packet start, stay in loop until address bytes are
 | ||||||
|         { |         // received and the AK/NAK packet is sent
 | ||||||
|             case RX_WAIT_START: |         bool stayInRx = true; | ||||||
|                 if (_platform.uartAvailable()) | #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 { | ||||||
|  |             uint8_t* buffer = _receiveBuffer + 2; | ||||||
|  |             uint8_t rxByte; | ||||||
|  |             switch (_rxState) | ||||||
|  |             { | ||||||
|  |                 case RX_WAIT_START: | ||||||
|  |                     if (_platform.uartAvailable()) | ||||||
|  |                     { | ||||||
|  |                         rxByte = _platform.readUart(); | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                         print(rxByte, HEX); | ||||||
|  | #endif | ||||||
|  |                         _lastByteRxTime = millis(); | ||||||
|  | 
 | ||||||
|  |                         // Check for layer-2 packets
 | ||||||
|  |                         _RxByteCnt = 0; | ||||||
|  |                         _xorSum = 0; | ||||||
|  |                         if ((rxByte & L_DATA_MASK) == L_DATA_STANDARD_IND) | ||||||
|  |                         { | ||||||
|  |                             buffer[_RxByteCnt++] = rxByte; | ||||||
|  |                             _xorSum ^= rxByte; | ||||||
|  |                             _RxByteCnt++; //convert to L_DATA_EXTENDED
 | ||||||
|  |                             _convert = true; | ||||||
|  |                             _rxState = RX_L_ADDR; | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                             println("RLS"); | ||||||
|  | #endif | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  |                         else if ((rxByte & L_DATA_MASK) == L_DATA_EXTENDED_IND) | ||||||
|  |                         { | ||||||
|  |                             buffer[_RxByteCnt++] = rxByte; | ||||||
|  |                             _xorSum ^= rxByte; | ||||||
|  |                             _convert = false; | ||||||
|  |                             _rxState = RX_L_ADDR; | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                             println("RLX"); | ||||||
|  | #endif | ||||||
|  |                             break; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         // Handle all single byte packets here
 | ||||||
|  |                         else if ((rxByte & L_DATA_CON_MASK) == L_DATA_CON) | ||||||
|  |                         { | ||||||
|  |                             dataConnMsg = rxByte; | ||||||
|  |                         } | ||||||
|  |                         else if (rxByte == L_POLL_DATA_IND) | ||||||
|  |                         { | ||||||
|  |                             // not sure if this can happen
 | ||||||
|  |                             println("got L_POLL_DATA_IND"); | ||||||
|  |                         } | ||||||
|  |                         else if ((rxByte & L_ACKN_MASK) == L_ACKN_IND) | ||||||
|  |                         { | ||||||
|  |                             // this can only happen in bus monitor mode
 | ||||||
|  |                             println("got L_ACKN_IND"); | ||||||
|  |                         } | ||||||
|  |                         else if (rxByte == U_RESET_IND) | ||||||
|  |                         { | ||||||
|  |                             println("got U_RESET_IND"); | ||||||
|  |                         } | ||||||
|  |                         else if ((rxByte & U_STATE_IND) == U_STATE_IND) | ||||||
|  |                         { | ||||||
|  |                             print("got U_STATE_IND:"); | ||||||
|  |                             if (rxByte & 0x80) print (" SC"); | ||||||
|  |                             if (rxByte & 0x40) print (" RE"); | ||||||
|  |                             if (rxByte & 0x20) print (" TE"); | ||||||
|  |                             if (rxByte & 0x10) print (" PE"); | ||||||
|  |                             if (rxByte & 0x08) print (" TW"); | ||||||
|  |                             println(); | ||||||
|  |                         } | ||||||
|  |                         else if ((rxByte & U_FRAME_STATE_MASK) == U_FRAME_STATE_IND) | ||||||
|  |                         { | ||||||
|  |                             print("got U_FRAME_STATE_IND: 0x"); | ||||||
|  |                             print(rxByte, HEX); | ||||||
|  |                             println(); | ||||||
|  |                         } | ||||||
|  |                         else if ((rxByte & U_CONFIGURE_MASK) == U_CONFIGURE_IND) | ||||||
|  |                         { | ||||||
|  |                             print("got U_CONFIGURE_IND: 0x"); | ||||||
|  |                             print(rxByte, HEX); | ||||||
|  |                             println(); | ||||||
|  |                         } | ||||||
|  |                         else if (rxByte == U_FRAME_END_IND) | ||||||
|  |                         { | ||||||
|  |                             println("got U_FRAME_END_IND"); | ||||||
|  |                         } | ||||||
|  |                         else if (rxByte == U_STOP_MODE_IND) | ||||||
|  |                         { | ||||||
|  |                             println("got U_STOP_MODE_IND"); | ||||||
|  |                         } | ||||||
|  |                         else if (rxByte == U_SYSTEM_STAT_IND) | ||||||
|  |                         { | ||||||
|  |                             print("got U_SYSTEM_STAT_IND: 0x"); | ||||||
|  |                             while (true) | ||||||
|  |                             { | ||||||
|  |                                 int tmp = _platform.readUart(); | ||||||
|  |                                 if (tmp < 0) | ||||||
|  |                                     continue; | ||||||
|  | 
 | ||||||
|  |                                 print(tmp, HEX); | ||||||
|  |                                 break; | ||||||
|  |                             } | ||||||
|  |                             println(); | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             print("got UNEXPECTED: 0x"); | ||||||
|  |                             print(rxByte, HEX); | ||||||
|  |                             println(); | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|  |                 case RX_L_ADDR: | ||||||
|  |                     if (millis() - _lastByteRxTime > EOPR_TIMEOUT) | ||||||
|  |                     { | ||||||
|  |                         _rxState = RX_WAIT_START; | ||||||
|  |                         print("EOPR inside RX_L_ADDR"); | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     if (!_platform.uartAvailable()) | ||||||
|  |                         break; | ||||||
|  |                     _lastByteRxTime = millis(); | ||||||
|                     rxByte = _platform.readUart(); |                     rxByte = _platform.readUart(); | ||||||
| #ifdef DBG_TRACE | #ifdef DBG_TRACE | ||||||
|                     print(rxByte, HEX); |                     print(rxByte, HEX); | ||||||
| #endif | #endif | ||||||
|                     _lastByteRxTime = millis(); |  | ||||||
| 
 |  | ||||||
|                     // Check for layer-2 packets
 |  | ||||||
|                     _RxByteCnt = 0; |  | ||||||
|                     _xorSum = 0; |  | ||||||
|                     if ((rxByte & L_DATA_MASK) == L_DATA_STANDARD_IND) |  | ||||||
|                     { |  | ||||||
|                         buffer[_RxByteCnt++] = rxByte; |  | ||||||
|                         _xorSum ^= rxByte; |  | ||||||
|                         _RxByteCnt++; //convert to L_DATA_EXTENDED
 |  | ||||||
|                         _convert = true; |  | ||||||
|                         _rxState = RX_L_DATA; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                         println("RLS"); |  | ||||||
| #endif |  | ||||||
|                         break; |  | ||||||
|                     } |  | ||||||
|                     else if ((rxByte & L_DATA_MASK) == L_DATA_EXTENDED_IND) |  | ||||||
|                     { |  | ||||||
|                         buffer[_RxByteCnt++] = rxByte; |  | ||||||
|                         _xorSum ^= rxByte; |  | ||||||
|                         _convert = false; |  | ||||||
|                         _rxState = RX_L_DATA; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                         println("RLX"); |  | ||||||
| #endif |  | ||||||
|                         break; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     // Handle all single byte packets here
 |  | ||||||
|                     else if ((rxByte & L_DATA_CON_MASK) == L_DATA_CON) |  | ||||||
|                     { |  | ||||||
|                         dataConnMsg = rxByte; |  | ||||||
|                     } |  | ||||||
|                     else if (rxByte == L_POLL_DATA_IND) |  | ||||||
|                     { |  | ||||||
|                         // not sure if this can happen
 |  | ||||||
|                         println("got L_POLL_DATA_IND"); |  | ||||||
|                     } |  | ||||||
|                     else if ((rxByte & L_ACKN_MASK) == L_ACKN_IND) |  | ||||||
|                     { |  | ||||||
|                         // this can only happen in bus monitor mode
 |  | ||||||
|                         println("got L_ACKN_IND"); |  | ||||||
|                     } |  | ||||||
|                     else if (rxByte == U_RESET_IND) |  | ||||||
|                     { |  | ||||||
|                         println("got U_RESET_IND"); |  | ||||||
|                     } |  | ||||||
|                     else if ((rxByte & U_STATE_IND) == U_STATE_IND) |  | ||||||
|                     { |  | ||||||
|                         print("got U_STATE_IND:"); |  | ||||||
|                         if (rxByte & 0x80) print (" SC"); |  | ||||||
|                         if (rxByte & 0x40) print (" RE"); |  | ||||||
|                         if (rxByte & 0x20) print (" TE"); |  | ||||||
|                         if (rxByte & 0x10) print (" PE"); |  | ||||||
|                         if (rxByte & 0x08) print (" TW"); |  | ||||||
|                         println(); |  | ||||||
|                     } |  | ||||||
|                     else if ((rxByte & U_FRAME_STATE_MASK) == U_FRAME_STATE_IND) |  | ||||||
|                     { |  | ||||||
|                         print("got U_FRAME_STATE_IND: 0x"); |  | ||||||
|                         print(rxByte, HEX); |  | ||||||
|                         println(); |  | ||||||
|                     } |  | ||||||
|                     else if ((rxByte & U_CONFIGURE_MASK) == U_CONFIGURE_IND) |  | ||||||
|                     { |  | ||||||
|                         print("got U_CONFIGURE_IND: 0x"); |  | ||||||
|                         print(rxByte, HEX); |  | ||||||
|                         println(); |  | ||||||
|                     } |  | ||||||
|                     else if (rxByte == U_FRAME_END_IND) |  | ||||||
|                     { |  | ||||||
|                         println("got U_FRAME_END_IND"); |  | ||||||
|                     } |  | ||||||
|                     else if (rxByte == U_STOP_MODE_IND) |  | ||||||
|                     { |  | ||||||
|                         println("got U_STOP_MODE_IND"); |  | ||||||
|                     } |  | ||||||
|                     else if (rxByte == U_SYSTEM_STAT_IND) |  | ||||||
|                     { |  | ||||||
|                         print("got U_SYSTEM_STAT_IND: 0x"); |  | ||||||
|                         while (true) |  | ||||||
|                         { |  | ||||||
|                             int tmp = _platform.readUart(); |  | ||||||
|                             if (tmp < 0) |  | ||||||
|                                 continue; |  | ||||||
| 
 |  | ||||||
|                             print(tmp, HEX); |  | ||||||
|                             break; |  | ||||||
|                         } |  | ||||||
|                         println(); |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |  | ||||||
|                         print("got UNEXPECTED: 0x"); |  | ||||||
|                         print(rxByte, HEX); |  | ||||||
|                         println(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 break; |  | ||||||
|             case RX_L_DATA: |  | ||||||
|                 if (isEOP) |  | ||||||
|                 { |  | ||||||
|                     _rxState = RX_WAIT_START; |  | ||||||
|                     print("EOP inside RX_L_DATA"); |  | ||||||
|                     printHex(" => ", buffer, _RxByteCnt); |  | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|                 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; |                     buffer[_RxByteCnt++] = rxByte; | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (_RxByteCnt == 7) |  | ||||||
|                 { |  | ||||||
|                     //Destination Address + payload available
 |  | ||||||
|                     _xorSum ^= rxByte; |                     _xorSum ^= rxByte; | ||||||
|                     //check if echo
 | 
 | ||||||
|                     if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5))) |                     if (_RxByteCnt == 7) | ||||||
|                     { //ignore repeated bit of control byte
 |  | ||||||
|                         _isEcho = true; |  | ||||||
|                     } |  | ||||||
|                     else |  | ||||||
|                     { |                     { | ||||||
|                         _isEcho = false; |                         //Destination Address + payload available
 | ||||||
|                     } |                         //check if echo
 | ||||||
| 
 |                         if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5))) | ||||||
|                     //convert into Extended.ind
 |                         { //ignore repeated bit of control byte
 | ||||||
|                     if (_convert) |                             _isEcho = true; | ||||||
|                     { |  | ||||||
|                         uint8_t payloadLength = buffer[6] & 0x0F; |  | ||||||
|                         buffer[1] = buffer[6] & 0xF0; |  | ||||||
|                         buffer[6] = payloadLength; |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     if (!_isEcho) |  | ||||||
|                     { |  | ||||||
|                         uint8_t c = 0x10; |  | ||||||
| 
 |  | ||||||
|                         // The bau knows everything and could either check the address table object (normal device)
 |  | ||||||
|                         // or any filter tables (coupler) to see if we are addressed.
 |  | ||||||
| 
 |  | ||||||
|                         //check if individual or group address
 |  | ||||||
|                         bool isGroupAddress = (buffer[1] & 0x80) != 0; |  | ||||||
|                         uint16_t addr = getWord(buffer + 4); |  | ||||||
| 
 |  | ||||||
|                         if (_cb.isAckRequired(addr, isGroupAddress)) |  | ||||||
|                         { |  | ||||||
|                             c |= 0x01; |  | ||||||
|                         } |  | ||||||
| 
 |  | ||||||
|                         // Hint: We can send directly here, this doesn't disturb other transmissions
 |  | ||||||
|                         _platform.writeUart(c); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 else if (_RxByteCnt == buffer[6] + 7 + 2) |  | ||||||
|                 { |  | ||||||
|                     //complete Frame received, payloadLength+1 for TCPI +1 for CRC
 |  | ||||||
|                     if (rxByte == (uint8_t)(~_xorSum)) |  | ||||||
|                     { |  | ||||||
|                         //check if crc is correct
 |  | ||||||
|                         if (_isEcho && _sendBuffer != NULL) |  | ||||||
|                         { |  | ||||||
|                             //check if it is realy an echo, rx_crc = tx_crc
 |  | ||||||
|                             if (rxByte == _sendBuffer[_sendBufferLength - 1]) |  | ||||||
|                                 _isEcho = true; |  | ||||||
|                             else |  | ||||||
|                                 _isEcho = false; |  | ||||||
|                         } |  | ||||||
|                         if (_isEcho) |  | ||||||
|                         { |  | ||||||
|                             isEchoComplete = true; |  | ||||||
|                         } |                         } | ||||||
|                         else |                         else | ||||||
|                         { |                         { | ||||||
|                             frameBytesReceived(_receiveBuffer, _RxByteCnt + 2); |                             _isEcho = false; | ||||||
|                         } |                         } | ||||||
|  | 
 | ||||||
|  |                         //convert into Extended.ind
 | ||||||
|  |                         if (_convert) | ||||||
|  |                         { | ||||||
|  |                             uint8_t payloadLength = buffer[6] & 0x0F; | ||||||
|  |                             buffer[1] = buffer[6] & 0xF0; | ||||||
|  |                             buffer[6] = payloadLength; | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                         if (!_isEcho) | ||||||
|  |                         { | ||||||
|  |                             uint8_t c = 0x10; | ||||||
|  | 
 | ||||||
|  |                             // The bau knows everything and could either check the address table object (normal device)
 | ||||||
|  |                             // or any filter tables (coupler) to see if we are addressed.
 | ||||||
|  | 
 | ||||||
|  |                             //check if individual or group address
 | ||||||
|  |                             bool isGroupAddress = (buffer[1] & 0x80) != 0; | ||||||
|  |                             uint16_t addr = getWord(buffer + 4); | ||||||
|  | 
 | ||||||
|  |                             if (_cb.isAckRequired(addr, isGroupAddress)) | ||||||
|  |                             { | ||||||
|  |                                 c |= 0x01; | ||||||
|  |                             } | ||||||
|  | 
 | ||||||
|  |                             // 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); | ||||||
|  |                         } | ||||||
|  |                         _rxState = RX_L_DATA; | ||||||
|  |                     } | ||||||
|  |                     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
 | ||||||
|  |                         if (rxByte == (uint8_t)(~_xorSum)) | ||||||
|  |                         { | ||||||
|  |                             //check if crc is correct
 | ||||||
|  |                             if (_isEcho && _sendBuffer != NULL) | ||||||
|  |                             { | ||||||
|  |                                 //check if it is realy an echo, rx_crc = tx_crc
 | ||||||
|  |                                 if (rxByte == _sendBuffer[_sendBufferLength - 1]) | ||||||
|  |                                     _isEcho = true; | ||||||
|  |                                 else | ||||||
|  |                                     _isEcho = false; | ||||||
|  |                             } | ||||||
|  |                             if (_isEcho) | ||||||
|  |                             { | ||||||
|  |                                 isEchoComplete = true; | ||||||
|  |                             } | ||||||
|  |                             else | ||||||
|  |                             { | ||||||
|  |                                 _receiveBuffer[0] = 0x29; | ||||||
|  |                                 _receiveBuffer[1] = 0; | ||||||
|  |                                 frameBytesReceived(_receiveBuffer, _RxByteCnt + 2); | ||||||
|  |                             } | ||||||
|  |                             _rxState = RX_WAIT_START; | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                             println("RX_WAIT_START"); | ||||||
|  | #endif | ||||||
|  |                         } | ||||||
|  |                         else | ||||||
|  |                         { | ||||||
|  |                             println("frame with invalid crc ignored"); | ||||||
|  |                             _rxState = RX_WAIT_EOP; | ||||||
|  |                         } | ||||||
|  |                     } | ||||||
|  |                     else | ||||||
|  |                     { | ||||||
|  |                         _xorSum ^= rxByte; | ||||||
|  |                     } | ||||||
|  |                     break; | ||||||
|  |                 case RX_WAIT_EOP: | ||||||
|  |                     if (millis() - _lastByteRxTime > EOP_TIMEOUT) | ||||||
|  |                     { | ||||||
|  |                         _RxByteCnt = 0; | ||||||
|                         _rxState = RX_WAIT_START; |                         _rxState = RX_WAIT_START; | ||||||
| #ifdef DBG_TRACE | #ifdef DBG_TRACE | ||||||
|                         println("RX_WAIT_START"); |                         println("RX_WAIT_START"); | ||||||
|  | #endif | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                     if (!_platform.uartAvailable()) | ||||||
|  |                         break; | ||||||
|  |                     _lastByteRxTime = millis(); | ||||||
|  |                     rxByte = _platform.readUart(); | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                     print(rxByte, HEX); | ||||||
|  | #endif | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |         } while (_rxState == RX_L_ADDR && (stayInRx || _platform.uartAvailable())); | ||||||
|  | 
 | ||||||
|  |         // Check for spurios DATA_CONN message
 | ||||||
|  |         if (dataConnMsg && _txState != TX_WAIT_CONN && _txState != TX_WAIT_ECHO) { | ||||||
|  |             println("got unexpected L_DATA_CON"); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         switch (_txState) | ||||||
|  |         { | ||||||
|  |             case TX_IDLE: | ||||||
|  |                 if (!isTxQueueEmpty()) | ||||||
|  |                 { | ||||||
|  |                     loadNextTxFrame(); | ||||||
|  |                     _txState = TX_FRAME; | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                     println("TX_FRAME"); | ||||||
|  | #endif | ||||||
|  |                 } | ||||||
|  |                 break; | ||||||
|  |             case TX_FRAME: | ||||||
|  |                 if (millis() - _lastByteTxTime > TX_TIMEPAUSE) | ||||||
|  |                 { | ||||||
|  |                     if (sendSingleFrameByte() == false) | ||||||
|  |                     { | ||||||
|  |                         _waitConfirmStartTime = millis(); | ||||||
|  |                         _txState = TX_WAIT_ECHO; | ||||||
|  | #ifdef DBG_TRACE | ||||||
|  |                         println("TX_WAIT_ECHO"); | ||||||
| #endif | #endif | ||||||
|                     } |                     } | ||||||
|                     else |                     else | ||||||
|                     { |                     { | ||||||
|                         println("frame with invalid crc ignored"); |                         _lastByteTxTime = millis(); | ||||||
|                         _rxState = RX_WAIT_EOP; |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 else |  | ||||||
|                 { |  | ||||||
|                     _xorSum ^= rxByte; |  | ||||||
|                 } |  | ||||||
|                 break; |                 break; | ||||||
|             case RX_WAIT_EOP: |             case TX_WAIT_ECHO: | ||||||
|                 if (isEOP) |             case TX_WAIT_CONN: | ||||||
|  |                 if (isEchoComplete) | ||||||
|                 { |                 { | ||||||
|                     _RxByteCnt = 0; |                     _txState = TX_WAIT_CONN; | ||||||
|                     _rxState = RX_WAIT_START; |  | ||||||
| #ifdef DBG_TRACE | #ifdef DBG_TRACE | ||||||
|                     println("RX_WAIT_START"); |                     println("TX_WAIT_CONN"); | ||||||
| #endif | #endif | ||||||
|                     break; |  | ||||||
|                 } |                 } | ||||||
|                 if (!_platform.uartAvailable()) |                 else if (dataConnMsg) | ||||||
|                     break; |                 { | ||||||
|                 _lastByteRxTime = millis(); |                     bool waitEcho = (_txState == TX_WAIT_ECHO); | ||||||
|                 rxByte = _platform.readUart(); |                     if (waitEcho) { | ||||||
|  |                         println("L_DATA_CON without echo"); | ||||||
|  |                     } | ||||||
|  |                     dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, !waitEcho && ((dataConnMsg & SUCCESS) > 0)); | ||||||
|  |                     delete[] _sendBuffer; | ||||||
|  |                     _sendBuffer = 0; | ||||||
|  |                     _sendBufferLength = 0; | ||||||
|  |                     _txState = TX_IDLE; | ||||||
|  |                 } | ||||||
|  |                 else if (millis() - _waitConfirmStartTime > CONFIRM_TIMEOUT) | ||||||
|  |                 { | ||||||
|  |                     println("L_DATA_CON not received within expected time"); | ||||||
|  |                     uint8_t cemiBuffer[MAX_KNX_TELEGRAM_SIZE]; | ||||||
|  |                     cemiBuffer[0] = 0x29; | ||||||
|  |                     cemiBuffer[1] = 0; | ||||||
|  |                     memcpy((cemiBuffer + 2), _sendBuffer, _sendBufferLength); | ||||||
|  |                     dataConBytesReceived(cemiBuffer, _sendBufferLength + 2, false); | ||||||
|  |                     delete[] _sendBuffer; | ||||||
|  |                     _sendBuffer = 0; | ||||||
|  |                     _sendBufferLength = 0; | ||||||
|  |                     _txState = TX_IDLE; | ||||||
| #ifdef DBG_TRACE | #ifdef DBG_TRACE | ||||||
|                 print(rxByte, HEX); |                     println("TX_IDLE"); | ||||||
| #endif | #endif | ||||||
|                 break; |                 } | ||||||
|             default: |  | ||||||
|                 break; |                 break; | ||||||
|         } |         } | ||||||
|     } while (_rxState == RX_L_DATA); |     } while (_platform.uartAvailable()); | ||||||
| 
 |  | ||||||
|     // Check for spurios DATA_CONN message
 |  | ||||||
|     if (dataConnMsg && _txState != TX_WAIT_CONN && _txState != TX_WAIT_ECHO) { |  | ||||||
|         println("got unexpected L_DATA_CON"); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     switch (_txState) |  | ||||||
|     { |  | ||||||
|         case TX_IDLE: |  | ||||||
|             if (!isTxQueueEmpty()) |  | ||||||
|             { |  | ||||||
|                 loadNextTxFrame(); |  | ||||||
|                 _txState = TX_FRAME; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                 println("TX_FRAME"); |  | ||||||
| #endif |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         case TX_FRAME: |  | ||||||
|             if (sendSingleFrameByte() == false) |  | ||||||
|             { |  | ||||||
|                 _waitConfirmStartTime = millis(); |  | ||||||
|                 _txState = TX_WAIT_ECHO; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                 println("TX_WAIT_ECHO"); |  | ||||||
| #endif |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|         case TX_WAIT_ECHO: |  | ||||||
|         case TX_WAIT_CONN: |  | ||||||
|             if (isEchoComplete) |  | ||||||
|             { |  | ||||||
|                 _txState = TX_WAIT_CONN; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                 println("TX_WAIT_CONN"); |  | ||||||
| #endif |  | ||||||
|             } |  | ||||||
|             else if (dataConnMsg) |  | ||||||
|             { |  | ||||||
|                 bool waitEcho = (_txState == TX_WAIT_ECHO); |  | ||||||
|                 if (waitEcho) { |  | ||||||
|                     println("L_DATA_CON without echo"); |  | ||||||
|                 } |  | ||||||
|                 dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, !waitEcho && ((dataConnMsg & SUCCESS) > 0)); |  | ||||||
|                 delete[] _sendBuffer; |  | ||||||
|                 _sendBuffer = 0; |  | ||||||
|                 _sendBufferLength = 0; |  | ||||||
|                 _txState = TX_IDLE; |  | ||||||
|             } |  | ||||||
|             else if (millis() - _waitConfirmStartTime > CONFIRM_TIMEOUT) |  | ||||||
|             { |  | ||||||
|                 println("L_DATA_CON not received within expected time"); |  | ||||||
|                 uint8_t cemiBuffer[MAX_KNX_TELEGRAM_SIZE]; |  | ||||||
|                 cemiBuffer[0] = 0x29; |  | ||||||
|                 cemiBuffer[1] = 0; |  | ||||||
|                 memcpy((cemiBuffer + 2), _sendBuffer, _sendBufferLength); |  | ||||||
|                 dataConBytesReceived(cemiBuffer, _sendBufferLength + 2, false); |  | ||||||
|                 delete[] _sendBuffer; |  | ||||||
|                 _sendBuffer = 0; |  | ||||||
|                 _sendBufferLength = 0; |  | ||||||
|                 _txState = TX_IDLE; |  | ||||||
| #ifdef DBG_TRACE |  | ||||||
|                 println("TX_IDLE"); |  | ||||||
| #endif |  | ||||||
|             } |  | ||||||
|             break; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 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