Merge branch 'master' into feat_datasecure

This commit is contained in:
Nanosonde 2020-06-25 21:28:51 +02:00
commit 318d350243
21 changed files with 730 additions and 775 deletions

View File

@ -93,6 +93,7 @@
<ClInclude Include="..\..\src\knx\device_object.h" /> <ClInclude Include="..\..\src\knx\device_object.h" />
<ClInclude Include="..\..\src\knx\dpt.h" /> <ClInclude Include="..\..\src\knx\dpt.h" />
<ClInclude Include="..\..\src\knx\dptconvert.h" /> <ClInclude Include="..\..\src\knx\dptconvert.h" />
<ClInclude Include="..\..\src\knx\function_property.h" />
<ClInclude Include="..\..\src\knx\group_object.h" /> <ClInclude Include="..\..\src\knx\group_object.h" />
<ClInclude Include="..\..\src\knx\group_object_table_object.h" /> <ClInclude Include="..\..\src\knx\group_object_table_object.h" />
<ClInclude Include="..\..\src\knx\interface_object.h" /> <ClInclude Include="..\..\src\knx\interface_object.h" />

View File

@ -194,6 +194,9 @@
<ClInclude Include="..\..\src\knx\knx_ip_supported_service_dib.h"> <ClInclude Include="..\..\src\knx\knx_ip_supported_service_dib.h">
<Filter>Header files\knx</Filter> <Filter>Header files\knx</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\knx\function_property.h">
<Filter>Header files\knx</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.cpp"> <ClCompile Include="main.cpp">

View File

@ -487,7 +487,7 @@ void ApplicationLayer::systemNetworkParameterReadResponse(Priority priority, Hop
//TODO: ApplicationLayer::domainAddressSerialNumberWriteRequest() //TODO: ApplicationLayer::domainAddressSerialNumberWriteRequest()
//TODO: ApplicationLayer::domainAddressSerialNumberReadRequest() //TODO: ApplicationLayer::domainAddressSerialNumberReadRequest()
void ApplicationLayer::domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, uint8_t* rfDoA, void ApplicationLayer::domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber) const uint8_t* knxSerialNumber)
{ {
CemiFrame frame(13); CemiFrame frame(13);
@ -506,8 +506,8 @@ void ApplicationLayer::domainAddressSerialNumberReadResponse(Priority priority,
//TODO: ApplicationLayer::IndividualAddressSerialNumberWriteRequest() //TODO: ApplicationLayer::IndividualAddressSerialNumberWriteRequest()
//TODO: ApplicationLayer::IndividualAddressSerialNumberReadRequest() //TODO: ApplicationLayer::IndividualAddressSerialNumberReadRequest()
void ApplicationLayer::IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, uint8_t* rfDoA, void ApplicationLayer::IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
uint8_t* knxSerialNumber) const uint8_t* knxSerialNumber)
{ {
CemiFrame frame(13); CemiFrame frame(13);
APDU& apdu = frame.apdu(); APDU& apdu = frame.apdu();

View File

@ -135,10 +135,10 @@ class ApplicationLayer
void systemNetworkParameterReadResponse(Priority priority, HopCountType hopType, uint16_t objectType, void systemNetworkParameterReadResponse(Priority priority, HopCountType hopType, uint16_t objectType,
uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength, uint16_t propertyId, uint8_t* testInfo, uint16_t testInfoLength,
uint8_t* testResult, uint16_t testResultLength); uint8_t* testResult, uint16_t testResultLength);
void domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, uint8_t* rfDoA, void domainAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber);
void IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, const uint8_t* rfDoA,
const uint8_t* knxSerialNumber); const uint8_t* knxSerialNumber);
void IndividualAddressSerialNumberReadResponse(Priority priority, HopCountType hopType, uint8_t* rfDoA,
uint8_t* knxSerialNumber);
#pragma endregion #pragma endregion
protected: protected:

View File

