mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	Merge branch 'master' into flashnew_w_master2
# Conflicts: # src/rp2040_arduino_platform.cpp
This commit is contained in:
		
						commit
						5bf2177d66
					
				| @ -89,17 +89,23 @@ enum { | ||||
| //rx states
 | ||||
| enum { | ||||
|     RX_WAIT_START, | ||||
|     RX_L_ADDR, | ||||
|     RX_L_DATA, | ||||
|     RX_WAIT_EOP | ||||
| }; | ||||
| 
 | ||||
| #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 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() | ||||
| { | ||||
| 
 | ||||
|     if (!_enabled) | ||||
|     { | ||||
|         if (millis() - _lastResetChipTime > 1000) | ||||
| @ -113,318 +119,357 @@ void TpUartDataLinkLayer::loop() | ||||
|     if (!_enabled) | ||||
|         return; | ||||
| 
 | ||||
|     // Signals to communicate from rx part with the tx part
 | ||||
|     bool isEchoComplete = false;    // Flag that a complete echo is received
 | ||||
|     uint8_t dataConnMsg = 0;  // The DATA_CONN message just seen or 0
 | ||||
|     // Loop once and repeat as long we have rx data available
 | ||||
|     do { | ||||
|         _receiveBuffer[0] = 0x29; | ||||
|         _receiveBuffer[1] = 0; | ||||
|         uint8_t* buffer = _receiveBuffer + 2; | ||||
|         uint8_t rxByte; | ||||
|         bool isEOP = (millis() - _lastByteRxTime > EOP_TIMEOUT); // Flag that an EOP gap is seen
 | ||||
|         switch (_rxState) | ||||
|         { | ||||
|             case RX_WAIT_START: | ||||
|                 if (_platform.uartAvailable()) | ||||
|                 { | ||||
|         // Signals to communicate from rx part with the tx part
 | ||||
|         bool isEchoComplete = false;    // Flag that a complete echo is received
 | ||||
|         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 { | ||||
|             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(); | ||||
| #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_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; | ||||
|                 } | ||||
| 
 | ||||
|                 if (_RxByteCnt == 7) | ||||
|                 { | ||||
|                     //Destination Address + payload available
 | ||||
|                     _xorSum ^= rxByte; | ||||
|                     //check if echo
 | ||||
|                     if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5))) | ||||
|                     { //ignore repeated bit of control byte
 | ||||
|                         _isEcho = true; | ||||
|                     } | ||||
|                     else | ||||
| 
 | ||||
|                     if (_RxByteCnt == 7) | ||||
|                     { | ||||
|                         _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
 | ||||
|                         _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; | ||||
|                         //Destination Address + payload available
 | ||||
|                         //check if echo
 | ||||
|                         if (_sendBuffer != nullptr && (!((buffer[0] ^ _sendBuffer[0]) & ~0x20) && !memcmp(buffer + _convert + 1, _sendBuffer + 1, 5))) | ||||
|                         { //ignore repeated bit of control byte
 | ||||
|                             _isEcho = true; | ||||
|                         } | ||||
|                         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; | ||||
| #ifdef DBG_TRACE | ||||
|                         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 | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         println("frame with invalid crc ignored"); | ||||
|                         _rxState = RX_WAIT_EOP; | ||||
|                         _lastByteTxTime = millis(); | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     _xorSum ^= rxByte; | ||||
|                 } | ||||
|                 break; | ||||
|             case RX_WAIT_EOP: | ||||
|                 if (isEOP) | ||||
|             case TX_WAIT_ECHO: | ||||
|             case TX_WAIT_CONN: | ||||
|                 if (isEchoComplete) | ||||
|                 { | ||||
|                     _RxByteCnt = 0; | ||||
|                     _rxState = RX_WAIT_START; | ||||
|                     _txState = TX_WAIT_CONN; | ||||
| #ifdef DBG_TRACE | ||||
|                     println("RX_WAIT_START"); | ||||
|                     println("TX_WAIT_CONN"); | ||||
| #endif | ||||
|                     break; | ||||
|                 } | ||||
|                 if (!_platform.uartAvailable()) | ||||
|                     break; | ||||
|                 _lastByteRxTime = millis(); | ||||
|                 rxByte = _platform.readUart(); | ||||
|                 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 | ||||
|                 print(rxByte, HEX); | ||||
|                     println("TX_IDLE"); | ||||
| #endif | ||||
|                 break; | ||||
|             default: | ||||
|                 } | ||||
|                 break; | ||||
|         } | ||||
|     } while (_rxState == RX_L_DATA); | ||||
| 
 | ||||
|     // 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; | ||||
|     } | ||||
|     } while (_platform.uartAvailable()); | ||||
| } | ||||
| 
 | ||||
| bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame) | ||||
|  | ||||
| @ -43,6 +43,8 @@ class TpUartDataLinkLayer : public DataLinkLayer | ||||
|     bool _convert = false; | ||||
|     uint8_t _xorSum = 0; | ||||
|     uint32_t _lastByteRxTime; | ||||
|     uint32_t _lastByteTxTime; | ||||
|     uint32_t _lastLoopTime; | ||||
|     uint32_t _waitConfirmStartTime; | ||||
|     uint32_t _lastResetChipTime = 0; | ||||
| 
 | ||||
|  | ||||
| @ -1,18 +1,20 @@ | ||||
| /*-----------------------------------------------------
 | ||||
| 
 | ||||
| Plattform for Raspberry Pi Pico and other RP2040 boards | ||||
| by SirSydom <com@sirsydom.de> 2021-2022 | ||||
| 
 | ||||
| made to work with arduino-pico - "Raspberry Pi Pico Arduino core, for all RP2040 boards" | ||||
| by Earl E. Philhower III https://github.com/earlephilhower/arduino-pico
 | ||||
| tested with V1.9.1 | ||||
| by Earl E. Philhower III https://github.com/earlephilhower/arduino-pico V1.11.0
 | ||||
| 
 | ||||
| by SirSydom <com@sirsydom.de> 2021-2022 | ||||
| 
 | ||||
| RTTI must be set to enabled in the board options | ||||
| 
 | ||||
| Uses direct flash reading/writing. | ||||
| Size ist defined by KNX_FLASH_SIZE (default 4k). | ||||
| Offset in Flash is defined by KNX_FLASH_OFFSET (default 1,5MiB / 0x180000). | ||||
| EEPROM Emulation from arduino-pico core (max 4k) can be use by defining USE_RP2040_EEPROM_EMULATION | ||||
| 
 | ||||
| 
 | ||||
| ----------------------------------------------------*/ | ||||
| 
 | ||||
| #include "rp2040_arduino_platform.h" | ||||
| @ -46,6 +48,19 @@ RP2040ArduinoPlatform::RP2040ArduinoPlatform( HardwareSerial* s) : ArduinoPlatfo | ||||
|     #endif | ||||
| } | ||||
| 
 | ||||
| void RP2040ArduinoPlatform::setupUart() | ||||
| { | ||||
|     SerialUART* serial = dynamic_cast<SerialUART*>(_knxSerial); | ||||
|     if(serial) | ||||
|     { | ||||
|         serial->setPollingMode(); | ||||
|     } | ||||
| 
 | ||||
|     _knxSerial->begin(19200, SERIAL_8E1); | ||||
|     while (!_knxSerial)  | ||||
|         ; | ||||
| } | ||||
| 
 | ||||
| uint32_t RP2040ArduinoPlatform::uniqueSerialNumber() | ||||
| { | ||||
|     pico_unique_board_id_t id;      // 64Bit unique serial number from the QSPI flash
 | ||||
|  | ||||
| @ -19,6 +19,8 @@ public: | ||||
|     RP2040ArduinoPlatform(); | ||||
|     RP2040ArduinoPlatform( HardwareSerial* s); | ||||
| 
 | ||||
|     void setupUart(); | ||||
| 
 | ||||
|     // unique serial number
 | ||||
|     uint32_t uniqueSerialNumber(); //override; 
 | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user