Skip to content

Commit

Permalink
Add KNX-IP support for the rp2040 plattform
Browse files Browse the repository at this point in the history
Some general optimizations reagrding KNX-IP

Squashed commit of the following:

commit 2911448
Merge: 8ac6aec 3c29d16
Author: Dom <[email protected]>
Date:   Wed Dec 20 10:04:32 2023 +0100

    Merge pull request #13 from OpenKNX/fix_serialnumber

    Fix serialnumber

commit 8ac6aec
Author: Ing-Dom <[email protected]>
Date:   Thu Dec 14 12:28:02 2023 +0100

    fix macAddress reading for Wifi

commit 9db2cd5
Author: Ing-Dom <[email protected]>
Date:   Tue Dec 12 13:08:53 2023 +0100

    remove LARGE_BUFFERS and clean up header files of ETHERNET_GENERIC

commit 2f229ae
Author: Ing-Dom <[email protected]>
Date:   Tue Dec 12 00:56:32 2023 +0100

    temporary fix, solution needed for tunneling

commit f6e7e61
Author: Ing-Dom <[email protected]>
Date:   Mon Dec 11 13:54:26 2023 +0100

    unified approach for different ip stacks with rp2040 plattform

commit 4723eda
Author: Marco Scholl <[email protected]>
Date:   Mon Dec 11 08:34:25 2023 +0100

    wip

commit 5bf3e61
Author: Ing-Dom <[email protected]>
Date:   Thu Dec 7 14:53:42 2023 +0100

    ip and not ip in one rp2040 plattform

commit aaca34a
Merge: fd97f59 d44606d
Author: Dom <[email protected]>
Date:   Wed Dec 6 15:30:17 2023 +0100

    Merge branch 'thelsing:master' into rp2040_lwip

commit fd97f59
Author: Marco Scholl <[email protected]>
Date:   Thu Nov 30 23:19:13 2023 +0100

    dd sime ifdef to allow build without ip interface

commit c665a79
Author: Ing-Dom <[email protected]>
Date:   Tue Nov 14 10:03:48 2023 +0100

    stub for handling SearchRequestExt to prevent console messages

commit 50745be
Author: Ing-Dom <[email protected]>
Date:   Tue Nov 14 00:02:49 2023 +0100

    adding ip support for rp2040 plattform
  • Loading branch information