@ -56,6 +56,9 @@ void BauSystemB::enabled(bool value)
void BauSystemB::sendNextGroupTelegram() void BauSystemB::sendNextGroupTelegram()
{ {
if(!configured())
return;
static uint16_t startIdx = 1; static uint16_t startIdx = 1;
GroupObjectTableObject& table = _groupObjTable; GroupObjectTableObject& table = _groupObjTable;

View File

@ -34,7 +34,7 @@ uint32_t digitalRead(uint32_t dwPin);
typedef void (*voidFuncPtr)(void); typedef void (*voidFuncPtr)(void);
void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode); void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode);
#elif ARDUINO_ARCH_SAMD #elif ARDUINO_ARCH_SAMD || ARDUINO_ARCH_STM32
#include <Arduino.h> #include <Arduino.h>
#define getbyte(x,n) (*(((uint8_t*)&(x))+n)) #define getbyte(x,n) (*(((uint8_t*)&(x))+n))

View File

@ -323,9 +323,9 @@ uint8_t* CemiFrame::rfSerialOrDoA() const
return _rfSerialOrDoA; return _rfSerialOrDoA;
} }
void CemiFrame::rfSerialOrDoA(uint8_t* rfSerialOrDoA) void CemiFrame::rfSerialOrDoA(const uint8_t* rfSerialOrDoA)
{ {
_rfSerialOrDoA = rfSerialOrDoA; _rfSerialOrDoA = (uint8_t*)rfSerialOrDoA;
} }
uint8_t CemiFrame::rfInfo() const uint8_t CemiFrame::rfInfo() const

View File

@ -60,7 +60,7 @@ class CemiFrame
#ifdef USE_RF #ifdef USE_RF
// only for RF medium // only for RF medium
uint8_t* rfSerialOrDoA() const; uint8_t* rfSerialOrDoA() const;
void rfSerialOrDoA(uint8_t* rfSerialOrDoA); void rfSerialOrDoA(const uint8_t* rfSerialOrDoA);
uint8_t rfInfo() const; uint8_t rfInfo() const;
void rfInfo(uint8_t rfInfo); void rfInfo(uint8_t rfInfo);
uint8_t rfLfn() const; uint8_t rfLfn() const;

View File

