mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +01:00 
			
		
		
		
	Merge branch 'thelsing:master' into master
This commit is contained in:
		
						commit
						6f9efca2fe
					
				| @ -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); | ||||
|  | ||||
| @ -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) | ||||
|       { | ||||
|  | ||||
| @ -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) | ||||
|       { | ||||
|  | ||||
| @ -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]); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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 | ||||
| { | ||||
|  | ||||
| @ -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
 | ||||
| @ -42,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) | ||||
| @ -132,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; | ||||
| } | ||||
| @ -159,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) | ||||
| @ -249,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; | ||||
| } | ||||
| 
 | ||||
| @ -803,12 +803,27 @@ 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; | ||||
| } | ||||
| 
 | ||||
| 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); | ||||
|                 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); | ||||
| @ -892,7 +907,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; | ||||
| @ -1159,7 +1174,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; | ||||
| @ -1450,7 +1465,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); | ||||
| @ -1477,7 +1492,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); | ||||
| @ -1525,6 +1540,24 @@ 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; | ||||
|                 unsigned32ToPayload(payload, payload_length, 0, rgbw, 0xffffffff); // RGBW
 | ||||
|             } | ||||
|             break; | ||||
|         case 1: // Mask bits
 | ||||
|             unsigned8ToPayload(payload, payload_length, 5, (uint8_t)value, 0x0f); | ||||
|             break; | ||||
| 
 | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| int valueToBusValueFlaggedScaling(const KNXValue& value, uint8_t* payload, size_t payload_length, const Dpt& datatype) | ||||
| { | ||||
|     switch (datatype.index) | ||||
| @ -1553,7 +1586,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); | ||||
|  | ||||
| @ -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); | ||||
| 
 | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
| @ -11,6 +11,9 @@ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| // 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,265 +113,317 @@ void TpUartDataLinkLayer::loop() | ||||
|     if (!_enabled) | ||||
|         return; | ||||
| 
 | ||||
|     switch (_loopState) | ||||
|     { | ||||
|         case IDLE: | ||||
|             if (_platform.uartAvailable()) | ||||
|             { | ||||
|                 _loopState = RX_FIRST_BYTE; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 if (!_waitConfirm && !isTxQueueEmpty()) | ||||
|     // 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 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; | ||||
|                     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 | ||||
|                     { | ||||
|                         _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 | ||||
|                 { | ||||
|                     _xorSum ^= rxByte; | ||||
|                 } | ||||
|                 break; | ||||
|             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; | ||||
|         } | ||||
|     } 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) | ||||
|             { | ||||
|                 _waitConfirm = true; | ||||
|                 _waitConfirmStartTime = millis(); | ||||
|                 _loopState = IDLE; | ||||
|                 _txState = TX_WAIT_ECHO; | ||||
| #ifdef DBG_TRACE | ||||
|                 println("TX_WAIT_ECHO"); | ||||
| #endif | ||||
|             } | ||||
|             break; | ||||
|         case RX_FIRST_BYTE: | ||||
|             rxByte = _platform.readUart(); | ||||
|             _lastByteRxTime = millis(); | ||||
|             _RxByteCnt = 0; | ||||
|             _xorSum = 0; | ||||
|             if ((rxByte & L_DATA_MASK) == L_DATA_STANDARD_IND) | ||||
|         case TX_WAIT_ECHO: | ||||
|         case TX_WAIT_CONN: | ||||
|             if (isEchoComplete) | ||||
|             { | ||||
|                 buffer[_RxByteCnt++] = rxByte; | ||||
|                 _xorSum ^= rxByte; | ||||
|                 _RxByteCnt++; //convert to L_DATA_EXTENDED
 | ||||
|                 _convert = true; | ||||
|                 _loopState = RX_L_DATA; | ||||
|                 break; | ||||
|                 _txState = TX_WAIT_CONN; | ||||
| #ifdef DBG_TRACE | ||||
|                 println("TX_WAIT_CONN"); | ||||
| #endif | ||||
|             } | ||||
|             else if ((rxByte & L_DATA_MASK) == L_DATA_EXTENDED_IND) | ||||
|             else if (dataConnMsg) | ||||
|             { | ||||
|                 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; | ||||
| 
 | ||||
|                     print(tmp, HEX); | ||||
|                     break; | ||||
|                 bool waitEcho = (_txState == TX_WAIT_ECHO); | ||||
|                 if (waitEcho) { | ||||
|                     println("L_DATA_CON without echo"); | ||||
|                 } | ||||
|                 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)) | ||||
|                     { | ||||
|                         c |= 0x01; | ||||
|                     } | ||||
| 
 | ||||