Ing-Dom committed Dec 20, 2023
1 parent 3c29d16 commit 45ed912
Show file tree
Hide file tree
Showing 7 changed files with 224 additions and 6 deletions.
8 changes: 8 additions & 0 deletions src/knx/ip_data_link_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,17 @@ void IpDataLinkLayer::loop()
_platform.sendBytesUniCast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
break;
}
case SearchRequestExt:
{
// FIXME, implement (not needed atm)
break;
}
default:
#ifdef KNX_LOG_IP
print("Unhandled service identifier: ");
println(code, HEX);
#endif
;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/knx/ip_parameter_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ IpParameterObject::IpParameterObject(DeviceObject& deviceObject, Platform& platf
io->_deviceObject.individualAddress(getWord(data));
return 1;
}),
new DataProperty(PID_CURRENT_IP_ASSIGNMENT_METHOD, false, PDT_UNSIGNED_CHAR, 0, ReadLv3 | WriteLv3),
new DataProperty(PID_IP_ASSIGNMENT_METHOD, true, PDT_UNSIGNED_CHAR, 1, ReadLv3 | WriteLv3),
new DataProperty(PID_IP_CAPABILITIES, true, PDT_BITSET8, 1, ReadLv3 | WriteLv1),
new DataProperty(PID_IP_CAPABILITIES, true, PDT_BITSET8, 0, ReadLv3 | WriteLv1), // must be set by application due to capabilities of the used ip stack
new CallbackProperty<IpParameterObject>(this, PID_CURRENT_IP_ADDRESS, false, PDT_UNSIGNED_LONG, 1, ReadLv3 | WriteLv0,
[](IpParameterObject* io, uint16_t start, uint8_t count, uint8_t* data) -> uint8_t
{
Expand Down
2 changes: 2 additions & 0 deletions src/knx/knx_ip_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ enum KnxIpServiceType
ConnectionStateResponse = 0x208,
DisconnectRequest = 0x209,
DisconnectResponse = 0x20A,
SearchRequestExt = 0x20B,
SearchResponseExt = 0x20C,
DeviceConfigurationRequest = 0x310,
DeviceConfigurationAck = 0x311,
TunnelingRequest = 0x420,
Expand Down
6 changes: 5 additions & 1 deletion src/knx_facade.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,17 @@
#error "Mask version not supported on ARDUINO_ARCH_SAMD"
#endif
#elif defined(ARDUINO_ARCH_RP2040)
// predefined global instance for TP or RF or TP/RF coupler
// predefined global instance for TP or RF or IP or TP/RF coupler or TP/IP coupler
#if MASK_VERSION == 0x07B0
KnxFacade<RP2040ArduinoPlatform, Bau07B0> knx(buttonEvent);
#elif MASK_VERSION == 0x27B0
KnxFacade<RP2040ArduinoPlatform, Bau27B0> knx(buttonEvent);
#elif MASK_VERSION == 0x57B0
KnxFacade<RP2040ArduinoPlatform, Bau57B0> knx(buttonEvent);
#elif MASK_VERSION == 0x2920
KnxFacade<RP2040ArduinoPlatform, Bau2920> knx(buttonEvent);
#elif MASK_VERSION == 0x091A
KnxFacade<RP2040ArduinoPlatform, Bau091A> knx(buttonEvent);
#else
#error "Mask version not supported on ARDUINO_ARCH_RP2040"
#endif
Expand Down
6 changes: 5 additions & 1 deletion src/knx_facade.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,17 @@ template <class P, class B> class KnxFacade : private SaveRestore
#error "Mask version not supported on ARDUINO_ARCH_SAMD"
#endif
#elif defined(ARDUINO_ARCH_RP2040)
// predefined global instance for TP or RF or TP/RF coupler
// predefined global instance for TP or RF or TP/RF or TP/IP coupler
#if MASK_VERSION == 0x07B0
extern KnxFacade<RP2040ArduinoPlatform, Bau07B0> knx;
#elif MASK_VERSION == 0x27B0
extern KnxFacade<RP2040ArduinoPlatform, Bau27B0> knx;
#elif MASK_VERSION == 0x57B0
extern KnxFacade<RP2040ArduinoPlatform, Bau57B0> knx;
#elif MASK_VERSION == 0x2920
extern KnxFacade<RP2040ArduinoPlatform, Bau2920> knx;
#elif MASK_VERSION == 0x091A
extern KnxFacade<RP2040ArduinoPlatform, Bau091A> knx;
#else
#error "Mask version not supported on ARDUINO_ARCH_RP2040"
#endif
Expand Down
133 changes: 130 additions & 3 deletions src/rp2040_arduino_platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Plattform for Raspberry Pi Pico and other RP2040 boards
by SirSydom <[email protected]> 2021-2022
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 V1.11.0
by Earl E. Philhower III https://github.com/earlephilhower/arduino-pico
RTTI must be set to enabled in the board options
Expand All @@ -17,6 +17,10 @@ EEPROM Emulation from arduino-pico core (max 4k) can be use by defining USE_RP20
A RAM-buffered Flash can be use by defining USE_RP2040_LARGE_EEPROM_EMULATION
For usage of KNX-IP you have to define either
- KNX_IP_W5500 (use the arduino-pico core's w5500 lwip stack)
- KNX_IP_WIFI (use the arduino-pico core's PiPicoW lwip stack)
- KNX_IP_GENERIC (use the Ethernet_Generic stack)
----------------------------------------------------*/

Expand Down Expand Up @@ -45,8 +49,11 @@ A RAM-buffered Flash can be use by defining USE_RP2040_LARGE_EEPROM_EMULATION
#endif
#endif

#ifndef KNX_SERIAL
#define KNX_SERIAL Serial1
#ifdef KNX_IP_W5500
extern Wiznet5500lwIP KNX_NETIF;
#elif defined(KNX_IP_WIFI)
#elif defined(KNX_IP_GENERIC)

#endif

RP2040ArduinoPlatform::RP2040ArduinoPlatform()
Expand Down Expand Up @@ -234,6 +241,126 @@ void RP2040ArduinoPlatform::writeBufferedEraseBlock()
}
}
#endif

#if defined(KNX_NETIF)
uint32_t RP2040ArduinoPlatform::currentIpAddress()
{

return KNX_NETIF.localIP();
}
uint32_t RP2040ArduinoPlatform::currentSubnetMask()
{
return KNX_NETIF.subnetMask();
}
uint32_t RP2040ArduinoPlatform::currentDefaultGateway()
{
return KNX_NETIF.gatewayIP();
}
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};
addr = KNX_NETIF.macAddress(macaddr);
#elif defined(KNX_IP_GENERIC)
KNX_NETIF.MACAddress(addr);
#endif
}

// multicast
void RP2040ArduinoPlatform::setupMultiCast(uint32_t addr, uint16_t port)
{
mcastaddr = IPAddress(htonl(addr));
_port = port;
uint8_t result = _udp.beginMulticast(mcastaddr, port);
(void) result;

#ifdef KNX_IP_GENERIC
//if(!_unicast_socket_setup)
// _unicast_socket_setup = UDP_UNICAST.begin(3671);
#endif

#ifdef KNX_LOG_IP
print("Setup Mcast addr: ");
print(mcastaddr.toString().c_str());
print(" on port: ");
print(port);
print(" result ");
println(result);
#endif
}