@ -416,11 +416,11 @@ int busValueToUnsigned8(const uint8_t* payload, size_t payload_length, const Dpt
switch (datatype.subGroup) switch (datatype.subGroup)
{ {
case 1: case 1:
value = (uint8_t)(unsigned8FromPayload(payload, 0) * 100.0 / 255.0); value = (uint8_t)round(unsigned8FromPayload(payload, 0) * 100.0 / 255.0);
return true; return true;
case 3: case 3:
value = (uint8_t)unsigned8FromPayload(payload, 0) * 360.0 / 255.0; value = (uint8_t)round(unsigned8FromPayload(payload, 0) * 360.0 / 255.0);
return true; return true;
case 6: case 6:
@ -1043,7 +1043,7 @@ int valueToBusValueSigned8(const KNXValue& value, uint8_t* payload, size_t paylo
if ((int64_t)value < INT64_C(-128) || (int64_t)value > INT64_C(127)) if ((int64_t)value < INT64_C(-128) || (int64_t)value > INT64_C(127))
return false; return false;
signed8ToPayload(payload, 0, payload_length, (uint64_t)value, 0xFF); signed8ToPayload(payload, payload_length, 0, (uint64_t)value, 0xFF);
return true; return true;
} }
@ -1723,8 +1723,9 @@ double float16FromPayload(const uint8_t* payload, int index)
} }
float float32FromPayload(const uint8_t* payload, int index) float float32FromPayload(const uint8_t* payload, int index)
{ {
uint32_t area = unsigned32FromPayload(payload, index); union { float f; uint32_t i; } area;
return *((float*)&area); area.i = unsigned32FromPayload(payload, index);
return area.f;
} }
int64_t signed64FromPayload(const uint8_t* payload, int index) int64_t signed64FromPayload(const uint8_t* payload, int index)
{ {
@ -1815,8 +1816,9 @@ void float16ToPayload(uint8_t* payload, size_t payload_length, int index, double
} }
void float32ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint32_t mask) void float32ToPayload(uint8_t* payload, size_t payload_length, int index, double value, uint32_t mask)
{ {
float num = value; union { float f; uint32_t i; } num;
unsigned32ToPayload(payload, payload_length, index, *((uint32_t*)&num), mask); num.f = value;
unsigned32ToPayload(payload, payload_length, index, num.i, mask);
} }
void signed64ToPayload(uint8_t* payload, size_t payload_length, int index, int64_t value, uint64_t mask) void signed64ToPayload(uint8_t* payload, size_t payload_length, int index, int64_t value, uint64_t mask)
{ {

View File

@ -7,11 +7,11 @@ class InterfaceObject;
template <class T> class FunctionProperty : public Property template <class T> class FunctionProperty : public Property
{ {
public: public:
FunctionProperty(T* io, PropertyID id, uint8_t access, FunctionProperty(T* io, PropertyID id,
void (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&), void (*commandCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&),
void (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&)) void (*stateCallback)(T*, uint8_t*, uint8_t, uint8_t*, uint8_t&))
: Property(id, false, PDT_FUNCTION, 1, access), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback) : Property(id, false, PDT_FUNCTION, 1, ReadLv0|WriteLv0), _interfaceObject(io), _commandCallback(commandCallback), _stateCallback(stateCallback)
/* max_elements is set to 1, see 3.3.7 Application Layer p.68 */ /* max_elements is set to 1, read and write level any value so we use Lv0, see 3.3.7 Application Layer p.68 */
{} {}
virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override virtual uint8_t read(uint16_t start, uint8_t count, uint8_t* data) const override

View File

@ -10,54 +10,6 @@ InterfaceObject::~InterfaceObject()
} }
void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access) void InterfaceObject::readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access)
{
PropertyDescription* descriptions = propertyDescriptions();
uint8_t count = propertyDescriptionCount();
numberOfElements = 0;
if (descriptions == nullptr || count == 0)
return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access);
PropertyDescription* desc = nullptr;
// from KNX spec. 03.03.07 Application Layer (page 56) - 3.4.3.3 A_PropertyDescription_Read-service
// Summary: either propertyId OR propertyIndex, but not both at the same time
if (propertyId != 0)
{
for (uint8_t i = 0; i < count; i++)
{
PropertyDescription d = descriptions[i];
if (d.Id != propertyId)
continue;
desc = &d;
propertyIndex = i;
break;
}
}
else
{
// If propertyId is zero, propertyIndex shall be used.
// Response: propertyIndex of received A_PropertyDescription_Read
if (propertyIndex < count)
{
desc = &descriptions[propertyIndex];
}
}
if (desc != nullptr)
{
propertyId = desc->Id;
writeEnable = desc->WriteEnable;
type = desc->Type;
numberOfElements = desc->MaxElements;
access = desc->Access;
}
else
return readPropertyDescription2(propertyId, propertyIndex, writeEnable, type, numberOfElements, access);
}
void InterfaceObject::readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access)
{ {
uint8_t count = _propertyCount; uint8_t count = _propertyCount;
@ -161,17 +113,6 @@ void InterfaceObject::state(PropertyID id, uint8_t* data, uint8_t length, uint8_
prop->state(data, length, resultData, resultLength); prop->state(data, length, resultData, resultLength);
} }
uint8_t InterfaceObject::propertyDescriptionCount()
{
return 0;
}
PropertyDescription* InterfaceObject::propertyDescriptions()
{
return nullptr;
}
void InterfaceObject::initializeProperties(size_t propertiesSize, Property** properties) void InterfaceObject::initializeProperties(size_t propertiesSize, Property** properties)
{ {
_propertyCount = propertiesSize / sizeof(Property*); _propertyCount = propertiesSize / sizeof(Property*);

View File

@ -147,9 +147,7 @@ class InterfaceObject : public SaveRestore
* *
* @param[out] access the ::AccessLevel necessary to read/write the property. * @param[out] access the ::AccessLevel necessary to read/write the property.
*/ */
// TODO: remove first version after complete property refactoring
void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access); void readPropertyDescription(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
void readPropertyDescription2(uint8_t& propertyId, uint8_t& propertyIndex, bool& writeEnable, uint8_t& type, uint16_t& numberOfElements, uint8_t& access);
/** /**
* Gets property with PropertyID id if it exists and nullptr otherwise. * Gets property with PropertyID id if it exists and nullptr otherwise.
@ -184,15 +182,6 @@ class InterfaceObject : public SaveRestore
virtual uint16_t saveSize() override; virtual uint16_t saveSize() override;
protected: protected:
/**
* Returns the number of properties the interface object has.
*/
virtual uint8_t propertyDescriptionCount();
/**
* Returns a pointer to the first PropertyDescription of the interface object.
* This is used by readPropertyDescription() together with propertyCount().
*/
virtual PropertyDescription* propertyDescriptions();
/** /**
* Intializes the Property-array the the supplied values. * Intializes the Property-array the the supplied values.

View File

@ -1,141 +1,60 @@
#include <cstring> #include <cstring>
#include "rf_medium_object.h" #include "rf_medium_object.h"
#include "bits.h" #include "bits.h"
#include "data_property.h"
#include "function_property.h"
#include "config.h" #include "config.h"
#ifdef USE_RF #ifdef USE_RF
void RfMediumObject::readProperty(PropertyID propertyId, uint16_t start, uint8_t& count, uint8_t* data) RfMediumObject::RfMediumObject()
{ {
switch (propertyId) uint8_t rfDomainAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // see KNX RF S-Mode AN160 p.11
Property* properties[] =
{ {
case PID_OBJECT_TYPE: new DataProperty(PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0, (uint16_t)OT_RF_MEDIUM),
pushWord(OT_RF_MEDIUM, data); new DataProperty(PID_RF_MULTI_TYPE, true, PDT_GENERIC_01, 1, ReadLv3 | WriteLv2, (uint8_t)0x00),
break; new DataProperty(PID_RF_RETRANSMITTER, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0, (uint8_t)0x00),
case PID_RF_MULTI_TYPE: new DataProperty(PID_RF_DOMAIN_ADDRESS, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv2, rfDomainAddress),
data[0] = 0x00; // KNX RF ready only new FunctionProperty<RfMediumObject>(this, PID_RF_BIDIR_TIMEOUT,
break; [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
case PID_RF_DOMAIN_ADDRESS:
pushByteArray((uint8_t*)_rfDomainAddress, 6, data);
break;
case PID_RF_RETRANSMITTER:
data[0] = 0x00; // No KNX RF retransmitter
break;
case PID_RF_BIDIR_TIMEOUT: // PDT_FUNCTION
data[0] = 0x00; // success
data[1] = 0xFF; // permanent bidirectional device
data[2] = 0xFF; // permanent bidirectional device
break;
case PID_RF_DIAG_SA_FILTER_TABLE: // PDT_GENERIC_03[]
pushByteArray((uint8_t*)_rfDiagSourceAddressFilterTable, 24, data);
break;
case PID_RF_DIAG_BUDGET_TABLE:
pushByteArray((uint8_t*)_rfDiagLinkBudgetTable, 24, data);
break;
case PID_RF_DIAG_PROBE: // PDT_FUNCTION
// Not supported yet
break;
default:
count = 0;
}
}
void RfMediumObject::writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count)
{
switch (id)
{ {
case PID_RF_MULTI_TYPE: resultData[0] = 0x00; // success
// We only support RF ready and not RF multi, ignore write request resultData[1] = 0xFF; // permanent bidirectional device
break; resultData[2] = 0xFF; // permanent bidirectional device
case PID_RF_DOMAIN_ADDRESS: resultLength = 3;
for (uint8_t i = start; i < start + count; i++) },
_rfDomainAddress[i-1] = data[i - start]; [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
break;
case PID_RF_BIDIR_TIMEOUT: // PDT_FUNCTION
// Not supported yet (permanent bidir device)
break;
case PID_RF_DIAG_SA_FILTER_TABLE:
for (uint8_t i = start; i < start + count; i++)
_rfDiagSourceAddressFilterTable[i-1] = data[i - start];
break;
case PID_RF_DIAG_BUDGET_TABLE:
for (uint8_t i = start; i < start + count; i++)
_rfDiagLinkBudgetTable[i-1] = data[i - start];
break;
case PID_RF_DIAG_PROBE:
// Not supported yet
break;
default:
count = 0;
break;
}
}
uint8_t RfMediumObject::propertySize(PropertyID id)
{
switch (id)
{ {
case PID_RF_MULTI_TYPE: resultData[0] = 0x00; // success
case PID_RF_RETRANSMITTER: resultData[1] = 0xFF; // permanent bidirectional device
return 1; resultData[2] = 0xFF; // permanent bidirectional device
case PID_OBJECT_TYPE: resultLength = 3;
return 2; }),
case PID_RF_DOMAIN_ADDRESS: /* This properties are used in NMP_LinkBudget_Measure to diagnose the Link Budget of the communication.
return 6; This in not implemented yet.
case PID_RF_DIAG_SA_FILTER_TABLE: new DataProperty(PID_RF_DIAG_SA_FILTER_TABLE, true, PDT_GENERIC_03, 8, ReadLv3 | WriteLv3),
case PID_RF_DIAG_BUDGET_TABLE: new DataProperty(PID_RF_DIAG_BUDGET_TABLE, false, PDT_GENERIC_03, 8, ReadLv3 | WriteLv0),
return 24; new FunctionProperty<RfMediumObject>(this, PID_RF_DIAG_PROBE,
// case PID_RF_BIDIR_TIMEOUT: ? [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
// case PID_RF_DIAG_PROBE: ? {
default: },
break; [](RfMediumObject* io, uint8_t* data, uint8_t length, uint8_t* resultData, uint8_t& resultLength)
} {
return 0; }), */
};
initializeProperties(sizeof(properties), properties);
} }
uint8_t* RfMediumObject::save(uint8_t* buffer) const uint8_t* RfMediumObject::rfDomainAddress()
{ {
buffer = pushByteArray((uint8_t*)_rfDomainAddress, 6, buffer); DataProperty* prop = (DataProperty*)property(PID_RF_DOMAIN_ADDRESS);
return buffer; return prop->data();
}
const uint8_t* RfMediumObject::restore(const uint8_t* buffer)
{
buffer = popByteArray((uint8_t*)_rfDomainAddress, 6, buffer);
return buffer;
}
uint16_t RfMediumObject::saveSize()
{
return 6;
}
uint8_t* RfMediumObject::rfDomainAddress()
{
return _rfDomainAddress;
} }
void RfMediumObject::rfDomainAddress(const uint8_t* value) void RfMediumObject::rfDomainAddress(const uint8_t* value)
{ {
pushByteArray(value, 6, _rfDomainAddress); Property* prop = property(PID_RF_DOMAIN_ADDRESS);
} prop->write(value);
static PropertyDescription _propertyDescriptions[] =
{
{ PID_OBJECT_TYPE, false, PDT_UNSIGNED_INT, 1, ReadLv3 | WriteLv0 },
{ PID_RF_MULTI_TYPE, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 },
{ PID_RF_RETRANSMITTER, false, PDT_GENERIC_01, 1, ReadLv3 | WriteLv0 },
{ PID_RF_DOMAIN_ADDRESS, true, PDT_GENERIC_06, 1, ReadLv3 | WriteLv0 }
};
static uint8_t _propertyDescriptionCount = sizeof(_propertyDescriptions) / sizeof(PropertyDescription);
uint8_t RfMediumObject::propertyDescriptionCount()
{
return _propertyDescriptionCount;
}
PropertyDescription* RfMediumObject::propertyDescriptions()
{
return _propertyDescriptions;
} }
#endif #endif

