mirror of
				https://github.com/thelsing/knx.git
				synced 2025-10-26 10:26:25 +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 
 | 
			
		||||
; so that the KNX USB interface gets recognized by ETS
 | 
			
		||||
;extra_scripts = pre:custom_hwids.py
 | 
			
		||||
;board_build.usb_product="KNX RF - USB Interface"
 | 
			
		||||
; not possible within ci
 | 
			
		||||
;;extra_scripts = pre:custom_hwids.py
 | 
			
		||||
;;board_build.usb_product="KNX RF - USB Interface"
 | 
			
		||||
 | 
			
		||||
lib_deps =
 | 
			
		||||
  SPI
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,10 @@
 | 
			
		||||
name=knx
 | 
			
		||||
version=1.2.0
 | 
			
		||||
author=Thomas Kunze
 | 
			
		||||
maintainer=Thomas Kunze
 | 
			
		||||
version=2.0.0
 | 
			
		||||
author=Thomas Kunze et al.
 | 
			
		||||
maintainer=OpenKNX Team
 | 
			
		||||
sentence=knx stack
 | 
			
		||||
paragraph=
 | 
			
		||||
category=Communication
 | 
			
		||||
url=https://github.com/thelsing/knx
 | 
			
		||||
url=https://github.com/OpenKNX/knx
 | 
			
		||||
architectures=*
 | 
			
		||||
includes=knx.h
 | 
			
		||||