void RP2040ArduinoPlatform::closeMultiCast()
{
_udp.stop();
}

bool RP2040ArduinoPlatform::sendBytesMultiCast(uint8_t* buffer, uint16_t len)
{
#ifdef KNX_LOG_IP
printHex("<- ",buffer, len);
#endif
//ToDo: check if Ethernet is able to receive
_udp.beginPacket(mcastaddr, _port);
_udp.write(buffer, len);
_udp.endPacket();
return true;
}

int RP2040ArduinoPlatform::readBytesMultiCast(uint8_t* buffer, uint16_t maxLen)
{
int len = _udp.parsePacket();
if (len == 0)
return 0;

if (len > maxLen)
{
print("udp buffer to small. was ");
print(maxLen);
print(", needed ");
println(len);
fatalError();
}

_udp.read(buffer, len);
#ifdef KNX_LOG_IP
print("Remote IP: ");
print(_udp.remoteIP().toString().c_str());

printHex("-> ", buffer, len);
#endif
return len;
}

// unicast
bool RP2040ArduinoPlatform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len)
{
IPAddress ucastaddr(htonl(addr));

#ifdef KNX_LOG_IP
print("sendBytesUniCast to:");
println(ucastaddr.toString().c_str());
#endif

#ifdef KNX_IP_GENERIC
if(!_unicast_socket_setup)
_unicast_socket_setup = UDP_UNICAST.begin(3671);
#endif

if (UDP_UNICAST.beginPacket(ucastaddr, port) == 1)
{
UDP_UNICAST.write(buffer, len);
if (UDP_UNICAST.endPacket() == 0)
println("sendBytesUniCast endPacket fail");
}
else
println("sendBytesUniCast beginPacket fail");

return true;
}
#endif

#endif


72 changes: 72 additions & 0 deletions src/rp2040_arduino_platform.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include "arduino_platform.h"

#include "Arduino.h"
Expand All @@ -15,6 +17,47 @@
#define USE_RP2040_EEPROM_EMULATION
#endif

#ifndef KNX_SERIAL
#pragma warn "KNX_SERIAL not defined, using Serial1"
#define KNX_SERIAL Serial1
#endif

#ifdef KNX_IP_W5500
#if ARDUINO_PICO_MAJOR * 10000 + ARDUINO_PICO_MINOR * 100 + ARDUINO_PICO_REVISION < 30600
#pragma error "arduino-pico >= 3.6.0 needed"
#endif
#define KNX_NETIF Eth

#include "SPI.h"
#include <W5500lwIP.h>

#elif defined(KNX_IP_WIFI)

#define KNX_NETIF WiFi
#include <WiFi.h>

#elif defined(KNX_IP_GENERIC)


#include <SPI.h>

#ifndef DEBUG_ETHERNET_GENERIC_PORT
#define DEBUG_ETHERNET_GENERIC_PORT Serial
#endif

#ifndef _ETG_LOGLEVEL_
#define _ETG_LOGLEVEL_ 1
#endif


#define ETHERNET_USE_RPIPICO true
#include <Ethernet_Generic.hpp> // https://github.com/khoih-prog/Ethernet_Generic


#define KNX_NETIF Ethernet

#endif


class RP2040ArduinoPlatform : public ArduinoPlatform
{
Expand Down Expand Up @@ -55,6 +98,35 @@ class RP2040ArduinoPlatform : public ArduinoPlatform
// writes _eraseblockBuffer to flash - overrides Plattform::writeBufferedEraseBlock() for performance optimization only
void writeBufferedEraseBlock();
#endif


#if defined(KNX_NETIF)
uint32_t currentIpAddress() override;
uint32_t currentSubnetMask() override;
uint32_t currentDefaultGateway() override;
void macAddress(uint8_t* addr) override;

// multicast
void setupMultiCast(uint32_t addr, uint16_t port) override;
void closeMultiCast() override;
bool sendBytesMultiCast(uint8_t* buffer, uint16_t len) override;
int readBytesMultiCast(uint8_t* buffer, uint16_t maxLen) override;

// unicast
bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) override;

#if defined(KNX_IP_W5500) || defined(KNX_IP_WIFI)
#define UDP_UNICAST _udp
protected: WiFiUDP _udp;
#elif defined(KNX_IP_GENERIC)
#define UDP_UNICAST _udp_uni
protected: bool _unicast_socket_setup = false;
protected: EthernetUDP _udp;
protected: EthernetUDP UDP_UNICAST;
#endif
protected: IPAddress mcastaddr;
protected: uint16_t _port;
#endif
};

#endif

0 comments on commit 45ed912

Please sign in to comment.