From 57b1950e38de1e26e17aec6e815a6b1b6043214a Mon Sep 17 00:00:00 2001 From: SirSydom Date: Wed, 22 Sep 2021 23:51:21 +0200 Subject: [PATCH 01/12] support DPT9.009 (airflow) and DPT9.029 (absolute humidity) (#149) * added support for RP2040 (Raspberry Pi Pico) * support DPT9.009 (airflow) and DPT9.029 (absolute humidity) --- src/knx/dptconvert.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index e595238..a5d8d5b 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -55,7 +55,7 @@ int KNX_Decode_Value(uint8_t* payload, size_t payload_length, const Dpt& datatyp if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) return busValueToTimeDelta(payload, payload_length, datatype, value); // DPT 9.* - 16 Bit Float - if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11 && datatype.subGroup != 9) || (datatype.subGroup >= 20 && datatype.subGroup <= 28)) && !datatype.index) + if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11) || (datatype.subGroup >= 20 && datatype.subGroup <= 29)) && !datatype.index) return busValueToFloat16(payload, payload_length, datatype, value); // DPT 10.* - Time and Weekday if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1) @@ -172,7 +172,7 @@ int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_len if (datatype.mainGroup == 8 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) return valueToBusValueTimeDelta(value, payload, payload_length, datatype); // DPT 9.* - 16 Bit Float - if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11 && datatype.subGroup != 9) || (datatype.subGroup >= 20 && datatype.subGroup <= 28)) && !datatype.index) + if (datatype.mainGroup == 9 && ((datatype.subGroup >= 1 && datatype.subGroup <= 11 ) || (datatype.subGroup >= 20 && datatype.subGroup <= 29)) && !datatype.index) return valueToBusValueFloat16(value, payload, payload_length, datatype); // DPT 10.* - Time and Weekday if (datatype.mainGroup == 10 && datatype.subGroup == 1 && datatype.index <= 1) From 616599cf8b6be2fca0fe062e18903a26483f47f4 Mon Sep 17 00:00:00 2001 From: rueckix <39458989+rueckix@users.noreply.github.com> Date: Sun, 17 Oct 2021 18:19:45 +0200 Subject: [PATCH 02/12] Fix EEPROM include on STM32 (#151) The structure of the stm32 arduino core changed (https://github.com/stm32duino/Arduino_Core_STM32/tree/main/libraries/EEPROM/src). stm32_eeprom.h was moved to a subfolder. Instead, we can now include (and potentially use later), the `EEPROM.h` header. --- src/stm32_platform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stm32_platform.cpp b/src/stm32_platform.cpp index 4e70231..8fbfaa3 100644 --- a/src/stm32_platform.cpp +++ b/src/stm32_platform.cpp @@ -1,7 +1,7 @@ #include "stm32_platform.h" #ifdef ARDUINO_ARCH_STM32 -#include +#include #include "knx/bits.h" Stm32Platform::Stm32Platform() From 87edd3dfe01398f56af3bf97633dc9fbd90f6d76 Mon Sep 17 00:00:00 2001 From: Sonnengruesser <36325150+Sonnengruesser@users.noreply.github.com> Date: Mon, 13 Dec 2021 11:17:36 +0100 Subject: [PATCH 03/12] Fix callback sequence (#153) Save-/restore callbacks need to be defined before knx.readMemory() to ensure the restore callback is called. --- examples/knx-bme680/knx-bme680.ino | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/knx-bme680/knx-bme680.ino b/examples/knx-bme680/knx-bme680.ino index f10a723..332bddf 100644 --- a/examples/knx-bme680/knx-bme680.ino +++ b/examples/knx-bme680/knx-bme680.ino @@ -53,6 +53,10 @@ void setup(void) wifiManager.autoConnect("knx-bme680"); #endif + // set save and restore callbacks + knx.setSaveCallback(saveBme680State); + knx.setRestoreCallback(loadBme680State); + // read adress table, association table, groupobject table and parameters from eeprom knx.readMemory(); @@ -60,7 +64,6 @@ void setup(void) if(knx.configured()) goTriggerSample.callback(triggerCallback); - // Configure Wire pins before this call if needed. Wire.begin(); // depends on sensor board. Try BME680_I2C_ADDR_PRIMARY if it doen't work. @@ -87,9 +90,6 @@ void setup(void) BSEC_OUTPUT_GAS_PERCENTAGE }; - knx.setSaveCallback(saveBme680State); - knx.setRestoreCallback(loadBme680State); - if (knx.configured()) { cyclSend = knx.paramInt(0); From 63ff2c5d4d15e2633872d2fcc05135f6381c77af Mon Sep 17 00:00:00 2001 From: mptei Date: Wed, 22 Dec 2021 19:59:55 +0100 Subject: [PATCH 04/12] Removed doubled code (#158) --- src/knx/dptconvert.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index a5d8d5b..2700478 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -22,12 +22,6 @@ int KNX_Decode_Value(uint8_t* payload, size_t payload_length, const Dpt& datatyp if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1) return busValueToBinaryControl(payload, payload_length, datatype, value); // DPT 3.* - Step Control - if (datatype.mainGroup == 3 && datatype.subGroup >= 7 && datatype.subGroup <= 8 && datatype.index <= 1) - return busValueToStepControl(payload, payload_length, datatype, value); - // DPT 4.* - Character// DPT 2.* - Binary Control - if (datatype.mainGroup == 2 && datatype.subGroup >= 1 && datatype.subGroup <= 12 && datatype.index <= 1) - return busValueToBinaryControl(payload, payload_length, datatype, value); - // DPT 3.* - Step Control if (datatype.mainGroup == 3 && datatype.subGroup >= 7 && datatype.subGroup <= 8 && datatype.index <= 1) return busValueToStepControl(payload, payload_length, datatype, value); // DPT 4.* - Character From eb7ae16ddee71d42ed9448a8ccee6c7367eeb15d Mon Sep 17 00:00:00 2001 From: mptei Date: Wed, 22 Dec 2021 20:00:27 +0100 Subject: [PATCH 05/12] Returning correct value for ULongType. (#157) --- src/knx/knx_value.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/knx/knx_value.cpp b/src/knx/knx_value.cpp index 79ee503..c8d9f54 100644 --- a/src/knx/knx_value.cpp +++ b/src/knx/knx_value.cpp @@ -318,7 +318,7 @@ uint64_t KNXValue::ulongValue() const switch (_type) { case ULongType: - return _value.uintValue; + return _value.ulongValue; case BoolType: return _value.boolValue ? 1 : 0; case UCharType: From fb74931bec618c32db48f7b2732a558e083fab16 Mon Sep 17 00:00:00 2001 From: Domos <41550963+Domos-Snips@users.noreply.github.com> Date: Thu, 23 Dec 2021 20:04:34 +0100 Subject: [PATCH 06/12] Add 2 new methods: paramSignedByte and paramBit. Comments and usage inside code (#159) --- src/knx_facade.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/knx_facade.h b/src/knx_facade.h index f2830a3..b1ccb1b 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -294,6 +294,40 @@ template class KnxFacade : private SaveRestore return _bau.parameters().data(addr); } + // paramBit(address, shift) + // get state of a parameter as a boolean like "enable/disable", ... + // Declaration in XML file: + // ... + // + // + // + // + // + // + // ... + // + // + // + // + // + // + // + // + // + // ... + // Usage in code : + // if ( knx.paramBit(1,1)) + // { + // //do somthings .... + // } + bool paramBit(uint32_t addr, uint8_t shift) + { + if (!_bau.configured()) + return 0; + + return (bool) ((_bau.parameters().getByte(addr) >> (7-shift)) & 0x01); + } + uint8_t paramByte(uint32_t addr) { if (!_bau.configured()) @@ -301,7 +335,20 @@ template class KnxFacade : private SaveRestore return _bau.parameters().getByte(addr); } + + // Same usage than paramByte(addresse) for signed parameters + // Declaration in XML file + // + // + // + int8_t paramSignedByte(uint32_t addr) + { + if (!_bau.configured()) + return 0; + return (int8_t) _bau.parameters().getByte(addr); + } + uint16_t paramWord(uint32_t addr) { if (!_bau.configured()) From 12d0ea1ad89f41fb2b77d73401f45c3dc0f18112 Mon Sep 17 00:00:00 2001 From: mptei Date: Tue, 28 Dec 2021 19:53:48 +0100 Subject: [PATCH 07/12] Use full duplex in tpuart_data_link_layer. (#161) * TPUART full duplex handling * Stay in loop when RX_L_DATA. --- src/knx/tpuart_data_link_layer.cpp | 568 ++++++++++++++++------------- src/knx/tpuart_data_link_layer.h | 5 +- 2 files changed, 316 insertions(+), 257 deletions(-) diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index fe0cb8f..c23fcf4 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -11,6 +11,9 @@ #include #include +// Activate trace output +//#define DBG_TRACE + // NCN5120 //#define NCN5120 @@ -75,25 +78,28 @@ #define U_STOP_MODE_IND 0x2B #define U_SYSTEM_STAT_IND 0x4B -//loop states -#define IDLE 0 -#define RX_FIRST_BYTE 1 -#define RX_L_DATA 2 -#define RX_WAIT_DATA_CON 3 -#define TX_FRAME 4 +//tx states +enum { + TX_IDLE, + TX_FRAME, + TX_WAIT_ECHO, + TX_WAIT_CONN +}; -#define BYTE_TIMEOUT 10 //milli seconds +//rx states +enum { + RX_WAIT_START, + RX_L_DATA, + RX_WAIT_EOP +}; + +#define EOP_TIMEOUT 2 //milli seconds; end of layer-2 packet gap #define CONFIRM_TIMEOUT 500 //milli seconds #define RESET_TIMEOUT 100 //milli seconds void TpUartDataLinkLayer::loop() { - _receiveBuffer[0] = 0x29; - _receiveBuffer[1] = 0; - uint8_t* buffer = _receiveBuffer + 2; - uint8_t rxByte; - if (!_enabled) { if (millis() - _lastResetChipTime > 1000) @@ -107,266 +113,317 @@ void TpUartDataLinkLayer::loop() if (!_enabled) return; - switch (_loopState) - { - case IDLE: - if (_platform.uartAvailable()) - { - _loopState = RX_FIRST_BYTE; - } - else - { - if (!_waitConfirm && !isTxQueueEmpty()) + do { + _receiveBuffer[0] = 0x29; + _receiveBuffer[1] = 0; + uint8_t* buffer = _receiveBuffer + 2; + uint8_t rxByte; + bool isEchoComplete = false; // Flag that a complete echo is received + bool dataConnMsg = 0; // The DATA_CONN message just seen or 0 + bool isEOP = (millis() - _lastByteRxTime > EOP_TIMEOUT); // Flag that an EOP gap is seen + switch (_rxState) + { + case RX_WAIT_START: + if (_platform.uartAvailable()) { - loadNextTxFrame(); - _loopState = TX_FRAME; - } - } - break; - case TX_FRAME: - if (sendSingleFrameByte() == false) - { - _waitConfirm = true; - _waitConfirmStartTime = millis(); - _loopState = IDLE; - } - break; - case RX_FIRST_BYTE: - rxByte = _platform.readUart(); - _lastByteRxTime = millis(); - _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; - _loopState = RX_L_DATA; - break; - } - else if ((rxByte & L_DATA_MASK) == L_DATA_EXTENDED_IND) - { - buffer[_RxByteCnt++] = rxByte; - _xorSum ^= rxByte; - _convert = false; - _loopState = RX_L_DATA; - break; - } - else if ((rxByte & L_DATA_CON_MASK) == L_DATA_CON) - { - println("got unexpected L_DATA_CON"); - } - 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: 0x"); - print(rxByte, HEX); - 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; + rxByte = _platform.readUart(); +#ifdef DBG_TRACE + print(rxByte, HEX); +#endif + _lastByteRxTime = millis(); - print(tmp, HEX); - break; - } - println(); - } - else - { - print("got UNEXPECTED: 0x"); - print(rxByte, HEX); - println(); - } - _loopState = IDLE; - break; - case RX_L_DATA: - if (millis() - _lastByteRxTime > BYTE_TIMEOUT) - { - _RxByteCnt = 0; - _loopState = IDLE; - println("Timeout during RX_L_DATA"); - break; - } - if (!_platform.uartAvailable()) - break; - _lastByteRxTime = millis(); - rxByte = _platform.readUart(); - - if (_RxByteCnt == MAX_KNX_TELEGRAM_SIZE) - { - _loopState = IDLE; - 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 - { - _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)) + // Check for layer-2 packets + _RxByteCnt = 0; + _xorSum = 0; + if ((rxByte & L_DATA_MASK) == L_DATA_STANDARD_IND) { - c |= 0x01; + 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; } - _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) + // Handle all single byte packets here + else if ((rxByte & L_DATA_CON_MASK) == L_DATA_CON) { - //check if it is realy an echo, rx_crc = tx_crc - if (rxByte == _sendBuffer[_sendBufferLength - 1]) - _isEcho = true; - else - _isEcho = false; + dataConnMsg = rxByte; } - if (_isEcho) + else if (rxByte == L_POLL_DATA_IND) { - _loopState = RX_WAIT_DATA_CON; + // 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 { - frameBytesReceived(_receiveBuffer, _RxByteCnt + 2); - _loopState = IDLE; + 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 + { + _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; + } + else + { + 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 { - println("frame with invalid crc ignored"); - _loopState = IDLE; + _xorSum ^= rxByte; } - } - else - { - _xorSum ^= rxByte; - } - break; - case RX_WAIT_DATA_CON: - if (!_platform.uartAvailable()) break; - rxByte = _platform.readUart(); - _lastByteRxTime = millis(); - if ((rxByte & L_DATA_CON_MASK) == L_DATA_CON) - { - //println("L_DATA_CON received"); - dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, ((rxByte & SUCCESS) > 0)); - _waitConfirm = false; - delete[] _sendBuffer; - _sendBuffer = 0; - _sendBufferLength = 0; - _loopState = IDLE; - } - else - { - //should not happen - println("expected L_DATA_CON not received"); - dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, false); - _waitConfirm = false; - delete[] _sendBuffer; - _sendBuffer = 0; - _sendBufferLength = 0; - _loopState = IDLE; - } - break; - default: - break; - } - - if (_waitConfirm) - { - 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); - _waitConfirm = false; - delete[] _sendBuffer; - _sendBuffer = 0; - _sendBufferLength = 0; - if (_loopState == RX_WAIT_DATA_CON) - _loopState = IDLE; + case RX_WAIT_EOP: + if (isEOP) + { + _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; } - } + + // 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 (_rxState == RX_L_DATA); } bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame) @@ -496,6 +553,9 @@ bool TpUartDataLinkLayer::sendSingleFrameByte() cmd[0] = U_L_DATA_END_REQ | _TxByteCnt; cmd[1] = _sendBuffer[_TxByteCnt]; +#ifdef DBG_TRACE + print(cmd[1], HEX); +#endif _platform.writeUart(cmd, 2); _TxByteCnt++; diff --git a/src/knx/tpuart_data_link_layer.h b/src/knx/tpuart_data_link_layer.h index 61fe533..35305f3 100644 --- a/src/knx/tpuart_data_link_layer.h +++ b/src/knx/tpuart_data_link_layer.h @@ -31,16 +31,15 @@ class TpUartDataLinkLayer : public DataLinkLayer private: bool _enabled = false; - bool _waitConfirm = false; uint8_t* _sendBuffer = 0; uint16_t _sendBufferLength = 0; uint8_t _receiveBuffer[MAX_KNX_TELEGRAM_SIZE]; - uint8_t _loopState = 0; + uint8_t _txState = 0; + uint8_t _rxState = 0; uint16_t _RxByteCnt = 0; uint16_t _TxByteCnt = 0; uint8_t _oldIdx = 0; bool _isEcho = false; - bool _isAddressed = false; bool _convert = false; uint8_t _xorSum = 0; uint32_t _lastByteRxTime; From bf70e162f8c1cd74fa1aa2334c6cae59b94df559 Mon Sep 17 00:00:00 2001 From: croghostrider Date: Wed, 29 Dec 2021 17:20:46 +0100 Subject: [PATCH 08/12] fix constant comparison (#162) * fix constant comparison * . --- examples/knx-linux-coupler/fdsk.cpp | 2 +- examples/knx-linux/fdsk.cpp | 2 +- src/knx/association_table_object.cpp | 4 ++-- src/knx/bau_systemB.cpp | 2 +- src/knx/dptconvert.cpp | 10 ++++------ 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/examples/knx-linux-coupler/fdsk.cpp b/examples/knx-linux-coupler/fdsk.cpp index 8d9b28c..bb62d57 100644 --- a/examples/knx-linux-coupler/fdsk.cpp +++ b/examples/knx-linux-coupler/fdsk.cpp @@ -82,7 +82,7 @@ int FdskCalculator::toBase32(uint8_t* in, long length, uint8_t*& out, bool usePa int next = 1; int bitsLeft = 8; - while (count < bufSize && (bitsLeft > 0 || next < length)) + while (bitsLeft > 0 || next < length) { if (bitsLeft < 5) { diff --git a/examples/knx-linux/fdsk.cpp b/examples/knx-linux/fdsk.cpp index 8d9b28c..bb62d57 100644 --- a/examples/knx-linux/fdsk.cpp +++ b/examples/knx-linux/fdsk.cpp @@ -82,7 +82,7 @@ int FdskCalculator::toBase32(uint8_t* in, long length, uint8_t*& out, bool usePa int next = 1; int bitsLeft = 8; - while (count < bufSize && (bitsLeft > 0 || next < length)) + while (bitsLeft > 0 || next < length) { if (bitsLeft < 5) { diff --git a/src/knx/association_table_object.cpp b/src/knx/association_table_object.cpp index c78b244..0880fc7 100644 --- a/src/knx/association_table_object.cpp +++ b/src/knx/association_table_object.cpp @@ -25,7 +25,7 @@ uint16_t AssociationTableObject::entryCount() uint16_t AssociationTableObject::getTSAP(uint16_t idx) { - if (idx < 0 || idx >= entryCount()) + if (idx >= entryCount()) return 0; return ntohs(_tableData[2 * idx + 1]); @@ -33,7 +33,7 @@ uint16_t AssociationTableObject::getTSAP(uint16_t idx) uint16_t AssociationTableObject::getASAP(uint16_t idx) { - if (idx < 0 || idx >= entryCount()) + if (idx >= entryCount()) return 0; return ntohs(_tableData[2 * idx + 2]); diff --git a/src/knx/bau_systemB.cpp b/src/knx/bau_systemB.cpp index 39bc894..7eee281 100644 --- a/src/knx/bau_systemB.cpp +++ b/src/knx/bau_systemB.cpp @@ -483,7 +483,7 @@ bool BauSystemB::restartRequest(uint16_t asap, const SecurityControl secCtrl) void BauSystemB::connectConfirm(uint16_t tsap) { - if (_restartState == Connecting && tsap >= 0) + if (_restartState == Connecting) { /* restart connection is confirmed, go to the next state */ _restartState = Connected; diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index 2700478..9942f0a 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -797,8 +797,6 @@ int busValueToRGB(const uint8_t* payload, size_t payload_length, const Dpt& data { ASSERT_PAYLOAD(3); uint32_t rgb = unsigned16FromPayload(payload, 0) * 256 + unsigned8FromPayload(payload, 2); - if (rgb > 16777215) - return false; value = rgb; return true; } @@ -886,7 +884,7 @@ int valueToBusValueStepControl(const KNXValue& value, uint8_t* payload, size_t p int valueToBusValueCharacter(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) { - if ((uint64_t)value < INT64_C(0) || (uint64_t)value > INT64_C(255) || (datatype.subGroup == 1 && (uint64_t)value > INT64_C(127))) + if ((uint64_t)value > INT64_C(255) || (datatype.subGroup == 1 && (uint64_t)value > INT64_C(127))) return false; unsigned8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF); return true; @@ -1153,7 +1151,7 @@ int valueToBusValueAccess(const KNXValue& value, uint8_t* payload, size_t payloa break; case 5: { - if ((uint64_t)value < INT64_C(0) || (uint64_t)value > INT64_C(15)) + if ((uint64_t)value > INT64_C(15)) return false; bcdToPayload(payload, payload_length, 7, (uint64_t)value); break; @@ -1444,7 +1442,7 @@ int valueToBusValueScaling(const KNXValue& value, uint8_t* payload, size_t paylo { uint32_t duration = value; - if (duration < INT64_C(0) || duration > INT64_C(65535)) + if (duration > INT64_C(65535)) return false; ENSURE_PAYLOAD(3); @@ -1471,7 +1469,7 @@ int valueToBusValueTariff(const KNXValue& value, uint8_t* payload, size_t payloa { uint32_t duration = value; - if (duration < INT64_C(0) || duration > INT64_C(65535)) + if (duration > INT64_C(65535)) return false; ENSURE_PAYLOAD(3); From f5feefb0f260b55f84d130763e022a3270b90e76 Mon Sep 17 00:00:00 2001 From: mptei Date: Sun, 16 Jan 2022 18:25:32 +0100 Subject: [PATCH 09/12] TPUART: Avoid false EOP (#166) * Made the rx loop shorter to avoid tx buffer saturation. * sendSingleFrameByte return false on last byte * sendSingleFrameByte return false on last byte --- src/knx/tpuart_data_link_layer.cpp | 145 +++++++++++++++-------------- 1 file changed, 74 insertions(+), 71 deletions(-) diff --git a/src/knx/tpuart_data_link_layer.cpp b/src/knx/tpuart_data_link_layer.cpp index c23fcf4..96f41f7 100644 --- a/src/knx/tpuart_data_link_layer.cpp +++ b/src/knx/tpuart_data_link_layer.cpp @@ -113,13 +113,14 @@ 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 do { _receiveBuffer[0] = 0x29; _receiveBuffer[1] = 0; uint8_t* buffer = _receiveBuffer + 2; uint8_t rxByte; - bool isEchoComplete = false; // Flag that a complete echo is received - bool dataConnMsg = 0; // The DATA_CONN message just seen or 0 bool isEOP = (millis() - _lastByteRxTime > EOP_TIMEOUT); // Flag that an EOP gap is seen switch (_rxState) { @@ -356,74 +357,74 @@ void TpUartDataLinkLayer::loop() default: break; } - - // 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 (_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; + } } bool TpUartDataLinkLayer::sendFrame(CemiFrame& frame) @@ -559,13 +560,15 @@ bool TpUartDataLinkLayer::sendSingleFrameByte() _platform.writeUart(cmd, 2); _TxByteCnt++; - return true; } - else + + // Check for last byte send + if (_TxByteCnt >= _sendBufferLength) { _TxByteCnt = 0; return false; } + return true; } void TpUartDataLinkLayer::addFrameTxQueue(CemiFrame& frame) From 71e8607f43c58f9c2642c10900efc335b607d930 Mon Sep 17 00:00:00 2001 From: mptei Date: Sun, 16 Jan 2022 18:26:51 +0100 Subject: [PATCH 10/12] Added support for DPT 251.600 RGBW (#167) * Added support for DPT 251.600 RGBW * style fix --- src/knx/dpt.h | 1 + src/knx/dptconvert.cpp | 45 +++++++++++++++++++++++++++++++++++++++++- src/knx/dptconvert.h | 2 ++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/knx/dpt.h b/src/knx/dpt.h index 5fc45fe..f6dcef3 100644 --- a/src/knx/dpt.h +++ b/src/knx/dpt.h @@ -357,6 +357,7 @@ #define DPT_FlaggedScaling Dpt(239, 1) #define DPT_CombinedPosition Dpt(240, 800) #define DPT_StatusSAB Dpt(241, 800) +#define DPT_Colour_RGBW Dpt(251, 600) class Dpt { diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index 9942f0a..16dc9e3 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -126,6 +126,9 @@ int KNX_Decode_Value(uint8_t* payload, size_t payload_length, const Dpt& datatyp // DPT 239.* - Flagged Scaling if (datatype.mainGroup == 239 && datatype.subGroup == 1 && datatype.index <= 1) return busValueToFlaggedScaling(payload, payload_length, datatype, value); + // DPT 251.600 - RGBW + if (datatype.mainGroup == 251 && datatype.subGroup == 600 && datatype.index <= 1) + return busValueToRGBW(payload, payload_length, datatype, value); } return false; } @@ -243,6 +246,9 @@ int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_len // DPT 239.* - Flagged Scaling if (datatype.mainGroup == 239 && datatype.subGroup == 1 && datatype.index <= 1) return valueToBusValueFlaggedScaling(value, payload, payload_length, datatype); + // DPT 251.600 - RGBW + if (datatype.mainGroup == 251 && datatype.subGroup == 600 && datatype.index <= 1) + return valueToBusValueRGBW(value, payload, payload_length, datatype); return false; } @@ -801,6 +807,24 @@ int busValueToRGB(const uint8_t* payload, size_t payload_length, const Dpt& data return true; } +int busValueToRGBW(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value) +{ + ASSERT_PAYLOAD(6); + switch (datatype.index) { + case 0: // The RGBW value + { + uint32_t rgbw = (unsigned32FromPayload(payload, 0) >> 8) + + (unsigned8FromPayload(payload, 3) << 24); + value = rgbw; + } + return true; + case 1: // The mask bits only + value = unsigned8FromPayload(payload,5); + return true; + } + return false; +} + int busValueToFlaggedScaling(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value) { ASSERT_PAYLOAD(2); @@ -1517,6 +1541,26 @@ int valueToBusValueRGB(const KNXValue& value, uint8_t* payload, size_t payload_l return true; } +int valueToBusValueRGBW(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) +{ + switch(datatype.index) + { + case 0: // RGBW + { + uint32_t rgbw = (uint32_t)value; + unsigned16ToPayload(payload, payload_length, 0, rgbw >> 8, 0xffff); // RG + unsigned8ToPayload(payload, payload_length, 2, rgbw, 0xff); // B + unsigned8ToPayload(payload, payload_length, 3, rgbw >> 24, 0xff); // W + } + break; + case 1: // Mask bits + unsigned8ToPayload(payload, payload_length, 5, (uint8_t)value, 0xff); + break; + + } + return true; +} + int valueToBusValueFlaggedScaling(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) { switch (datatype.index) @@ -1545,7 +1589,6 @@ int valueToBusValueActiveEnergy(const KNXValue& value, uint8_t* payload, size_t { case 0: { - if ((int64_t)value < INT64_C(-2147483648) || (int64_t)value > INT64_C(2147483647)) return false; ENSURE_PAYLOAD(6); diff --git a/src/knx/dptconvert.h b/src/knx/dptconvert.h index 9256b51..f341df8 100644 --- a/src/knx/dptconvert.h +++ b/src/knx/dptconvert.h @@ -78,6 +78,7 @@ int busValueToScaling(const uint8_t* payload, size_t payload_length, const Dpt& int busValueToTariff(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToLocale(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToRGB(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); +int busValueToRGBW(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToFlaggedScaling(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); int busValueToActiveEnergy(const uint8_t* payload, size_t payload_length, const Dpt& datatype, KNXValue& value); @@ -116,6 +117,7 @@ int valueToBusValueScaling(const KNXValue& value, uint8_t* payload, size_t paylo int valueToBusValueTariff(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueLocale(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueRGB(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); +int valueToBusValueRGBW(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueFlaggedScaling(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); int valueToBusValueActiveEnergy(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype); From 36e0a00e80160ef8bf54451eac91a0f3acb47fc6 Mon Sep 17 00:00:00 2001 From: dev-git-usr <56093270+dev-git-usr@users.noreply.github.com> Date: Sun, 16 Jan 2022 18:56:00 +0100 Subject: [PATCH 11/12] Added Datapointtype DPT 7.600 (colortemperature) (#165) * Added Datapointtype DPT 7.600 (colortemperature) * Added Decoding of Datatype --- src/knx/dptconvert.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index 16dc9e3..bb3ecdd 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -36,8 +36,8 @@ int KNX_Decode_Value(uint8_t* payload, size_t payload_length, const Dpt& datatyp // DPT 6.020 - Status with Mode if (datatype.mainGroup == 6 && datatype.subGroup == 20 && datatype.index <= 5) return busValueToStatusAndMode(payload, payload_length, datatype, value); - // DPT 7.001/7.010/7.011/7.012/7.013 - Unsigned 16 Bit Integer - if (datatype.mainGroup == 7 && (datatype.subGroup == 1 || (datatype.subGroup >= 10 && datatype.subGroup <= 13)) && !datatype.index) + // DPT 7.001/7.010/7.011/7.012/7.013/7.600 - Unsigned 16 Bit Integer + if (datatype.mainGroup == 7 && (datatype.subGroup == 1 || (datatype.subGroup >= 10 && datatype.subGroup <= 13) || (datatype.subGroup == 600)) && !datatype.index) return busValueToUnsigned16(payload, payload_length, datatype, value); // DPT 7.002-DPT 7.007 - Time Period if (datatype.mainGroup == 7 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) @@ -156,8 +156,8 @@ int KNX_Encode_Value(const KNXValue& value, uint8_t* payload, size_t payload_len // DPT 6.020 - Status with Mode if (datatype.mainGroup == 6 && datatype.subGroup == 20 && datatype.index <= 5) return valueToBusValueStatusAndMode(value, payload, payload_length, datatype); - // DPT 7.001/7.010/7.011/7.012/7.013 - Unsigned 16 Bit Integer - if (datatype.mainGroup == 7 && (datatype.subGroup == 1 || (datatype.subGroup >= 10 && datatype.subGroup <= 13)) && !datatype.index) + // DPT 7.001/7.010/7.011/7.012/7.013/7.600 - Unsigned 16 Bit Integer + if (datatype.mainGroup == 7 && (datatype.subGroup == 1 || (datatype.subGroup >= 10 && datatype.subGroup <= 13) || datatype.subGroup == 600) && !datatype.index) return valueToBusValueUnsigned16(value, payload, payload_length, datatype); // DPT 7.002-DPT 7.007 - Time Period if (datatype.mainGroup == 7 && datatype.subGroup >= 2 && datatype.subGroup <= 7 && !datatype.index) From 6720f86e5cb68d404d1e2e6b72ee32648702a65a Mon Sep 17 00:00:00 2001 From: mptei Date: Wed, 19 Jan 2022 14:51:00 +0100 Subject: [PATCH 12/12] Changed color byte order from WRGB to RGBW (R MSB). (#168) --- src/knx/dptconvert.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/knx/dptconvert.cpp b/src/knx/dptconvert.cpp index bb3ecdd..6fc644f 100644 --- a/src/knx/dptconvert.cpp +++ b/src/knx/dptconvert.cpp @@ -813,8 +813,7 @@ int busValueToRGBW(const uint8_t* payload, size_t payload_length, const Dpt& dat switch (datatype.index) { case 0: // The RGBW value { - uint32_t rgbw = (unsigned32FromPayload(payload, 0) >> 8) - + (unsigned8FromPayload(payload, 3) << 24); + uint32_t rgbw = unsigned32FromPayload(payload, 0); value = rgbw; } return true; @@ -1548,13 +1547,11 @@ int valueToBusValueRGBW(const KNXValue& value, uint8_t* payload, size_t payload_ case 0: // RGBW { uint32_t rgbw = (uint32_t)value; - unsigned16ToPayload(payload, payload_length, 0, rgbw >> 8, 0xffff); // RG - unsigned8ToPayload(payload, payload_length, 2, rgbw, 0xff); // B - unsigned8ToPayload(payload, payload_length, 3, rgbw >> 24, 0xff); // W + unsigned32ToPayload(payload, payload_length, 0, rgbw, 0xffffffff); // RGBW } break; case 1: // Mask bits - unsigned8ToPayload(payload, payload_length, 5, (uint8_t)value, 0xff); + unsigned8ToPayload(payload, payload_length, 5, (uint8_t)value, 0x0f); break; }