mirror of
https://github.com/thelsing/knx.git
synced 2024-12-18 19:08:18 +01:00
Merge commit '06e0365' into openknx-merge
This commit is contained in:
commit
f676cd2a20
@ -14,8 +14,9 @@ framework = arduino
|
|||||||
|
|
||||||
; VID must be changed to some known KNX Manufacturer
|
; VID must be changed to some known KNX Manufacturer
|
||||||
; so that the KNX USB interface gets recognized by ETS
|
; so that the KNX USB interface gets recognized by ETS
|
||||||
;extra_scripts = pre:custom_hwids.py
|
; not possible within ci
|
||||||
;board_build.usb_product="KNX RF - USB Interface"
|
;;extra_scripts = pre:custom_hwids.py
|
||||||
|
;;board_build.usb_product="KNX RF - USB Interface"
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
SPI
|
SPI
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
name=knx
|
name=knx
|
||||||
version=1.2.0
|
version=2.0.0
|
||||||
author=Thomas Kunze
|
author=Thomas Kunze et al.
|
||||||
maintainer=Thomas Kunze
|
maintainer=OpenKNX Team
|
||||||
sentence=knx stack
|
sentence=knx stack
|
||||||
paragraph=
|
paragraph=
|
||||||
category=Communication
|
category=Communication
|
||||||
url=https://github.com/thelsing/knx
|
url=https://github.com/OpenKNX/knx
|
||||||
architectures=*
|
architectures=*
|
||||||
includes=knx.h
|
includes=knx.h
|
@ -103,6 +103,11 @@ size_t ArduinoPlatform::readBytesUart(uint8_t *buffer, size_t length)
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ArduinoPlatform::flushUart()
|
||||||
|
{
|
||||||
|
return _knxSerial->flush();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef KNX_NO_SPI
|
#ifndef KNX_NO_SPI
|
||||||
void ArduinoPlatform::setupSpi()
|
void ArduinoPlatform::setupSpi()
|
||||||
{
|
{
|
||||||
|
@ -25,6 +25,7 @@ class ArduinoPlatform : public Platform
|
|||||||
virtual size_t writeUart(const uint8_t* buffer, size_t size);
|
virtual size_t writeUart(const uint8_t* buffer, size_t size);
|
||||||
virtual int readUart();
|
virtual int readUart();
|
||||||
virtual size_t readBytesUart(uint8_t* buffer, size_t length);
|
virtual size_t readBytesUart(uint8_t* buffer, size_t length);
|
||||||
|
virtual void flushUart();
|
||||||
|
|
||||||
//spi
|
//spi
|
||||||
#ifndef KNX_NO_SPI
|
#ifndef KNX_NO_SPI
|
||||||
|
@ -151,4 +151,7 @@ bool Bau07B0::isAckRequired(uint16_t address, bool isGrpAddr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TpUartDataLinkLayer* Bau07B0::getDataLinkLayer() {
|
||||||
|
return (TpUartDataLinkLayer*)&_dlLayer;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,7 +15,8 @@ class Bau07B0 : public BauSystemBDevice, public ITpUartCallBacks, public DataLin
|
|||||||
void loop() override;
|
void loop() override;
|
||||||
bool enabled() override;
|
bool enabled() override;
|
||||||
void enabled(bool value) override;
|
void enabled(bool value) override;
|
||||||
|
|
||||||
|
TpUartDataLinkLayer* getDataLinkLayer();
|
||||||
protected:
|
protected:
|
||||||
InterfaceObject* getInterfaceObject(uint8_t idx);
|
InterfaceObject* getInterfaceObject(uint8_t idx);
|
||||||
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
||||||
|
@ -167,4 +167,11 @@ bool Bau091A::isAckRequired(uint16_t address, bool isGrpAddr)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpDataLinkLayer* Bau091A::getPrimaryDataLinkLayer() {
|
||||||
|
return (IpDataLinkLayer*)&_dlLayerPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
|
TpUartDataLinkLayer* Bau091A::getSecondaryDataLinkLayer() {
|
||||||
|
return (TpUartDataLinkLayer*)&_dlLayerSecondary;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,6 +18,8 @@ class Bau091A : public BauSystemBCoupler, public ITpUartCallBacks, public DataLi
|
|||||||
bool enabled() override;
|
bool enabled() override;
|
||||||
void enabled(bool value) override;
|
void enabled(bool value) override;
|
||||||
|
|
||||||
|
IpDataLinkLayer* getPrimaryDataLinkLayer();
|
||||||
|
TpUartDataLinkLayer* getSecondaryDataLinkLayer();
|
||||||
protected:
|
protected:
|
||||||
InterfaceObject* getInterfaceObject(uint8_t idx);
|
InterfaceObject* getInterfaceObject(uint8_t idx);
|
||||||
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
||||||
|
@ -181,5 +181,7 @@ void Bau27B0::domainAddressSerialNumberReadLocalConfirm(Priority priority, HopCo
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RfDataLinkLayer* Bau27B0::getDataLinkLayer() {
|
||||||
|
return (RfDataLinkLayer*)&_dlLayer;
|
||||||
|
}
|
||||||
#endif // #ifdef USE_RF
|
#endif // #ifdef USE_RF
|
||||||
|
@ -22,6 +22,7 @@ class Bau27B0 : public BauSystemBDevice
|
|||||||
bool enabled() override;
|
bool enabled() override;
|
||||||
void enabled(bool value) override;
|
void enabled(bool value) override;
|
||||||
|
|
||||||
|
RfDataLinkLayer* getDataLinkLayer();
|
||||||
protected:
|
protected:
|
||||||
InterfaceObject* getInterfaceObject(uint8_t idx);
|
InterfaceObject* getInterfaceObject(uint8_t idx);
|
||||||
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
||||||
|
@ -154,4 +154,11 @@ void Bau2920::loop()
|
|||||||
BauSystemBCoupler::loop();
|
BauSystemBCoupler::loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TpUartDataLinkLayer* Bau2920::getPrimaryDataLinkLayer() {
|
||||||
|
return (TpUartDataLinkLayer*)&_dlLayerPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
|
RfDataLinkLayer* Bau2920::getSecondaryDataLinkLayer() {
|
||||||
|
return (RfDataLinkLayer*)&_dlLayerSecondary;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -22,6 +22,8 @@ class Bau2920 : public BauSystemBCoupler
|
|||||||
bool enabled() override;
|
bool enabled() override;
|
||||||
void enabled(bool value) override;
|
void enabled(bool value) override;
|
||||||
|
|
||||||
|
TpUartDataLinkLayer* getPrimaryDataLinkLayer();
|
||||||
|
RfDataLinkLayer* getSecondaryDataLinkLayer();
|
||||||
protected:
|
protected:
|
||||||
InterfaceObject* getInterfaceObject(uint8_t idx);
|
InterfaceObject* getInterfaceObject(uint8_t idx);
|
||||||
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
||||||
|
@ -143,4 +143,7 @@ void Bau57B0::loop()
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpDataLinkLayer* Bau57B0::getDataLinkLayer() {
|
||||||
|
return (IpDataLinkLayer*)&_dlLayer;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,7 +15,8 @@ class Bau57B0 : public BauSystemBDevice, public DataLinkLayerCallbacks
|
|||||||
void loop() override;
|
void loop() override;
|
||||||
bool enabled() override;
|
bool enabled() override;
|
||||||
void enabled(bool value) override;
|
void enabled(bool value) override;
|
||||||
|
|
||||||
|
IpDataLinkLayer* getDataLinkLayer();
|
||||||
protected:
|
protected:
|
||||||
InterfaceObject* getInterfaceObject(uint8_t idx);
|
InterfaceObject* getInterfaceObject(uint8_t idx);
|
||||||
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
|
||||||
|
@ -12,7 +12,8 @@ GroupObjectTableObject* GroupObject::_table = 0;
|
|||||||
GroupObject::GroupObject()
|
GroupObject::GroupObject()
|
||||||
{
|
{
|
||||||
_data = 0;
|
_data = 0;
|
||||||
_commFlag = Uninitialized;
|
_commFlagEx.uninitialized = true;
|
||||||
|
_commFlagEx.commFlag = Uninitialized;
|
||||||
_dataLength = 0;
|
_dataLength = 0;
|
||||||
#ifndef SMALL_GROUPOBJECT
|
#ifndef SMALL_GROUPOBJECT
|
||||||
_updateHandler = 0;
|
_updateHandler = 0;
|
||||||
@ -22,7 +23,7 @@ GroupObject::GroupObject()
|
|||||||
GroupObject::GroupObject(const GroupObject& other)
|
GroupObject::GroupObject(const GroupObject& other)
|
||||||
{
|
{
|
||||||
_data = new uint8_t[other._dataLength];
|
_data = new uint8_t[other._dataLength];
|
||||||
_commFlag = other._commFlag;
|
_commFlagEx = other._commFlagEx;
|
||||||
_dataLength = other._dataLength;
|
_dataLength = other._dataLength;
|
||||||
_asap = other._asap;
|
_asap = other._asap;
|
||||||
#ifndef SMALL_GROUPOBJECT
|
#ifndef SMALL_GROUPOBJECT
|
||||||
@ -75,7 +76,7 @@ bool GroupObject::readEnable()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
// we forbid reading of new (uninitialized) go
|
// we forbid reading of new (uninitialized) go
|
||||||
if (_commFlag == Uninitialized)
|
if (_commFlagEx.uninitialized)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
|
return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
|
||||||
@ -157,22 +158,29 @@ size_t GroupObject::asapValueSize(uint8_t code)
|
|||||||
|
|
||||||
ComFlag GroupObject::commFlag()
|
ComFlag GroupObject::commFlag()
|
||||||
{
|
{
|
||||||
return _commFlag;
|
return _commFlagEx.commFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupObject::commFlag(ComFlag value)
|
void GroupObject::commFlag(ComFlag value)
|
||||||
{
|
{
|
||||||
_commFlag = value;
|
_commFlagEx.commFlag = value;
|
||||||
|
if (value == WriteRequest || value == Updated || value == Ok)
|
||||||
|
_commFlagEx.uninitialized = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GroupObject::initialized()
|
||||||
|
{
|
||||||
|
return !_commFlagEx.uninitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupObject::requestObjectRead()
|
void GroupObject::requestObjectRead()
|
||||||
{
|
{
|
||||||
_commFlag = ReadRequest;
|
commFlag(ReadRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupObject::objectWritten()
|
void GroupObject::objectWritten()
|
||||||
{
|
{
|
||||||
_commFlag = WriteRequest;
|
commFlag(WriteRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GroupObject::valueSize()
|
size_t GroupObject::valueSize()
|
||||||
@ -274,15 +282,15 @@ void GroupObject::valueNoSend(const KNXValue& value)
|
|||||||
|
|
||||||
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
|
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
|
||||||
{
|
{
|
||||||
if (_commFlag == Uninitialized)
|
if (_commFlagEx.uninitialized)
|
||||||
_commFlag = Ok;
|
commFlag(Ok);
|
||||||
|
|
||||||
KNX_Encode_Value(value, _data, _dataLength, type);
|
KNX_Encode_Value(value, _data, _dataLength, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
|
bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
|
||||||
{
|
{
|
||||||
if (_commFlag == Uninitialized)
|
if (_commFlagEx.uninitialized)
|
||||||
{
|
{
|
||||||
// always set first value
|
// always set first value
|
||||||
this->valueNoSend(value, type);
|
this->valueNoSend(value, type);
|
||||||
@ -302,4 +310,14 @@ bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
|
|||||||
|
|
||||||
return dataChanged;
|
return dataChanged;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GroupObject::valueCompare(const KNXValue& value, const Dpt& type)
|
||||||
|
{
|
||||||
|
if (valueNoSendCompare(value, type))
|
||||||
|
{
|
||||||
|
objectWritten();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
class GroupObjectTableObject;
|
class GroupObjectTableObject;
|
||||||
|
|
||||||
enum ComFlag
|
enum ComFlag : uint8_t
|
||||||
{
|
{
|
||||||
Updated = 0, //!< Group object was updated
|
Updated = 0, //!< Group object was updated
|
||||||
ReadRequest = 1, //!< Read was requested but was not processed
|
ReadRequest = 1, //!< Read was requested but was not processed
|
||||||
@ -18,6 +18,16 @@ enum ComFlag
|
|||||||
Uninitialized = 6 //!< uninitialized Group Object, its value is not valid
|
Uninitialized = 6 //!< uninitialized Group Object, its value is not valid
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// extended ComFlag: Uninitialized it not handled correctly as ComFlag
|
||||||
|
// it might be in state Transmitting during a ReadRequest on startup while value is still not valid
|
||||||
|
// we use MSB to store Uninitialized and keep the size of GroupObject the same saving memory ressources
|
||||||
|
// the old Uninitialized handling is still there for compatibility reasons.
|
||||||
|
struct ComFlagEx
|
||||||
|
{
|
||||||
|
bool uninitialized : 1;
|
||||||
|
ComFlag commFlag : 7;
|
||||||
|
};
|
||||||
|
|
||||||
class GroupObject;
|
class GroupObject;
|
||||||
|
|
||||||
#ifndef HAS_FUNCTIONAL
|
#ifndef HAS_FUNCTIONAL
|
||||||
@ -96,6 +106,11 @@ class GroupObject
|
|||||||
*/
|
*/
|
||||||
void commFlag(ComFlag value);
|
void commFlag(ComFlag value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the group object contains a valid value assigned from bus or from application program
|
||||||
|
*/
|
||||||
|
bool initialized();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request the read of a communication object. Calling this function triggers the
|
* Request the read of a communication object. Calling this function triggers the
|
||||||
* sending of a read-group-value telegram, to read the value of the communication
|
* sending of a read-group-value telegram, to read the value of the communication
|
||||||
@ -158,6 +173,19 @@ class GroupObject
|
|||||||
* The parameters must fit the group object. Otherwise it will stay unchanged.
|
* The parameters must fit the group object. Otherwise it will stay unchanged.
|
||||||
*/
|
*/
|
||||||
void value(const KNXValue& value, const Dpt& type);
|
void value(const KNXValue& value, const Dpt& type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the value (after conversion to dpt) will differ from current value of the group object and changes the state of the group object to ::WriteRequest if different.
|
||||||
|
* Use this method only, when the value should not be sent if it was not changed, otherwise value(const KNXValue&, const Dpt&) will do the same (without overhead for comparing)
|
||||||
|
* @param value the value the group object is set to
|
||||||
|
* @param type the datapoint type used for the conversion.
|
||||||
|
*
|
||||||
|
* The parameters must fit the group object. Otherwise it will stay unchanged.
|
||||||
|
*
|
||||||
|
* @returns true if the value of the group object has changed
|
||||||
|
*/
|
||||||
|
bool valueCompare(const KNXValue& value, const Dpt& type);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* set the current value of the group object.
|
* set the current value of the group object.
|
||||||
* @param value the value the group object is set to
|
* @param value the value the group object is set to
|
||||||
@ -249,7 +277,7 @@ class GroupObject
|
|||||||
size_t asapValueSize(uint8_t code);
|
size_t asapValueSize(uint8_t code);
|
||||||
size_t goSize();
|
size_t goSize();
|
||||||
uint16_t _asap = 0;
|
uint16_t _asap = 0;
|
||||||
ComFlag _commFlag = Uninitialized;
|
ComFlagEx _commFlagEx;
|
||||||
uint8_t* _data = 0;
|
uint8_t* _data = 0;
|
||||||
uint8_t _dataLength = 0;
|
uint8_t _dataLength = 0;
|
||||||
#ifndef SMALL_GROUPOBJECT
|
#ifndef SMALL_GROUPOBJECT
|
||||||
|
@ -57,6 +57,14 @@ void Platform::closeUart()
|
|||||||
void Platform::setupUart()
|
void Platform::setupUart()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
bool Platform::overflowUart()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Platform::flushUart()
|
||||||
|
{}
|
||||||
|
|
||||||
uint32_t Platform::currentIpAddress()
|
uint32_t Platform::currentIpAddress()
|
||||||
{
|
{
|
||||||
return 0x01020304;
|
return 0x01020304;
|
||||||
|
@ -62,6 +62,8 @@ class Platform
|
|||||||
virtual size_t writeUart(const uint8_t* buffer, size_t size);
|
virtual size_t writeUart(const uint8_t* buffer, size_t size);
|
||||||
virtual int readUart();
|
virtual int readUart();
|
||||||
virtual size_t readBytesUart(uint8_t* buffer, size_t length);
|
virtual size_t readBytesUart(uint8_t* buffer, size_t length);
|
||||||
|
virtual bool overflowUart();
|
||||||
|
virtual void flushUart();
|
||||||
|
|
||||||
// SPI
|
// SPI
|
||||||
virtual void setupSpi();
|
virtual void setupSpi();
|
||||||
|
302
src/knx/tp_frame.h
Normal file
302
src/knx/tp_frame.h
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
#pragma once
|
||||||
|
#pragma GCC optimize("O3")
|
||||||
|
|
||||||
|
#include "cemi_frame.h"
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Means that the frame is invalid
|
||||||
|
#define TP_FRAME_FLAG_INVALID 0b10000000
|
||||||
|
|
||||||
|
// Means that the frame is an extended frame
|
||||||
|
#define TP_FRAME_FLAG_EXTENDED 0b01000000
|
||||||
|
|
||||||
|
// Means that the frame has been repeated
|
||||||
|
#define TP_FRAME_FLAG_REPEATED 0b00100000
|
||||||
|
|
||||||
|
// Means that the frame comes from the device itself
|
||||||
|
#define TP_FRAME_FLAG_ECHO 0b00010000
|
||||||
|
|
||||||
|
// Means that the frame is processed by this device
|
||||||
|
#define TP_FRAME_FLAG_ADDRESSED 0b00000100
|
||||||
|
|
||||||
|
// Means that the frame has been acked by this device.
|
||||||
|
#define TP_FRAME_FLAG_ACKING 0b00000010
|
||||||
|
|
||||||
|
// Means that the frame has been acked by other (Busmontior)
|
||||||
|
#define TP_FRAME_FLAG_ACKED 0b00000001
|
||||||
|
|
||||||
|
class TpFrame
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
uint8_t *_data;
|
||||||
|
uint16_t _size;
|
||||||
|
uint16_t _maxSize;
|
||||||
|
uint8_t _flags = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sets a few flags based on the control byte
|
||||||
|
*/
|
||||||
|
inline void presetFlags()
|
||||||
|
{
|
||||||
|
if (isExtended())
|
||||||
|
addFlags(TP_FRAME_FLAG_EXTENDED);
|
||||||
|
|
||||||
|
if (isRepeated())
|
||||||
|
addFlags(TP_FRAME_FLAG_REPEATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
* Convert a CemiFrame into a TpFrame
|
||||||
|
*/
|
||||||
|
TpFrame(CemiFrame &cemiFrame)
|
||||||
|
{
|
||||||
|
_size = cemiFrame.telegramLengthtTP();
|
||||||
|
_maxSize = cemiFrame.telegramLengthtTP();
|
||||||
|
_data = (uint8_t *)malloc(cemiFrame.telegramLengthtTP());
|
||||||
|
cemiFrame.fillTelegramTP(_data);
|
||||||
|
presetFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a TpFrame with a reserved space.
|
||||||
|
* Used for incoming parsing.
|
||||||
|
*/
|
||||||
|
TpFrame(uint16_t maxSize = 263)
|
||||||
|
: _maxSize(maxSize)
|
||||||
|
{
|
||||||
|
_data = (uint8_t *)malloc(_maxSize);
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free the data area
|
||||||
|
*/
|
||||||
|
~TpFrame()
|
||||||
|
{
|
||||||
|
free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a byte at end.
|
||||||
|
* Used for incoming parsing.
|
||||||
|
*/
|
||||||
|
inline void addByte(uint8_t byte)
|
||||||
|
{
|
||||||
|
if (!isFull())
|
||||||
|
{
|
||||||
|
_data[_size] = byte;
|
||||||
|
_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read meta data for flags
|
||||||
|
if (_size == 1)
|
||||||
|
presetFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Current frame size. This may differ from the actual size as long as the frame is not complete.
|
||||||
|
*/
|
||||||
|
inline uint16_t size()
|
||||||
|
{
|
||||||
|
return _size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the assigned flags
|
||||||
|
*/
|
||||||
|
inline uint16_t flags()
|
||||||
|
{
|
||||||
|
return _flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds one or more flags
|
||||||
|
*/
|
||||||
|
inline void addFlags(uint8_t flags)
|
||||||
|
{
|
||||||
|
_flags |= flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a pointer to the data
|
||||||
|
*/
|
||||||
|
inline uint8_t *data()
|
||||||
|
{
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the byte corresponding to the specified position
|
||||||
|
*/
|
||||||
|
inline uint8_t data(uint16_t pos)
|
||||||
|
{
|
||||||
|
return _data[pos];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Resets the internal values to refill the frame.
|
||||||
|
*/
|
||||||
|
inline void reset()
|
||||||
|
{
|
||||||
|
_size = 0;
|
||||||
|
_flags = 0;
|
||||||
|
// It is important to fill the _data with zeros so that the length is 0 as long as the value has not yet been read in.
|
||||||
|
memset(_data, 0x0, _maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks whether the frame has been imported completely
|
||||||
|
*/
|
||||||
|
inline bool isFull()
|
||||||
|
{
|
||||||
|
return _size >= (_size >= 7 ? fullSize() : _maxSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns is the frame exteneded or not
|
||||||
|
*/
|
||||||
|
inline bool isExtended()
|
||||||
|
{
|
||||||
|
return (_data[0] & 0xD3) == 0x10;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the source
|
||||||
|
* Assumes that enough data has been imported.
|
||||||
|
*/
|
||||||
|
inline uint16_t source()
|
||||||
|
{
|
||||||
|
return isExtended() ? (_data[2] << 8) + _data[3] : (_data[1] << 8) + _data[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string humanSource()
|
||||||
|
{
|
||||||
|
uint16_t value = source();
|
||||||
|
char buffer[10];
|
||||||
|
sprintf(buffer, "%02i.%02i.%03i", (value >> 12 & 0b1111), (value >> 8 & 0b1111), (value & 0b11111111));
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::string humanDestination()
|
||||||
|
{
|
||||||
|
uint16_t value = destination();
|
||||||
|
char buffer[10];
|
||||||
|
if (isGroupAddress())
|
||||||
|
sprintf(buffer, "%02i/%02i/%03i", (value >> 11 & 0b1111), (value >> 8 & 0b111), (value & 0b11111111));
|
||||||
|
else
|
||||||
|
sprintf(buffer, "%02i.%02i.%03i", (value >> 12 & 0b1111), (value >> 8 & 0b1111), (value & 0b11111111));
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the destination
|
||||||
|
* Assumes that enough data has been imported.
|
||||||
|
*/
|
||||||
|
inline uint16_t destination()
|
||||||
|
{
|
||||||
|
return isExtended() ? (_data[4] << 8) + _data[5] : (_data[3] << 8) + _data[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the payload size (with checksum)
|
||||||
|
* Assumes that enough data has been imported.
|
||||||
|
*/
|
||||||
|
inline uint8_t payloadSize()
|
||||||
|
{
|
||||||
|
return isExtended() ? _data[6] : _data[5] & 0b1111;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the header size
|
||||||
|
*/
|
||||||
|
inline uint8_t headerSize()
|
||||||
|
{
|
||||||
|
return isExtended() ? 9 : 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the frame size based on header and payload size.
|
||||||
|
* Assumes that enough data has been imported.
|
||||||
|
*/
|
||||||
|
inline uint16_t fullSize()
|
||||||
|
{
|
||||||
|
return headerSize() + payloadSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns if the destination is a group address
|
||||||
|
* Assumes that enough data has been imported.
|
||||||
|
*/
|
||||||
|
inline bool isGroupAddress()
|
||||||
|
{
|
||||||
|
return isExtended() ? (_data[1] >> 7) & 0b1 : (_data[5] >> 7) & 0b1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the size of a CemiFrame. A CemiFrame has 2 additional bytes at the beginning.
|
||||||
|
* An additional byte is added to a standard frame, as this still has to be converted into an extendend.
|
||||||
|
*/
|
||||||
|
uint16_t cemiSize()
|
||||||
|
{
|
||||||
|
return fullSize() + (isExtended() ? 2 : 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a buffer and converts the TpFrame into a CemiFrame.
|
||||||
|
* Important: After processing (i.e. also after using the CemiFrame), the reference must be released manually.
|
||||||
|
*/
|
||||||
|
uint8_t *cemiData()
|
||||||
|
{
|
||||||
|
uint8_t *cemiBuffer = (uint8_t *)malloc(cemiSize());
|
||||||
|
|
||||||
|
// Das CEMI erwartet die Daten im Extended format inkl. zwei zusätzlicher Bytes am Anfang.
|
||||||
|
cemiBuffer[0] = 0x29;
|
||||||
|
cemiBuffer[1] = 0x0;
|
||||||
|
cemiBuffer[2] = _data[0];
|
||||||
|
if (isExtended())
|
||||||
|
{
|
||||||
|
memcpy(cemiBuffer + 2, _data, fullSize());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cemiBuffer[3] = _data[5] & 0xF0;
|
||||||
|
memcpy(cemiBuffer + 4, _data + 1, 4);
|
||||||
|
cemiBuffer[8] = _data[5] & 0x0F;
|
||||||
|
memcpy(cemiBuffer + 9, _data + 6, cemiBuffer[8] + 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return cemiBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks whether the frame is complete and valid.
|
||||||
|
*/
|
||||||
|
inline bool isValid()
|
||||||
|
{
|
||||||
|
if (!isComplete())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint8_t sum = 0;
|
||||||
|
const uint16_t s = fullSize() - 1;
|
||||||
|
for (uint16_t i = 0; i < s; i++)
|
||||||
|
sum ^= _data[i];
|
||||||
|
return _data[s] == (uint8_t)~sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Checks whether the frame is long enough to match the length specified in the frame
|
||||||
|
*/
|
||||||
|
inline bool isComplete()
|
||||||
|
{
|
||||||
|
return _size == fullSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isRepeated()
|
||||||
|
{
|
||||||
|
return !(_data[0] & 0b100000);
|
||||||
|
}
|
||||||
|
};
|
File diff suppressed because it is too large
Load Diff
@ -3,14 +3,31 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#ifdef USE_TP
|
#ifdef USE_TP
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "data_link_layer.h"
|
#include "data_link_layer.h"
|
||||||
|
#include "tp_frame.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#define MAX_KNX_TELEGRAM_SIZE 263
|
#define MAX_KNX_TELEGRAM_SIZE 263
|
||||||
|
|
||||||
|
#ifndef MAX_RX_QUEUE_BYTES
|
||||||
|
#define MAX_RX_QUEUE_BYTES MAX_KNX_TELEGRAM_SIZE + 50
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAX_TX_QUEUE
|
||||||
|
#define MAX_TX_QUEUE 50
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// __time_critical_func fallback
|
||||||
|
#ifndef ARDUINO_ARCH_RP2040
|
||||||
|
#define __time_critical_func(X) X
|
||||||
|
#define __isr
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void printFrame(TpFrame* tpframe);
|
||||||
|
|
||||||
class ITpUartCallBacks
|
class ITpUartCallBacks
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~ITpUartCallBacks() = default;
|
virtual ~ITpUartCallBacks() = default;
|
||||||
virtual bool isAckRequired(uint16_t address, bool isGrpAddr) = 0;
|
virtual bool isAckRequired(uint16_t address, bool isGrpAddr) = 0;
|
||||||
};
|
};
|
||||||
@ -24,56 +41,137 @@ class TpUartDataLinkLayer : public DataLinkLayer
|
|||||||
TpUartDataLinkLayer(DeviceObject& devObj, NetworkLayerEntity& netLayerEntity,
|
TpUartDataLinkLayer(DeviceObject& devObj, NetworkLayerEntity& netLayerEntity,
|
||||||
Platform& platform, ITpUartCallBacks& cb, DataLinkLayerCallbacks* dllcb = nullptr);
|
Platform& platform, ITpUartCallBacks& cb, DataLinkLayerCallbacks* dllcb = nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void loop();
|
void loop();
|
||||||
void enabled(bool value);
|
void enabled(bool value);
|
||||||
bool enabled() const;
|
bool enabled() const;
|
||||||
DptMedium mediumType() const override;
|
DptMedium mediumType() const override;
|
||||||
|
bool reset();
|
||||||
|
void monitor();
|
||||||
|
void stop(bool state);
|
||||||
|
void requestBusy(bool state);
|
||||||
|
void forceAck(bool state);
|
||||||
|
void setRepetitions(uint8_t nack, uint8_t busy);
|
||||||
|
// Alias
|
||||||
|
void setFrameRepetition(uint8_t nack, uint8_t busy);
|
||||||
|
bool isConnected();
|
||||||
|
bool isMonitoring();
|
||||||
|
bool isStopped();
|
||||||
|
bool isBusy();
|
||||||
|
|
||||||
|
#ifdef USE_TP_RX_QUEUE
|
||||||
|
void processRxISR();
|
||||||
|
#endif
|
||||||
|
#ifdef NCN5120
|
||||||
|
void powerControl(bool state);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint32_t getRxInvalidFrameCounter();
|
||||||
|
uint32_t getRxProcessdFrameCounter();
|
||||||
|
uint32_t getRxIgnoredFrameCounter();
|
||||||
|
uint32_t getRxUnknownControlCounter();
|
||||||
|
uint32_t getTxFrameCounter();
|
||||||
|
uint32_t getTxProcessedFrameCounter();
|
||||||
|
uint8_t getMode();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _enabled = false;
|
// Frame
|
||||||
uint8_t* _sendBuffer = 0;
|
struct knx_tx_queue_entry_t
|
||||||
uint16_t _sendBufferLength = 0;
|
|
||||||
uint8_t _receiveBuffer[MAX_KNX_TELEGRAM_SIZE];
|
|
||||||
uint8_t _txState = 0;
|
|
||||||
uint8_t _rxState = 0;
|
|
||||||
uint16_t _RxByteCnt = 0;
|
|
||||||
uint16_t _TxByteCnt = 0;
|
|
||||||
uint8_t _oldIdx = 0;
|
|
||||||
bool _isEcho = false;
|
|
||||||
bool _convert = false;
|
|
||||||
uint8_t _xorSum = 0;
|
|
||||||
uint32_t _lastByteRxTime;
|
|
||||||
uint32_t _lastByteTxTime;
|
|
||||||
uint32_t _lastLoopTime;
|
|
||||||
uint32_t _waitConfirmStartTime = 0;
|
|
||||||
uint32_t _lastResetChipTime = 0;
|
|
||||||
|
|
||||||
struct _tx_queue_frame_t
|
|
||||||
{
|
{
|
||||||
uint8_t* data;
|
TpFrame* frame;
|
||||||
uint16_t length;
|
knx_tx_queue_entry_t* next = nullptr;
|
||||||
_tx_queue_frame_t* next;
|
|
||||||
|
knx_tx_queue_entry_t(TpFrame* tpFrame)
|
||||||
|
: frame(tpFrame)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _tx_queue_t
|
// TX Queue
|
||||||
|
struct knx_tx_queue_t
|
||||||
{
|
{
|
||||||
_tx_queue_frame_t* front = NULL;
|
knx_tx_queue_entry_t* front = nullptr;
|
||||||
_tx_queue_frame_t* back = NULL;
|
knx_tx_queue_entry_t* back = nullptr;
|
||||||
} _tx_queue;
|
} _txFrameQueue;
|
||||||
|
|
||||||
void addFrameTxQueue(CemiFrame& frame);
|
TpFrame* _txFrame = nullptr;
|
||||||
bool isTxQueueEmpty();
|
TpFrame* _rxFrame = nullptr;
|
||||||
void loadNextTxFrame();
|
|
||||||
bool sendSingleFrameByte();
|
volatile bool _stopped = false;
|
||||||
|
volatile bool _connected = false;
|
||||||
|
volatile bool _monitoring = false;
|
||||||
|
volatile bool _busy = false;
|
||||||
|
volatile bool _initialized = false;
|
||||||
|
|
||||||
|
volatile uint8_t _rxState = 0;
|
||||||
|
volatile uint8_t _txState = 0;
|
||||||
|
volatile uint32_t _rxProcessdFrameCounter = 0;
|
||||||
|
volatile uint32_t _rxInvalidFrameCounter = 0;
|
||||||
|
volatile uint32_t _rxIgnoredFrameCounter = 0;
|
||||||
|
volatile uint32_t _rxUnkownControlCounter = 0;
|
||||||
|
volatile uint32_t _txFrameCounter = 0;
|
||||||
|
volatile uint32_t _txProcessdFrameCounter = 0;
|
||||||
|
volatile bool _rxMarker = false;
|
||||||
|
volatile bool _rxOverflow = false;
|
||||||
|
volatile uint8_t _tpState = 0x0;
|
||||||
|
volatile uint32_t _txLastTime = 0;
|
||||||
|
volatile uint32_t _rxLastTime = 0;
|
||||||
|
volatile bool _forceAck = false;
|
||||||
|
uint8_t _txQueueCount = 0;
|
||||||
|
|
||||||
|
inline bool markerMode();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bits
|
||||||
|
*
|
||||||
|
* 5-7 Busy (Default 11 = 3)
|
||||||
|
* 0-3 Nack (Default 11 = 3)
|
||||||
|
*/
|
||||||
|
volatile uint8_t _repetitions = 0b00110011;
|
||||||
|
|
||||||
|
// to prevent parallel rx processing by isr (when using)
|
||||||
|
volatile bool _rxProcessing = false;
|
||||||
|
|
||||||
|
volatile uint32_t _lastStateRequest = 0;
|
||||||
|
|
||||||
|
// void loadNextTxFrame();
|
||||||
|
inline bool processTxFrameBytes();
|
||||||
bool sendFrame(CemiFrame& frame);
|
bool sendFrame(CemiFrame& frame);
|
||||||
void frameBytesReceived(uint8_t* buffer, uint16_t length);
|
void rxFrameReceived(TpFrame* frame);
|
||||||
void dataConBytesReceived(uint8_t* buffer, uint16_t length, bool success);
|
void dataConBytesReceived(uint8_t* buffer, uint16_t length, bool success);
|
||||||
void enterRxWaitEOP();
|
|
||||||
bool resetChip();
|
void processRx(bool isr = false);
|
||||||
bool resetChipTick();
|
void checkConnected();
|
||||||
void stopChip();
|
void processRxByte();
|
||||||
|
void processTxQueue();
|
||||||
|
void clearTxFrameQueue();
|
||||||
|
void processRxFrameComplete();
|
||||||
|
inline void processRxFrame(TpFrame* tpFrame);
|
||||||
|
void pushTxFrameQueue(TpFrame* tpFrame);
|
||||||
|
void requestState(bool force = false);
|
||||||
|
void requestConfig();
|
||||||
|
inline void processRxFrameByte(uint8_t byte);
|
||||||
|
|
||||||
|
#ifdef USE_TP_RX_QUEUE
|
||||||
|
// Es muss ein Extended Frame rein passen + 1Byte je erlaubter ms Verzögerung
|
||||||
|
volatile uint8_t _rxBuffer[MAX_RX_QUEUE_BYTES] = {};
|
||||||
|
volatile uint16_t _rxBufferFront = 0;
|
||||||
|
volatile uint16_t _rxBufferRear = 0;
|
||||||
|
volatile uint8_t _rxBufferCount = 0;
|
||||||
|
|
||||||
|
void pushByteToRxQueue(uint8_t byte);
|
||||||
|
uint8_t pullByteFromRxQueue();
|
||||||
|
uint16_t availableInRxQueue();
|
||||||
|
void pushRxFrameQueue();
|
||||||
|
void processRxQueue();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline bool isrLock(bool blocking = false);
|
||||||
|
inline void isrUnlock();
|
||||||
|
inline void clearUartBuffer();
|
||||||
|
inline void connected(bool state = true);
|
||||||
|
void clearTxFrame();
|
||||||
|
void clearOutdatedTxFrame();
|
||||||
|
void processTxFrameComplete(bool success);
|
||||||
|
|
||||||
ITpUartCallBacks& _cb;
|
ITpUartCallBacks& _cb;
|
||||||
DataLinkLayerCallbacks* _dllcb;
|
DataLinkLayerCallbacks* _dllcb;
|
||||||
|
@ -4,7 +4,7 @@ Plattform for Raspberry Pi Pico and other RP2040 boards
|
|||||||
by SirSydom <com@sirsydom.de> 2021-2022
|
by SirSydom <com@sirsydom.de> 2021-2022
|
||||||
|
|
||||||
made to work with arduino-pico - "Raspberry Pi Pico Arduino core, for all RP2040 boards"
|
made to work with arduino-pico - "Raspberry Pi Pico Arduino core, for all RP2040 boards"
|
||||||
by Earl E. Philhower III https://github.com/earlephilhower/arduino-pico
|
by Earl E. Philhower III https://github.com/earlephilhower/arduino-pico
|
||||||
|
|
||||||
|
|
||||||
RTTI must be set to enabled in the board options
|
RTTI must be set to enabled in the board options
|
||||||
@ -31,20 +31,77 @@ For usage of KNX-IP you have to define either
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
//Pi Pico specific libs
|
// Pi Pico specific libs
|
||||||
#include <EEPROM.h> // EEPROM emulation in flash, part of Earl E Philhowers Pi Pico Arduino support
|
#include <EEPROM.h> // EEPROM emulation in flash, part of Earl E Philhowers Pi Pico Arduino support
|
||||||
#include <pico/unique_id.h> // from Pico SDK
|
#include <hardware/flash.h> // from Pico SDK
|
||||||
#include <hardware/watchdog.h> // from Pico SDK
|
#include <hardware/watchdog.h> // from Pico SDK
|
||||||
#include <hardware/flash.h> // from Pico SDK
|
#include <pico/unique_id.h> // from Pico SDK
|
||||||
|
|
||||||
|
#ifdef USE_KNX_DMA_UART
|
||||||
|
#include <hardware/dma.h>
|
||||||
|
// constexpr uint32_t uartDmaTransferCount = 0b1111111111;
|
||||||
|
constexpr uint32_t uartDmaTransferCount = UINT32_MAX;
|
||||||
|
constexpr uint8_t uartDmaBufferExp = 8u; // 2**BufferExp
|
||||||
|
constexpr uint16_t uartDmaBufferSize = (1u << uartDmaBufferExp);
|
||||||
|
int8_t uartDmaChannel = -1;
|
||||||
|
volatile uint8_t __attribute__((aligned(uartDmaBufferSize))) uartDmaBuffer[uartDmaBufferSize] = {};
|
||||||
|
volatile uint32_t uartDmaReadCount = 0;
|
||||||
|
volatile uint16_t uartDmaRestartCount = 0;
|
||||||
|
volatile uint32_t uartDmaWriteCount2 = 0;
|
||||||
|
volatile uint32_t uartDmaAvail = 0;
|
||||||
|
|
||||||
|
// Liefert die Zahl der gelesenen Bytes seit dem DMA Transferstart
|
||||||
|
inline uint32_t uartDmaWriteCount()
|
||||||
|
{
|
||||||
|
uartDmaWriteCount2 = uartDmaTransferCount - dma_channel_hw_addr(uartDmaChannel)->transfer_count;
|
||||||
|
return uartDmaWriteCount2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liefert die aktuelle Schreibposition im DMA Buffer
|
||||||
|
inline uint16_t uartDmaWriteBufferPosition()
|
||||||
|
{
|
||||||
|
return uartDmaWriteCount() % uartDmaBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liefert die aktuelle Leseposition im DMA Buffer
|
||||||
|
inline uint16_t uartDmaReadBufferPosition()
|
||||||
|
{
|
||||||
|
return uartDmaReadCount % uartDmaBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liefert die aktuelle Leseposition als Pointer
|
||||||
|
inline uint8_t* uartDmaReadAddr()
|
||||||
|
{
|
||||||
|
return ((uint8_t*)uartDmaBuffer + uartDmaReadBufferPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Startet den Transfer nach Abschluss neu.
|
||||||
|
void __time_critical_func(uartDmaRestart)()
|
||||||
|
{
|
||||||
|
// println("Restart");
|
||||||
|
uartDmaRestartCount = uartDmaWriteBufferPosition() - uartDmaReadBufferPosition();
|
||||||
|
|
||||||
|
// wenn uartDmaRestartCount == 0 ist, wurde alles verarbeitet und der read count kann mit dem neustart wieder auf 0 gesetzt werden.
|
||||||
|
if (uartDmaRestartCount == 0)
|
||||||
|
{
|
||||||
|
uartDmaReadCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
asm volatile("" ::: "memory");
|
||||||
|
dma_hw->ints0 = 1u << uartDmaChannel; // clear DMA IRQ0 flag
|
||||||
|
asm volatile("" ::: "memory");
|
||||||
|
dma_channel_set_write_addr(uartDmaChannel, uartDmaBuffer, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define FLASHPTR ((uint8_t*)XIP_BASE + KNX_FLASH_OFFSET)
|
#define FLASHPTR ((uint8_t*)XIP_BASE + KNX_FLASH_OFFSET)
|
||||||
|
|
||||||
#ifndef USE_RP2040_EEPROM_EMULATION
|
#ifndef USE_RP2040_EEPROM_EMULATION
|
||||||
#if KNX_FLASH_SIZE%4096
|
#if KNX_FLASH_SIZE % 4096
|
||||||
#error "KNX_FLASH_SIZE must be multiple of 4096"
|
#error "KNX_FLASH_SIZE must be multiple of 4096"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if KNX_FLASH_OFFSET%4096
|
#if KNX_FLASH_OFFSET % 4096
|
||||||
#error "KNX_FLASH_OFFSET must be multiple of 4096"
|
#error "KNX_FLASH_OFFSET must be multiple of 4096"
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
@ -57,26 +114,27 @@ extern Wiznet5500lwIP KNX_NETIF;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
RP2040ArduinoPlatform::RP2040ArduinoPlatform()
|
RP2040ArduinoPlatform::RP2040ArduinoPlatform()
|
||||||
#ifndef KNX_NO_DEFAULT_UART
|
#if !defined(KNX_NO_DEFAULT_UART) && !defined(USE_KNX_DMA_UART)
|
||||||
: ArduinoPlatform(&KNX_SERIAL)
|
: ArduinoPlatform(&KNX_SERIAL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef KNX_UART_RX_PIN
|
#ifdef KNX_UART_RX_PIN
|
||||||
_rxPin = KNX_UART_RX_PIN;
|
_rxPin = KNX_UART_RX_PIN;
|
||||||
#endif
|
#endif
|
||||||
#ifdef KNX_UART_TX_PIN
|
#ifdef KNX_UART_TX_PIN
|
||||||
_txPin = KNX_UART_TX_PIN;
|
_txPin = KNX_UART_TX_PIN;
|
||||||
#endif
|
#endif
|
||||||
#ifndef USE_RP2040_EEPROM_EMULATION
|
#ifndef USE_RP2040_EEPROM_EMULATION
|
||||||
_memoryType = Flash;
|
_memoryType = Flash;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
RP2040ArduinoPlatform::RP2040ArduinoPlatform( HardwareSerial* s) : ArduinoPlatform(s)
|
RP2040ArduinoPlatform::RP2040ArduinoPlatform(HardwareSerial* s)
|
||||||
|
: ArduinoPlatform(s)
|
||||||
{
|
{
|
||||||
#ifndef USE_RP2040_EEPROM_EMULATION
|
#ifndef USE_RP2040_EEPROM_EMULATION
|
||||||
_memoryType = Flash;
|
_memoryType = Flash;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RP2040ArduinoPlatform::knxUartPins(pin_size_t rxPin, pin_size_t txPin)
|
void RP2040ArduinoPlatform::knxUartPins(pin_size_t rxPin, pin_size_t txPin)
|
||||||
@ -85,31 +143,162 @@ void RP2040ArduinoPlatform::knxUartPins(pin_size_t rxPin, pin_size_t txPin)
|
|||||||
_txPin = txPin;
|
_txPin = txPin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RP2040ArduinoPlatform::overflowUart()
|
||||||
|
{
|
||||||
|
#ifdef USE_KNX_DMA_UART
|
||||||
|
// during dma restart
|
||||||
|
bool ret;
|
||||||
|
const uint32_t writeCount = uartDmaWriteCount();
|
||||||
|
if (uartDmaRestartCount > 0)
|
||||||
|
ret = writeCount >= (uartDmaBufferSize - uartDmaRestartCount - 1);
|
||||||
|
else
|
||||||
|
ret = (writeCount - uartDmaReadCount) > uartDmaBufferSize;
|
||||||
|
|
||||||
|
// if (ret)
|
||||||
|
// {
|
||||||
|
// println(uartDmaWriteBufferPosition());
|
||||||
|
// println(uartDmaReadBufferPosition());
|
||||||
|
// println(uartDmaWriteCount());
|
||||||
|
// println(uartDmaReadCount);
|
||||||
|
// println(uartDmaRestartCount);
|
||||||
|
// printHex("BUF: ", (const uint8_t *)uartDmaBuffer, uartDmaBufferSize);
|
||||||
|
// println("OVERFLOW");
|
||||||
|
// while (true)
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
SerialUART* serial = dynamic_cast<SerialUART*>(_knxSerial);
|
||||||
|
return serial->overflow();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void RP2040ArduinoPlatform::setupUart()
|
void RP2040ArduinoPlatform::setupUart()
|
||||||
{
|
{
|
||||||
|
#ifdef USE_KNX_DMA_UART
|
||||||
|
if (uartDmaChannel == -1)
|
||||||
|
{
|
||||||
|
// configure uart0
|
||||||
|
gpio_set_function(_rxPin, GPIO_FUNC_UART);
|
||||||
|
gpio_set_function(_txPin, GPIO_FUNC_UART);
|
||||||
|
uart_init(KNX_DMA_UART, 19200);
|
||||||
|
uart_set_hw_flow(KNX_DMA_UART, false, false);
|
||||||
|
uart_set_format(KNX_DMA_UART, 8, 1, UART_PARITY_EVEN);
|
||||||
|
uart_set_fifo_enabled(KNX_DMA_UART, false);
|
||||||
|
|
||||||
|
// configure uart0
|
||||||
|
uartDmaChannel = dma_claim_unused_channel(true); // get free channel for dma
|
||||||
|
dma_channel_config dmaConfig = dma_channel_get_default_config(uartDmaChannel);
|
||||||
|
channel_config_set_transfer_data_size(&dmaConfig, DMA_SIZE_8);
|
||||||
|
channel_config_set_read_increment(&dmaConfig, false);
|
||||||
|
channel_config_set_write_increment(&dmaConfig, true);
|
||||||
|
channel_config_set_high_priority(&dmaConfig, true);
|
||||||
|
channel_config_set_ring(&dmaConfig, true, uartDmaBufferExp);
|
||||||
|
channel_config_set_dreq(&dmaConfig, KNX_DMA_UART_DREQ);
|
||||||
|
dma_channel_set_read_addr(uartDmaChannel, &uart_get_hw(uart0)->dr, false);
|
||||||
|
dma_channel_set_write_addr(uartDmaChannel, uartDmaBuffer, false);
|
||||||
|
dma_channel_set_trans_count(uartDmaChannel, uartDmaTransferCount, false);
|
||||||
|
dma_channel_set_config(uartDmaChannel, &dmaConfig, true);
|
||||||
|
dma_channel_set_irq1_enabled(uartDmaChannel, true);
|
||||||
|
// irq_add_shared_handler(KNX_DMA_IRQ, uartDmaRestart, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
|
||||||
|
irq_set_exclusive_handler(KNX_DMA_IRQ, uartDmaRestart);
|
||||||
|
irq_set_enabled(KNX_DMA_IRQ, true);
|
||||||
|
}
|
||||||
|
#else
|
||||||
SerialUART* serial = dynamic_cast<SerialUART*>(_knxSerial);
|
SerialUART* serial = dynamic_cast<SerialUART*>(_knxSerial);
|
||||||
if(serial)
|
if (serial)
|
||||||
{
|
{
|
||||||
if (_rxPin != UART_PIN_NOT_DEFINED)
|
if (_rxPin != UART_PIN_NOT_DEFINED)
|
||||||
serial->setRX(_rxPin);
|
serial->setRX(_rxPin);
|
||||||
if (_txPin != UART_PIN_NOT_DEFINED)
|
if (_txPin != UART_PIN_NOT_DEFINED)
|
||||||
serial->setTX(_txPin);
|
serial->setTX(_txPin);
|
||||||
serial->setPollingMode();
|
serial->setPollingMode();
|
||||||
|
serial->setFIFOSize(64);
|
||||||
}
|
}
|
||||||
|
|
||||||
_knxSerial->begin(19200, SERIAL_8E1);
|
_knxSerial->begin(19200, SERIAL_8E1);
|
||||||
while (!_knxSerial)
|
while (!_knxSerial)
|
||||||
;
|
;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_KNX_DMA_UART
|
||||||
|
int RP2040ArduinoPlatform::uartAvailable()
|
||||||
|
{
|
||||||
|
if (uartDmaChannel == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (uartDmaRestartCount > 0)
|
||||||
|
{
|
||||||
|
return uartDmaRestartCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t tc = dma_channel_hw_addr(uartDmaChannel)->transfer_count;
|
||||||
|
uartDmaAvail = tc;
|
||||||
|
int test = uartDmaTransferCount - tc - uartDmaReadCount;
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int RP2040ArduinoPlatform::readUart()
|
||||||
|
{
|
||||||
|
if (!uartAvailable())
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
int ret = uartDmaReadAddr()[0];
|
||||||
|
// print("< ");
|
||||||
|
// println(ret, HEX);
|
||||||
|
uartDmaReadCount++;
|
||||||
|
|
||||||
|
if (uartDmaRestartCount > 0)
|
||||||
|
{
|
||||||
|
// process previouse buffer
|
||||||
|
uartDmaRestartCount--;
|
||||||
|
|
||||||
|
// last char, then reset read count to start at new writer position
|
||||||
|
if (uartDmaRestartCount == 0)
|
||||||
|
uartDmaReadCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t RP2040ArduinoPlatform::writeUart(const uint8_t data)
|
||||||
|
{
|
||||||
|
if (uartDmaChannel == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// print("> ");
|
||||||
|
// println(data, HEX);
|
||||||
|
while (!uart_is_writable(uart0))
|
||||||
|
;
|
||||||
|
uart_putc_raw(uart0, data);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RP2040ArduinoPlatform::closeUart()
|
||||||
|
{
|
||||||
|
if (uartDmaChannel >= 0)
|
||||||
|
{
|
||||||
|
dma_channel_cleanup(uartDmaChannel);
|
||||||
|
irq_set_enabled(DMA_IRQ_0, false);
|
||||||
|
uart_deinit(uart0);
|
||||||
|
uartDmaChannel = -1;
|
||||||
|
uartDmaReadCount = 0;
|
||||||
|
uartDmaRestartCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint32_t RP2040ArduinoPlatform::uniqueSerialNumber()
|
uint32_t RP2040ArduinoPlatform::uniqueSerialNumber()
|
||||||
{
|
{
|
||||||
pico_unique_board_id_t id; // 64Bit unique serial number from the QSPI flash
|
pico_unique_board_id_t id; // 64Bit unique serial number from the QSPI flash
|
||||||
|
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
rp2040.idleOtherCore();
|
rp2040.idleOtherCore();
|
||||||
|
|
||||||
flash_get_unique_id(id.id); //pico_get_unique_board_id(&id);
|
flash_get_unique_id(id.id); // pico_get_unique_board_id(&id);
|
||||||
|
|
||||||
rp2040.resumeOtherCore();
|
rp2040.resumeOtherCore();
|
||||||
interrupts();
|
interrupts();
|
||||||
@ -123,7 +312,7 @@ uint32_t RP2040ArduinoPlatform::uniqueSerialNumber()
|
|||||||
void RP2040ArduinoPlatform::restart()
|
void RP2040ArduinoPlatform::restart()
|
||||||
{
|
{
|
||||||
println("restart");
|
println("restart");
|
||||||
watchdog_reboot(0,0,0);
|
watchdog_reboot(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_RP2040_EEPROM_EMULATION
|
#ifdef USE_RP2040_EEPROM_EMULATION
|
||||||
@ -132,20 +321,20 @@ void RP2040ArduinoPlatform::restart()
|
|||||||
|
|
||||||
#ifdef USE_RP2040_LARGE_EEPROM_EMULATION
|
#ifdef USE_RP2040_LARGE_EEPROM_EMULATION
|
||||||
|
|
||||||
uint8_t * RP2040ArduinoPlatform::getEepromBuffer(uint32_t size)
|
uint8_t* RP2040ArduinoPlatform::getEepromBuffer(uint32_t size)
|
||||||
{
|
{
|
||||||
if(size%4096)
|
if (size % 4096)
|
||||||
{
|
{
|
||||||
println("KNX_FLASH_SIZE must be a multiple of 4096");
|
println("KNX_FLASH_SIZE must be a multiple of 4096");
|
||||||
fatalError();
|
fatalError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!_rambuff_initialized)
|
if (!_rambuff_initialized)
|
||||||
{
|
{
|
||||||
memcpy(_rambuff, FLASHPTR, KNX_FLASH_SIZE);
|
memcpy(_rambuff, FLASHPTR, KNX_FLASH_SIZE);
|
||||||
_rambuff_initialized = true;
|
_rambuff_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return _rambuff;
|
return _rambuff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +343,10 @@ void RP2040ArduinoPlatform::commitToEeprom()
|
|||||||
noInterrupts();
|
noInterrupts();
|
||||||
rp2040.idleOtherCore();
|
rp2040.idleOtherCore();
|
||||||
|
|
||||||
//ToDo: write block-by-block to prevent writing of untouched blocks
|
// ToDo: write block-by-block to prevent writing of untouched blocks
|
||||||
if(memcmp(_rambuff, FLASHPTR, KNX_FLASH_SIZE))
|
if (memcmp(_rambuff, FLASHPTR, KNX_FLASH_SIZE))
|
||||||
{
|
{
|
||||||
flash_range_erase (KNX_FLASH_OFFSET, KNX_FLASH_SIZE);
|
flash_range_erase(KNX_FLASH_OFFSET, KNX_FLASH_SIZE);
|
||||||
flash_range_program(KNX_FLASH_OFFSET, _rambuff, KNX_FLASH_SIZE);
|
flash_range_program(KNX_FLASH_OFFSET, _rambuff, KNX_FLASH_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,22 +356,22 @@ void RP2040ArduinoPlatform::commitToEeprom()
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
uint8_t * RP2040ArduinoPlatform::getEepromBuffer(uint32_t size)
|
uint8_t* RP2040ArduinoPlatform::getEepromBuffer(uint32_t size)
|
||||||
{
|
{
|
||||||
if(size > 4096)
|
if (size > 4096)
|
||||||
{
|
{
|
||||||
println("KNX_FLASH_SIZE to big for EEPROM emulation (max. 4kB)");
|
println("KNX_FLASH_SIZE to big for EEPROM emulation (max. 4kB)");
|
||||||
fatalError();
|
fatalError();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t * eepromptr = EEPROM.getDataPtr();
|
|
||||||
|
|
||||||
if(eepromptr == nullptr)
|
uint8_t* eepromptr = EEPROM.getDataPtr();
|
||||||
|
|
||||||
|
if (eepromptr == nullptr)
|
||||||
{
|
{
|
||||||
EEPROM.begin(4096);
|
EEPROM.begin(4096);
|
||||||
eepromptr = EEPROM.getDataPtr();
|
eepromptr = EEPROM.getDataPtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
return eepromptr;
|
return eepromptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,10 +401,10 @@ uint8_t* RP2040ArduinoPlatform::userFlashStart()
|
|||||||
|
|
||||||
size_t RP2040ArduinoPlatform::userFlashSizeEraseBlocks()
|
size_t RP2040ArduinoPlatform::userFlashSizeEraseBlocks()
|
||||||
{
|
{
|
||||||
if(KNX_FLASH_SIZE <= 0)
|
if (KNX_FLASH_SIZE <= 0)
|
||||||
return 0;
|
return 0;
|
||||||
else
|
else
|
||||||
return ( (KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1;
|
return ((KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum)
|
void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum)
|
||||||
@ -223,7 +412,7 @@ void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum)
|
|||||||
noInterrupts();
|
noInterrupts();
|
||||||
rp2040.idleOtherCore();
|
rp2040.idleOtherCore();
|
||||||
|
|
||||||
flash_range_erase (KNX_FLASH_OFFSET + eraseBlockNum * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
|
flash_range_erase(KNX_FLASH_OFFSET + eraseBlockNum * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
|
||||||
|
|
||||||
rp2040.resumeOtherCore();
|
rp2040.resumeOtherCore();
|
||||||
interrupts();
|
interrupts();
|
||||||
@ -242,12 +431,12 @@ void RP2040ArduinoPlatform::flashWritePage(uint16_t pageNumber, uint8_t* data)
|
|||||||
|
|
||||||
void RP2040ArduinoPlatform::writeBufferedEraseBlock()
|
void RP2040ArduinoPlatform::writeBufferedEraseBlock()
|
||||||
{
|
{
|
||||||
if(_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty)
|
if (_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty)
|
||||||
{
|
{
|
||||||
noInterrupts();
|
noInterrupts();
|
||||||
rp2040.idleOtherCore();
|
rp2040.idleOtherCore();
|
||||||
|
|
||||||
flash_range_erase (KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
|
flash_range_erase(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), flashPageSize() * flashEraseBlockSize());
|
||||||
flash_range_program(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), _eraseblockBuffer, flashPageSize() * flashEraseBlockSize());
|
flash_range_program(KNX_FLASH_OFFSET + _bufferedEraseblockNumber * flashPageSize() * flashEraseBlockSize(), _eraseblockBuffer, flashPageSize() * flashEraseBlockSize());
|
||||||
|
|
||||||
rp2040.resumeOtherCore();
|
rp2040.resumeOtherCore();
|
||||||
@ -276,7 +465,7 @@ void RP2040ArduinoPlatform::macAddress(uint8_t* addr)
|
|||||||
#if defined(KNX_IP_W5500)
|
#if defined(KNX_IP_W5500)
|
||||||
addr = KNX_NETIF.getNetIf()->hwaddr;
|
addr = KNX_NETIF.getNetIf()->hwaddr;
|
||||||
#elif defined(KNX_IP_WIFI)
|
#elif defined(KNX_IP_WIFI)
|
||||||
uint8_t macaddr[6] = {0,0,0,0,0,0};
|
uint8_t macaddr[6] = {0, 0, 0, 0, 0, 0};
|
||||||
addr = KNX_NETIF.macAddress(macaddr);
|
addr = KNX_NETIF.macAddress(macaddr);
|
||||||
#elif defined(KNX_IP_GENERIC)
|
#elif defined(KNX_IP_GENERIC)
|
||||||
KNX_NETIF.MACAddress(addr);
|
KNX_NETIF.MACAddress(addr);
|
||||||
@ -289,12 +478,12 @@ void RP2040ArduinoPlatform::setupMultiCast(uint32_t addr, uint16_t port)
|
|||||||
mcastaddr = IPAddress(htonl(addr));
|
mcastaddr = IPAddress(htonl(addr));
|
||||||
_port = port;
|
_port = port;
|
||||||
uint8_t result = _udp.beginMulticast(mcastaddr, port);
|
uint8_t result = _udp.beginMulticast(mcastaddr, port);
|
||||||
(void) result;
|
(void)result;
|
||||||
|
|
||||||
#ifdef KNX_IP_GENERIC
|
#ifdef KNX_IP_GENERIC
|
||||||
//if(!_unicast_socket_setup)
|
// if(!_unicast_socket_setup)
|
||||||
// _unicast_socket_setup = UDP_UNICAST.begin(3671);
|
// _unicast_socket_setup = UDP_UNICAST.begin(3671);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// print("Setup Mcast addr: ");
|
// print("Setup Mcast addr: ");
|
||||||
// print(mcastaddr.toString().c_str());
|
// print(mcastaddr.toString().c_str());
|
||||||
@ -313,7 +502,7 @@ bool RP2040ArduinoPlatform::sendBytesMultiCast(uint8_t* buffer, uint16_t len)
|
|||||||
{
|
{
|
||||||
// printHex("<- ",buffer, len);
|
// printHex("<- ",buffer, len);
|
||||||
|
|
||||||
//ToDo: check if Ethernet is able to receive, return false if not
|
// ToDo: check if Ethernet is able to receive, return false if not
|
||||||
_udp.beginPacket(mcastaddr, _port);
|
_udp.beginPacket(mcastaddr, _port);
|
||||||
_udp.write(buffer, len);
|
_udp.write(buffer, len);
|
||||||
_udp.endPacket();
|
_udp.endPacket();
|
||||||
@ -348,12 +537,12 @@ int RP2040ArduinoPlatform::readBytesMultiCast(uint8_t* buffer, uint16_t maxLen)
|
|||||||
bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
|
bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
|
||||||
{
|
{
|
||||||
IPAddress ucastaddr(htonl(addr));
|
IPAddress ucastaddr(htonl(addr));
|
||||||
|
|
||||||
// print("sendBytesUniCast to:");
|
// print("sendBytesUniCast to:");
|
||||||
// println(ucastaddr.toString().c_str());
|
// println(ucastaddr.toString().c_str());
|
||||||
|
|
||||||
#ifdef KNX_IP_GENERIC
|
#ifdef KNX_IP_GENERIC
|
||||||
if(!_unicast_socket_setup)
|
if (!_unicast_socket_setup)
|
||||||
_unicast_socket_setup = UDP_UNICAST.begin(3671);
|
_unicast_socket_setup = UDP_UNICAST.begin(3671);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -371,5 +560,3 @@ bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,6 +58,22 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if USE_KNX_DMA_UART == 1
|
||||||
|
#define KNX_DMA_UART uart1
|
||||||
|
#define KNX_DMA_UART_IRQ UART1_IRQ
|
||||||
|
#define KNX_DMA_UART_DREQ DREQ_UART1_RX
|
||||||
|
#else
|
||||||
|
#define KNX_DMA_UART uart0
|
||||||
|
#define KNX_DMA_UART_IRQ UART0_IRQ
|
||||||
|
#define KNX_DMA_UART_DREQ DREQ_UART0_RX
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if USE_KNX_DMA_IRQ == 1
|
||||||
|
#define KNX_DMA_IRQ DMA_IRQ_1
|
||||||
|
#else
|
||||||
|
#define KNX_DMA_IRQ DMA_IRQ_0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class RP2040ArduinoPlatform : public ArduinoPlatform
|
class RP2040ArduinoPlatform : public ArduinoPlatform
|
||||||
{
|
{
|
||||||
@ -67,7 +83,20 @@ public:
|
|||||||
|
|
||||||
// uart
|
// uart
|
||||||
void knxUartPins(pin_size_t rxPin, pin_size_t txPin);
|
void knxUartPins(pin_size_t rxPin, pin_size_t txPin);
|
||||||
void setupUart();
|
void setupUart() override;
|
||||||
|
bool overflowUart() override;
|
||||||
|
#ifdef USE_KNX_DMA_UART
|
||||||
|
int uartAvailable() override;
|
||||||
|
void closeUart() override;
|
||||||
|
void knxUart( HardwareSerial* serial) override {};
|
||||||
|
HardwareSerial* knxUart() override { return nullptr; };
|
||||||
|
size_t writeUart(const uint8_t data) override;
|
||||||
|
size_t writeUart(const uint8_t* buffer, size_t size) override { return 0; };
|
||||||
|
int readUart() override;
|
||||||
|
size_t readBytesUart(uint8_t* buffer, size_t length) override { return 0; };
|
||||||
|
void flushUart() override {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// unique serial number
|
// unique serial number
|
||||||
uint32_t uniqueSerialNumber() override;
|
uint32_t uniqueSerialNumber() override;
|
||||||
|
Loading…
Reference in New Issue
Block a user