|                     _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) | ||||
|                     { | ||||
|                         _loopState = RX_WAIT_DATA_CON; | ||||
|                     } | ||||
|                     else | ||||
|                     { | ||||
|                         frameBytesReceived(_receiveBuffer, _RxByteCnt + 2); | ||||
|                         _loopState = IDLE; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     println("frame with invalid crc ignored"); | ||||
|                     _loopState = IDLE; | ||||
|                 } | ||||
|             } | ||||
|             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; | ||||
|                 dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, !waitEcho && ((dataConnMsg & SUCCESS) > 0)); | ||||
|                 delete[] _sendBuffer; | ||||
|                 _sendBuffer = 0; | ||||
|                 _sendBufferLength = 0; | ||||
|                 _loopState = IDLE; | ||||
|                 _txState = TX_IDLE; | ||||
|             } | ||||
|             else | ||||
|             else if (millis() - _waitConfirmStartTime > CONFIRM_TIMEOUT) | ||||
|             { | ||||
|                 //should not happen
 | ||||
|                 println("expected L_DATA_CON not received"); | ||||
|                 dataConBytesReceived(_receiveBuffer, _RxByteCnt + 2, false); | ||||
|                 _waitConfirm = false; | ||||
|                 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; | ||||
|                 _loopState = IDLE; | ||||
|                 _txState = TX_IDLE; | ||||
| #ifdef DBG_TRACE | ||||
|                 println("TX_IDLE"); | ||||
| #endif | ||||
|             } | ||||
|             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; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| @ -496,16 +554,21 @@ 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++; | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|      | ||||
|     // Check for last byte send
 | ||||
|     if (_TxByteCnt >= _sendBufferLength) | ||||
|     { | ||||
|         _TxByteCnt = 0; | ||||
|         return false; | ||||
|     } | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| void TpUartDataLinkLayer::addFrameTxQueue(CemiFrame& frame) | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -294,6 +294,40 @@ template <class P, class B> 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:
 | ||||
|     // ...
 | ||||
|     // <ParameterType Id="M-00FA_A-0066-EA-0001_PT-toggle" Name="toggle">
 | ||||
|     //   <TypeRestriction Base="Value" SizeInBit="1">
 | ||||
|     //     <Enumeration Text="Désactivé" Value="0" Id="M-00FA_A-0066-EA-0001_PT-toggle_EN-0"/>
 | ||||
|     //     <Enumeration Text="Activé" Value="1" Id="M-00FA_A-0066-EA-0001_PT-toggle_EN-1"/>
 | ||||
|     //  </TypeRestriction>
 | ||||
|     // </ParameterType>
 | ||||
|     // ...
 | ||||
|     // <Parameter Id="M-00FA_A-0066-EA-0001_P-2" Name="Input 1" ParameterType="M-00FA_A-0066-EA-0001_PT-toggle" Text="Input 1" Value="1">
 | ||||
|     //   <Memory CodeSegment="M-00FA_A-0066-EA-0001_RS-04-00000" Offset="1" BitOffset="0"/>
 | ||||
|     // </Parameter>
 | ||||
|     // <Parameter Id="M-00FA_A-0066-EA-0001_P-3" Name="Input 2" ParameterType="M-00FA_A-0066-EA-0001_PT-toggle" Text="Input 2" Value="1">
 | ||||
|     //   <Memory CodeSegment="M-00FA_A-0066-EA-0001_RS-04-00000" Offset="1" BitOffset="1"/>
 | ||||
|     // </Parameter>
 | ||||
|     // <Parameter Id="M-00FA_A-0066-EA-0001_P-4" Name="Inout 3" ParameterType="M-00FA_A-0066-EA-0001_PT-toggle" Text="Input 3" Value="1">
 | ||||
|     //   <Memory CodeSegment="M-00FA_A-0066-EA-0001_RS-04-00000" Offset="1" BitOffset="2"/>
 | ||||
|     // </Parameter>
 | ||||
|     // ...
 | ||||
|     // 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 P, class B> class KnxFacade : private SaveRestore | ||||
| 
 | ||||
|         return _bau.parameters().getByte(addr); | ||||
|     } | ||||
|      | ||||
|     // Same usage than paramByte(addresse) for signed parameters
 | ||||
|     // Declaration in XML file
 | ||||
|     // <ParameterType Id="M-00FA_A-0066-EA-0001_PT-delta" Name="delta">
 | ||||
|     //   <TypeNumber SizeInBit="8" Type="signedInt" minInclusive="-10" maxInclusive="10"/>
 | ||||
|     // </ParameterType>
 | ||||
|     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()) | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| #include "stm32_platform.h" | ||||
| 
 | ||||
| #ifdef ARDUINO_ARCH_STM32 | ||||
| #include <stm32_eeprom.h> | ||||
| #include <EEPROM.h> | ||||
| #include "knx/bits.h" | ||||
| 
 | ||||
| Stm32Platform::Stm32Platform() | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user