View File

@ -7,21 +7,11 @@
class RfMediumObject: public InterfaceObject class RfMediumObject: public InterfaceObject
{ {
public: public:
void readProperty(PropertyID id, uint16_t start, uint8_t& count, uint8_t* data) override; RfMediumObject();
void writeProperty(PropertyID id, uint16_t start, uint8_t* data, uint8_t& count) override; const uint8_t* rfDomainAddress();
uint8_t propertySize(PropertyID id) override;
uint8_t* save(uint8_t* buffer) override;
const uint8_t* restore(const uint8_t* buffer) override;
uint16_t saveSize() override;
uint8_t* rfDomainAddress();
void rfDomainAddress(const uint8_t* value); void rfDomainAddress(const uint8_t* value);
protected:
uint8_t propertyDescriptionCount() override;
PropertyDescription* propertyDescriptions() override;
private: private:
uint8_t _rfDomainAddress[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // see KNX RF S-Mode AN160 p.11
uint8_t _rfDiagSourceAddressFilterTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; uint8_t _rfDiagSourceAddressFilterTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
uint8_t _rfDiagLinkBudgetTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,}; uint8_t _rfDiagLinkBudgetTable[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
}; };

View File

@ -59,7 +59,7 @@ extern void delayMicroseconds (unsigned int howLong);
#define PKTLEN 0x06 // Packet length #define PKTLEN 0x06 // Packet length
#define PKTCTRL1 0x07 // Packet automation control #define PKTCTRL1 0x07 // Packet automation control
#define PKTCTRL0 0x08 // Packet automation control #define PKTCTRL0 0x08 // Packet automation control
#define DADDR 0x09 // Device address #define DEVADDR 0x09 // Device address
#define CHANNR 0x0A // Channel number #define CHANNR 0x0A // Channel number
#define FSCTRL1 0x0B // Frequency synthesizer control #define FSCTRL1 0x0B // Frequency synthesizer control
#define FSCTRL0 0x0C // Frequency synthesizer control #define FSCTRL0 0x0C // Frequency synthesizer control

View File

@ -92,6 +92,16 @@ void TpUartDataLinkLayer::loop()
uint8_t* buffer = _receiveBuffer + 2; uint8_t* buffer = _receiveBuffer + 2;
uint8_t rxByte; uint8_t rxByte;
if (!_enabled)
{
if (millis() - _lastResetChipTime > 1000)
{
//reset chip every 1 seconds
_lastResetChipTime = millis();
_enabled = resetChip();
}
}
if (!_enabled) if (!_enabled)
return; return;
@ -429,12 +439,14 @@ void TpUartDataLinkLayer::enabled(bool value)
{ {
_platform.setupUart(); _platform.setupUart();
if (resetChip()){ if (resetChip())
{
_enabled = true; _enabled = true;
print("ownaddr "); print("ownaddr ");
println(_deviceObject.induvidualAddress(), HEX); println(_deviceObject.induvidualAddress(), HEX);
} }
else{ else
{
_enabled = false; _enabled = false;
println("ERROR, TPUART not responding"); println("ERROR, TPUART not responding");
} }

View File

@ -38,6 +38,7 @@ class TpUartDataLinkLayer : public DataLinkLayer
uint8_t _xorSum = 0; uint8_t _xorSum = 0;
uint32_t _lastByteRxTime; uint32_t _lastByteRxTime;
uint32_t _waitConfirmStartTime; uint32_t _waitConfirmStartTime;
uint32_t _lastResetChipTime = 0;
struct _tx_queue_frame_t struct _tx_queue_frame_t
{ {

View File

@ -15,24 +15,37 @@
#else #else
#error "No medium type specified for platform Arduino_SAMD! Please set MEDIUM_TYPE! (TP:0, RF:2, IP:5)" #error "No medium type specified for platform Arduino_SAMD! Please set MEDIUM_TYPE! (TP:0, RF:2, IP:5)"
#endif #endif
#define ICACHE_RAM_ATTR
#elif ARDUINO_ARCH_ESP8266 #elif ARDUINO_ARCH_ESP8266
// predefined global instance for IP only // predefined global instance for IP only
KnxFacade<EspPlatform, Bau57B0> knx; KnxFacade<EspPlatform, Bau57B0> knx;
#elif ARDUINO_ARCH_ESP32 #elif ARDUINO_ARCH_ESP32
// predefined global instance for IP only // predefined global instance for TP or IP
#ifdef MEDIUM_TYPE
#if MEDIUM_TYPE == 0
KnxFacade<Esp32Platform, Bau07B0> knx;
#elif MEDIUM_TYPE == 5
KnxFacade<Esp32Platform, Bau57B0> knx; KnxFacade<Esp32Platform, Bau57B0> knx;
#else
#error "Only TP and IP supported for Arduino ESP32 platform!"
#endif
#else
// Compatibility
KnxFacade<Esp32Platform, Bau57B0> knx;
//#error "No medium type specified for platform Arduino ESP32! Please set MEDIUM_TYPE! (TP:0, RF:2, IP:5)"
#endif
#elif ARDUINO_ARCH_STM32
KnxFacade<Stm32Platform, Bau07B0> knx;
#elif __linux__ #elif __linux__
// no predefined global instance // no predefined global instance
#define ICACHE_RAM_ATTR
#endif #endif
#ifndef __linux__ #ifndef ICACHE_RAM_ATTR
uint32_t lastpressed=0; #define ICACHE_RAM_ATTR
#endif #endif
ICACHE_RAM_ATTR void buttonUp() ICACHE_RAM_ATTR void buttonUp()
{ {
#ifndef __linux__ #ifndef __linux__
static uint32_t lastpressed=0;
if (millis() - lastpressed > 200){ if (millis() - lastpressed > 200){
knx._toogleProgMode = true; knx._toogleProgMode = true;
lastpressed = millis(); lastpressed = millis();

View File

@ -17,7 +17,11 @@
#elif ARDUINO_ARCH_ESP32 #elif ARDUINO_ARCH_ESP32
#define LED_BUILTIN 13 #define LED_BUILTIN 13
#include "esp32_platform.h" #include "esp32_platform.h"
#include "knx/bau07B0.h"
#include "knx/bau57B0.h" #include "knx/bau57B0.h"
#elif ARDUINO_ARCH_STM32
#include "stm32_platform.h"
#include "knx/bau07B0.h"
#else #else
#define LED_BUILTIN 0 #define LED_BUILTIN 0
#include "linux_platform.h" #include "linux_platform.h"
@ -331,8 +335,21 @@ template <class P, class B> class KnxFacade : private SaveRestore
// predefined global instance for IP only // predefined global instance for IP only
extern KnxFacade<EspPlatform, Bau57B0> knx; extern KnxFacade<EspPlatform, Bau57B0> knx;
#elif ARDUINO_ARCH_ESP32 #elif ARDUINO_ARCH_ESP32
// predefined global instance for IP only // predefined global instance for TP or IP
#ifdef MEDIUM_TYPE
#if MEDIUM_TYPE == 0
extern KnxFacade<Esp32Platform, Bau07B0> knx;
#elif MEDIUM_TYPE == 5
extern KnxFacade<Esp32Platform, Bau57B0> knx; extern KnxFacade<Esp32Platform, Bau57B0> knx;
#else
#error "Only TP and IP supported for Arduino ESP32 platform!"
#endif
#else
#error "No medium type specified for Arduino ESP32 platform! Please set MEDIUM_TYPE! (TP:0, RF:2, IP:5)"
#endif
#elif ARDUINO_ARCH_STM32
// predefined global instance for TP only
extern KnxFacade<Stm32Platform, Bau07B0> knx;
#elif __linux__ #elif __linux__
// no predefined global instance // no predefined global instance
#endif #endif

42
src/stm32_platform.cpp Normal file
View File

@ -0,0 +1,42 @@
#include "stm32_platform.h"
#ifdef ARDUINO_ARCH_STM32
#include <EEPROM.h>
#include "knx/bits.h"
Stm32Platform::Stm32Platform() : ArduinoPlatform(&Serial2), eepromPtr(nullptr), eepromSize(0)
{
}
Stm32Platform::Stm32Platform( HardwareSerial* s) : ArduinoPlatform(s), eepromPtr(nullptr), eepromSize(0)
{
}
Stm32Platform::~Stm32Platform()
{
delete [] eepromPtr;
}
void Stm32Platform::restart()
{
NVIC_SystemReset();
}
uint8_t * Stm32Platform::getEepromBuffer(uint16_t size)
{
delete [] eepromPtr;
eepromPtr = new uint8_t[size];
for (uint16_t i = 0; i < size; ++i)
eepromPtr[i] = EEPROM[i];
return eepromPtr;
}
void Stm32Platform::commitToEeprom()
{
if(eepromPtr == nullptr)
return;
for (uint16_t i = 0; i < eepromSize; ++i)
EEPROM.update(i, eepromPtr[i]);
}
#endif

22
src/stm32_platform.h Normal file
View File

@ -0,0 +1,22 @@
#ifdef ARDUINO_ARCH_STM32
#include "arduino_platform.h"
class Stm32Platform : public ArduinoPlatform
{
public:
Stm32Platform();
Stm32Platform( HardwareSerial* s);
~Stm32Platform();
// basic stuff
void restart();
//memory
uint8_t* getEepromBuffer(uint16_t size);
void commitToEeprom();
private:
uint8_t *eepromPtr;
uint16_t eepromSize;
};
#endif