@ -103,6 +103,11 @@ size_t ArduinoPlatform::readBytesUart(uint8_t *buffer, size_t length)
 | 
			
		||||
    return length;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ArduinoPlatform::flushUart()
 | 
			
		||||
{
 | 
			
		||||
    return _knxSerial->flush();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef KNX_NO_SPI
 | 
			
		||||
void ArduinoPlatform::setupSpi()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,7 @@ class ArduinoPlatform : public Platform
 | 
			
		||||
    virtual size_t writeUart(const uint8_t* buffer, size_t size);
 | 
			
		||||
    virtual int readUart();
 | 
			
		||||
    virtual size_t readBytesUart(uint8_t* buffer, size_t length);
 | 
			
		||||
    virtual void flushUart();
 | 
			
		||||
 | 
			
		||||
    //spi
 | 
			
		||||
#ifndef KNX_NO_SPI
 | 
			
		||||
 | 
			
		||||
@ -151,4 +151,7 @@ bool Bau07B0::isAckRequired(uint16_t address, bool isGrpAddr)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TpUartDataLinkLayer* Bau07B0::getDataLinkLayer() {
 | 
			
		||||
    return (TpUartDataLinkLayer*)&_dlLayer;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ class Bau07B0 : public BauSystemBDevice, public ITpUartCallBacks, public DataLin
 | 
			
		||||
    bool enabled() override;
 | 
			
		||||
    void enabled(bool value) override;
 | 
			
		||||
 | 
			
		||||
    TpUartDataLinkLayer* getDataLinkLayer();
 | 
			
		||||
  protected:
 | 
			
		||||
    InterfaceObject* getInterfaceObject(uint8_t idx);
 | 
			
		||||
    InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
 | 
			
		||||
 | 
			
		||||
@ -167,4 +167,11 @@ bool Bau091A::isAckRequired(uint16_t address, bool isGrpAddr)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IpDataLinkLayer* Bau091A::getPrimaryDataLinkLayer() {
 | 
			
		||||
    return (IpDataLinkLayer*)&_dlLayerPrimary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TpUartDataLinkLayer* Bau091A::getSecondaryDataLinkLayer() {
 | 
			
		||||
    return (TpUartDataLinkLayer*)&_dlLayerSecondary;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,8 @@ class Bau091A : public BauSystemBCoupler, public ITpUartCallBacks, public DataLi
 | 
			
		||||
    bool enabled() override;
 | 
			
		||||
    void enabled(bool value) override;
 | 
			
		||||
 | 
			
		||||
    IpDataLinkLayer* getPrimaryDataLinkLayer();
 | 
			
		||||
    TpUartDataLinkLayer* getSecondaryDataLinkLayer();
 | 
			
		||||
  protected:
 | 
			
		||||
    InterfaceObject* getInterfaceObject(uint8_t idx);
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,7 @@ class Bau27B0 : public BauSystemBDevice
 | 
			
		||||
    bool enabled() override;
 | 
			
		||||
    void enabled(bool value) override;
 | 
			
		||||
 | 
			
		||||
    RfDataLinkLayer* getDataLinkLayer();
 | 
			
		||||
  protected:
 | 
			
		||||
    InterfaceObject* getInterfaceObject(uint8_t idx);
 | 
			
		||||
    InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
 | 
			
		||||
 | 
			
		||||
@ -154,4 +154,11 @@ void Bau2920::loop()
 | 
			
		||||
    BauSystemBCoupler::loop();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TpUartDataLinkLayer* Bau2920::getPrimaryDataLinkLayer() {
 | 
			
		||||
    return (TpUartDataLinkLayer*)&_dlLayerPrimary;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
RfDataLinkLayer* Bau2920::getSecondaryDataLinkLayer() {
 | 
			
		||||
    return (RfDataLinkLayer*)&_dlLayerSecondary;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -22,6 +22,8 @@ class Bau2920 : public BauSystemBCoupler
 | 
			
		||||
    bool enabled() override;
 | 
			
		||||
    void enabled(bool value) override;
 | 
			
		||||
 | 
			
		||||
    TpUartDataLinkLayer* getPrimaryDataLinkLayer();
 | 
			
		||||
    RfDataLinkLayer* getSecondaryDataLinkLayer();
 | 
			
		||||
  protected:
 | 
			
		||||
    InterfaceObject* getInterfaceObject(uint8_t idx);
 | 
			
		||||
    InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
 | 
			
		||||
 | 
			
		||||
@ -143,4 +143,7 @@ void Bau57B0::loop()
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
IpDataLinkLayer* Bau57B0::getDataLinkLayer() {
 | 
			
		||||
    return (IpDataLinkLayer*)&_dlLayer;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ class Bau57B0 : public BauSystemBDevice, public DataLinkLayerCallbacks
 | 
			
		||||
    bool enabled() override;
 | 
			
		||||
    void enabled(bool value) override;
 | 
			
		||||
    
 | 
			
		||||
    IpDataLinkLayer* getDataLinkLayer();
 | 
			
		||||
  protected:
 | 
			
		||||
    InterfaceObject* getInterfaceObject(uint8_t idx);
 | 
			
		||||
    InterfaceObject* getInterfaceObject(ObjectType objectType, uint8_t objectInstance);
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,8 @@ GroupObjectTableObject* GroupObject::_table = 0;
 | 
			
		||||
GroupObject::GroupObject()
 | 
			
		||||
{
 | 
			
		||||
    _data = 0;
 | 
			
		||||
    _commFlag = Uninitialized;
 | 
			
		||||
    _commFlagEx.uninitialized = true;
 | 
			
		||||
    _commFlagEx.commFlag = Uninitialized;
 | 
			
		||||
    _dataLength = 0;
 | 
			
		||||
#ifndef SMALL_GROUPOBJECT
 | 
			
		||||
    _updateHandler = 0;
 | 
			
		||||
@ -22,7 +23,7 @@ GroupObject::GroupObject()
 | 
			
		||||
GroupObject::GroupObject(const GroupObject& other)
 | 
			
		||||
{
 | 
			
		||||
    _data = new uint8_t[other._dataLength];
 | 
			
		||||
    _commFlag = other._commFlag;
 | 
			
		||||
    _commFlagEx = other._commFlagEx;
 | 
			
		||||
    _dataLength = other._dataLength;
 | 
			
		||||
    _asap = other._asap;
 | 
			
		||||
#ifndef SMALL_GROUPOBJECT
 | 
			
		||||
@ -75,7 +76,7 @@ bool GroupObject::readEnable()
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    // we forbid reading of new (uninitialized) go
 | 
			
		||||
    if (_commFlag == Uninitialized)
 | 
			
		||||
    if (_commFlagEx.uninitialized)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    return bitRead(ntohs(_table->_tableData[_asap]), 11) > 0;
 | 
			
		||||
@ -157,22 +158,29 @@ size_t GroupObject::asapValueSize(uint8_t code)
 | 
			
		||||
 | 
			
		||||
ComFlag GroupObject::commFlag()
 | 
			
		||||
{
 | 
			
		||||
    return _commFlag;
 | 
			
		||||
    return _commFlagEx.commFlag;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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()
 | 
			
		||||
{
 | 
			
		||||
    _commFlag = ReadRequest;
 | 
			
		||||
    commFlag(ReadRequest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GroupObject::objectWritten()
 | 
			
		||||
{
 | 
			
		||||
    _commFlag = WriteRequest;
 | 
			
		||||
    commFlag(WriteRequest);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t GroupObject::valueSize()
 | 
			
		||||
@ -274,15 +282,15 @@ void GroupObject::valueNoSend(const KNXValue& value)
 | 
			
		||||
 | 
			
		||||
void GroupObject::valueNoSend(const KNXValue& value, const Dpt& type)
 | 
			
		||||
{
 | 
			
		||||
    if (_commFlag == Uninitialized)
 | 
			
		||||
        _commFlag = Ok;
 | 
			
		||||
    if (_commFlagEx.uninitialized)
 | 
			
		||||
        commFlag(Ok);
 | 
			
		||||
 | 
			
		||||
    KNX_Encode_Value(value, _data, _dataLength, type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
 | 
			
		||||
{
 | 
			
		||||
    if (_commFlag == Uninitialized)
 | 
			
		||||
    if (_commFlagEx.uninitialized)
 | 
			
		||||
    {
 | 
			
		||||
        // always set first value
 | 
			
		||||
        this->valueNoSend(value, type);
 | 
			
		||||
@ -303,3 +311,13 @@ bool GroupObject::valueNoSendCompare(const KNXValue& value, const Dpt& type)
 | 
			
		||||
        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;
 | 
			
		||||
 | 
			
		||||
enum ComFlag
 | 
			
		||||
enum ComFlag : uint8_t
 | 
			
		||||
{
 | 
			
		||||
    Updated = 0,      //!< Group object was updated
 | 
			
		||||
    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
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
 | 
			
		||||
#ifndef HAS_FUNCTIONAL
 | 
			
		||||
@ -96,6 +106,11 @@ class GroupObject
 | 
			
		||||
     */
 | 
			
		||||
    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
 | 
			
		||||
    * 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.
 | 
			
		||||
     */
 | 
			
		||||
    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.
 | 
			
		||||
     * @param value the value the group object is set to
 | 
			
		||||
@ -249,7 +277,7 @@ class GroupObject
 | 
			
		||||
    size_t asapValueSize(uint8_t code);
 | 
			
		||||
    size_t goSize();
 | 
			
		||||
    uint16_t _asap = 0;
 | 
			
		||||
    ComFlag _commFlag = Uninitialized;
 | 
			
		||||
    ComFlagEx _commFlagEx;
 | 
			
		||||
    uint8_t* _data = 0;
 | 
			
		||||
    uint8_t _dataLength = 0;
 | 
			
		||||
#ifndef SMALL_GROUPOBJECT
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,14 @@ void Platform::closeUart()
 | 
			
		||||
void Platform::setupUart()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
bool Platform::overflowUart()
 | 
			
		||||
{
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Platform::flushUart()
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
uint32_t Platform::currentIpAddress()
 | 
			
		||||
{
 | 
			
		||||
    return 0x01020304;
 | 
			
		||||
 | 
			
		||||
@ -62,6 +62,8 @@ class Platform
 | 
			
		||||
    virtual size_t writeUart(const uint8_t* buffer, size_t size);
 | 
			
		||||
    virtual int readUart();
 | 
			
		||||
    virtual size_t readBytesUart(uint8_t* buffer, size_t length);
 | 
			
		||||
    virtual bool overflowUart();
 | 
			
		||||
    virtual void flushUart();
 | 
			
		||||
 | 
			
		||||
    // SPI
 | 
			
		||||
    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"
 | 
			
		||||
#ifdef USE_TP
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "data_link_layer.h"
 | 
			
		||||
#include "tp_frame.h"
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  public:
 | 
			
		||||
    virtual ~ITpUartCallBacks() = default;
 | 
			
		||||
    virtual bool isAckRequired(uint16_t address, bool isGrpAddr) = 0;
 | 
			
		||||
};
 | 
			
		||||
@ -24,56 +41,137 @@ class TpUartDataLinkLayer : public DataLinkLayer
 | 
			
		||||
    TpUartDataLinkLayer(DeviceObject& devObj, NetworkLayerEntity& netLayerEntity,
 | 
			
		||||
                        Platform& platform, ITpUartCallBacks& cb, DataLinkLayerCallbacks* dllcb = nullptr);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void loop();
 | 
			
		||||
    void enabled(bool value);
 | 
			
		||||
    bool enabled() const;
 | 
			
		||||
    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:
 | 
			
		||||
    bool _enabled = false;
 | 
			
		||||
    uint8_t* _sendBuffer = 0;
 | 
			
		||||
    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
 | 
			
		||||
    // Frame
 | 
			
		||||
    struct knx_tx_queue_entry_t
 | 
			
		||||
    {
 | 
			
		||||
        uint8_t* data;
 | 
			
		||||
        uint16_t length;
 | 
			
		||||
        _tx_queue_frame_t* next;
 | 
			
		||||
        TpFrame* frame;
 | 
			
		||||
        knx_tx_queue_entry_t* next = nullptr;
 | 
			
		||||
 | 
			
		||||
        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;
 | 
			
		||||
        _tx_queue_frame_t* back = NULL;
 | 
			
		||||
    } _tx_queue;
 | 
			
		||||
        knx_tx_queue_entry_t* front = nullptr;
 | 
			
		||||
        knx_tx_queue_entry_t* back = nullptr;
 | 
			
		||||
    } _txFrameQueue;
 | 
			
		||||
 | 
			
		||||
    void addFrameTxQueue(CemiFrame& frame);
 | 
			
		||||
    bool isTxQueueEmpty();
 | 
			
		||||
    void loadNextTxFrame();
 | 
			
		||||
    bool sendSingleFrameByte();
 | 
			
		||||
    TpFrame* _txFrame = nullptr;
 | 
			
		||||
    TpFrame* _rxFrame = nullptr;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
    void frameBytesReceived(uint8_t* buffer, uint16_t length);
 | 
			
		||||
    void rxFrameReceived(TpFrame* frame);
 | 
			
		||||
    void dataConBytesReceived(uint8_t* buffer, uint16_t length, bool success);
 | 
			
		||||
    void enterRxWaitEOP();
 | 
			
		||||
    bool resetChip();
 | 
			
		||||
    bool resetChipTick();
 | 
			
		||||
    void stopChip();
 | 
			
		||||
 | 
			
		||||
    void processRx(bool isr = false);
 | 
			
		||||
    void checkConnected();
 | 
			
		||||
    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;
 | 
			
		||||
    DataLinkLayerCallbacks* _dllcb;
 | 
			
		||||
 | 
			
		||||
@ -31,20 +31,77 @@ For usage of KNX-IP you have to define either
 | 
			
		||||
 | 
			
		||||
#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 <pico/unique_id.h>     // from Pico SDK
 | 
			
		||||
#include <hardware/watchdog.h>  // from Pico SDK
 | 
			
		||||
#include <hardware/flash.h>    // from Pico SDK
 | 
			
		||||
#include <hardware/watchdog.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)
 | 
			
		||||
 | 
			
		||||
#ifndef USE_RP2040_EEPROM_EMULATION
 | 
			
		||||
#if KNX_FLASH_SIZE%4096
 | 
			
		||||
#if KNX_FLASH_SIZE % 4096
 | 
			
		||||
#error "KNX_FLASH_SIZE must be multiple of 4096"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if KNX_FLASH_OFFSET%4096
 | 
			
		||||
#if KNX_FLASH_OFFSET % 4096
 | 
			
		||||
#error "KNX_FLASH_OFFSET must be multiple of 4096"
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
@ -57,26 +114,27 @@ extern Wiznet5500lwIP KNX_NETIF;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RP2040ArduinoPlatform::RP2040ArduinoPlatform()
 | 
			
		||||
#ifndef KNX_NO_DEFAULT_UART
 | 
			
		||||
#if !defined(KNX_NO_DEFAULT_UART) && !defined(USE_KNX_DMA_UART)
 | 
			
		||||
    : ArduinoPlatform(&KNX_SERIAL)
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
    #ifdef KNX_UART_RX_PIN
 | 
			
		||||
#ifdef KNX_UART_RX_PIN
 | 
			
		||||
    _rxPin = KNX_UART_RX_PIN;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifdef KNX_UART_TX_PIN
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef KNX_UART_TX_PIN
 | 
			
		||||
    _txPin = KNX_UART_TX_PIN;
 | 
			
		||||
    #endif
 | 
			
		||||
    #ifndef USE_RP2040_EEPROM_EMULATION
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef USE_RP2040_EEPROM_EMULATION
 | 
			
		||||
    _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;
 | 
			
		||||
    #endif
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RP2040ArduinoPlatform::knxUartPins(pin_size_t rxPin, pin_size_t txPin)
 | 
			
		||||
@ -85,23 +143,154 @@ void RP2040ArduinoPlatform::knxUartPins(pin_size_t rxPin, pin_size_t 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()
 | 
			
		||||
{
 | 
			
		||||
#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);
 | 
			
		||||
    if(serial)
 | 
			
		||||
    if (serial)
 | 
			
		||||
    {
 | 
			
		||||
        if (_rxPin != UART_PIN_NOT_DEFINED)
 | 
			
		||||
            serial->setRX(_rxPin);
 | 
			
		||||
        if (_txPin != UART_PIN_NOT_DEFINED)
 | 
			
		||||
            serial->setTX(_txPin);
 | 
			
		||||
        serial->setPollingMode();
 | 
			
		||||
        serial->setFIFOSize(64);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _knxSerial->begin(19200, SERIAL_8E1);
 | 
			
		||||
    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()
 | 
			
		||||
{
 | 
			
		||||
    pico_unique_board_id_t id; // 64Bit unique serial number from the QSPI flash
 | 
			
		||||
@ -109,7 +298,7 @@ uint32_t RP2040ArduinoPlatform::uniqueSerialNumber()
 | 
			
		||||
    noInterrupts();
 | 
			
		||||
    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();
 | 
			
		||||
    interrupts();
 | 
			
		||||
@ -123,7 +312,7 @@ uint32_t RP2040ArduinoPlatform::uniqueSerialNumber()
 | 
			
		||||
void RP2040ArduinoPlatform::restart()
 | 
			
		||||
{
 | 
			
		||||
    println("restart");
 | 
			
		||||
    watchdog_reboot(0,0,0);
 | 
			
		||||
    watchdog_reboot(0, 0, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef USE_RP2040_EEPROM_EMULATION
 | 
			
		||||
@ -132,15 +321,15 @@ void RP2040ArduinoPlatform::restart()
 | 
			
		||||
 | 
			
		||||
#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");
 | 
			
		||||
        fatalError();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!_rambuff_initialized)
 | 
			
		||||
    if (!_rambuff_initialized)
 | 
			
		||||
    {
 | 
			
		||||
        memcpy(_rambuff, FLASHPTR, KNX_FLASH_SIZE);
 | 
			
		||||
        _rambuff_initialized = true;
 | 
			
		||||
@ -154,10 +343,10 @@ void RP2040ArduinoPlatform::commitToEeprom()
 | 
			
		||||
    noInterrupts();
 | 
			
		||||
    rp2040.idleOtherCore();
 | 
			
		||||
 | 
			
		||||
    //ToDo: write block-by-block to prevent writing of untouched blocks
 | 
			
		||||
    if(memcmp(_rambuff, FLASHPTR, KNX_FLASH_SIZE))
 | 
			
		||||
    // ToDo: write block-by-block to prevent writing of untouched blocks
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -167,17 +356,17 @@ void RP2040ArduinoPlatform::commitToEeprom()
 | 
			
		||||
 | 
			
		||||
#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)");
 | 
			
		||||
        fatalError();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    uint8_t * eepromptr = EEPROM.getDataPtr();
 | 
			
		||||
    uint8_t* eepromptr = EEPROM.getDataPtr();
 | 
			
		||||
 | 
			
		||||
    if(eepromptr == nullptr)
 | 
			
		||||
    if (eepromptr == nullptr)
 | 
			
		||||
    {
 | 
			
		||||
        EEPROM.begin(4096);
 | 
			
		||||
        eepromptr = EEPROM.getDataPtr();
 | 
			
		||||
@ -212,10 +401,10 @@ uint8_t* RP2040ArduinoPlatform::userFlashStart()
 | 
			
		||||
 | 
			
		||||
size_t RP2040ArduinoPlatform::userFlashSizeEraseBlocks()
 | 
			
		||||
{
 | 
			
		||||
    if(KNX_FLASH_SIZE <= 0)
 | 
			
		||||
    if (KNX_FLASH_SIZE <= 0)
 | 
			
		||||
        return 0;
 | 
			
		||||
    else
 | 
			
		||||
        return ( (KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1;
 | 
			
		||||
        return ((KNX_FLASH_SIZE - 1) / (flashPageSize() * flashEraseBlockSize())) + 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum)
 | 
			
		||||
@ -223,7 +412,7 @@ void RP2040ArduinoPlatform::flashErase(uint16_t eraseBlockNum)
 | 
			
		||||
    noInterrupts();
 | 
			
		||||
    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();
 | 
			
		||||
    interrupts();
 | 
			
		||||
@ -242,12 +431,12 @@ void RP2040ArduinoPlatform::flashWritePage(uint16_t pageNumber, uint8_t* data)
 | 
			
		||||
 | 
			
		||||
void RP2040ArduinoPlatform::writeBufferedEraseBlock()
 | 
			
		||||
{
 | 
			
		||||
    if(_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty)
 | 
			
		||||
    if (_bufferedEraseblockNumber > -1 && _bufferedEraseblockDirty)
 | 
			
		||||
    {
 | 
			
		||||
        noInterrupts();
 | 
			
		||||
        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());
 | 
			
		||||
 | 
			
		||||
        rp2040.resumeOtherCore();
 | 
			
		||||
@ -276,7 +465,7 @@ void RP2040ArduinoPlatform::macAddress(uint8_t* addr)
 | 
			
		||||
#if defined(KNX_IP_W5500)
 | 
			
		||||
    addr = KNX_NETIF.getNetIf()->hwaddr;
 | 
			
		||||
#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);
 | 
			
		||||
#elif defined(KNX_IP_GENERIC)
 | 
			
		||||
    KNX_NETIF.MACAddress(addr);
 | 
			
		||||
@ -289,12 +478,12 @@ void RP2040ArduinoPlatform::setupMultiCast(uint32_t addr, uint16_t port)
 | 
			
		||||
    mcastaddr = IPAddress(htonl(addr));
 | 
			
		||||
    _port = port;
 | 
			
		||||
    uint8_t result = _udp.beginMulticast(mcastaddr, port);
 | 
			
		||||
    (void) result;
 | 
			
		||||
    (void)result;
 | 
			
		||||
 | 
			
		||||
    #ifdef KNX_IP_GENERIC
 | 
			
		||||
    //if(!_unicast_socket_setup)
 | 
			
		||||
    //    _unicast_socket_setup = UDP_UNICAST.begin(3671);
 | 
			
		||||
    #endif
 | 
			
		||||
#ifdef KNX_IP_GENERIC
 | 
			
		||||
// if(!_unicast_socket_setup)
 | 
			
		||||
//     _unicast_socket_setup = UDP_UNICAST.begin(3671);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // print("Setup Mcast addr: ");
 | 
			
		||||
    // print(mcastaddr.toString().c_str());
 | 
			
		||||
@ -313,7 +502,7 @@ bool RP2040ArduinoPlatform::sendBytesMultiCast(uint8_t* buffer, uint16_t 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.write(buffer, len);
 | 
			
		||||
    _udp.endPacket();
 | 
			
		||||
@ -353,7 +542,7 @@ bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8
 | 
			
		||||
    // println(ucastaddr.toString().c_str());
 | 
			
		||||
 | 
			
		||||
#ifdef KNX_IP_GENERIC
 | 
			
		||||
    if(!_unicast_socket_setup)
 | 
			
		||||
    if (!_unicast_socket_setup)
 | 
			
		||||
        _unicast_socket_setup = UDP_UNICAST.begin(3671);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -371,5 +560,3 @@ bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -58,6 +58,22 @@
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
{
 | 
			
		||||
@ -67,7 +83,20 @@ public:
 | 
			
		||||
 | 
			
		||||
    // uart
 | 
			
		||||
    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
 | 
			
		||||
    uint32_t uniqueSerialNumber() override; 
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user