Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IP support for RP2040 plattform #267

Merged
merged 1 commit into from
Dec 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/knx/ip_data_link_layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,16 @@ void IpDataLinkLayer::loop()
_platform.sendBytesUniCast(hpai.ipAddress(), hpai.ipPortNumber(), searchResponse.data(), searchResponse.totalLength());
break;
}
case SearchRequestExt:
{
// FIXME, implement (not needed atm)
break;
}
default:
print("Unhandled service identifier: ");
println(code, HEX);
{
// print("Unhandled service identifier: ");
// println(code, HEX);
}
}
}

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
126 changes: 123 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 <com@sirsydom.de> 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,119 @@ 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

// print("Setup Mcast addr: ");
// print(mcastaddr.toString().c_str());
// print(" on port: ");
// print(port);
// print(" result ");
// println(result);
}

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

bool RP2040ArduinoPlatform::sendBytesMultiCast(uint8_t* buffer, uint16_t len)
{
// printHex("<- ",buffer, len);

//ToDo: check if Ethernet is able to receive, return false if not
_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);

// print("Remote IP: ");
// print(_udp.remoteIP().toString().c_str());
// printHex("-> ", buffer, len);

return len;
}

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

// print("sendBytesUniCast to:");
// println(ucastaddr.toString().c_str());

#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
Loading