diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e80666b..080e70d 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -3,5 +3,8 @@ // for the documentation about the extensions.json format "recommendations": [ "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" ] } diff --git a/examples/knx-demo/knx-demo.ino b/examples/knx-demo/knx-demo.ino index a72b214..f1e22c0 100644 --- a/examples/knx-demo/knx-demo.ino +++ b/examples/knx-demo/knx-demo.ino @@ -1,108 +1,180 @@ #include -#include -#if MASK_VERSION != 0x07B0 && (defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32) -#include +#define USE_KNX + +#ifdef USE_KNX + #include + + #if (MASK_VERSION != 0x07B0) && (defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32) + #include + #endif + +#if USE_W5X00 == 1 + #include + #include #endif -// create named references for easy access to group objects -#define goCurrent knx.getGroupObject(1) -#define goMax knx.getGroupObject(2) -#define goMin knx.getGroupObject(3) -#define goReset knx.getGroupObject(4) + // create named references for easy access to group objects + #define goCurrent knx.getGroupObject(1) + #define goMax knx.getGroupObject(2) + #define goMin knx.getGroupObject(3) + #define goReset knx.getGroupObject(4) -float currentValue = 0; -float maxValue = 0; -float minValue = RAND_MAX; -long lastsend = 0; + float currentValue = 0; + float maxValue = 0; + float minValue = RAND_MAX; + long lastsend = 0; -void measureTemp() -{ - long now = millis(); - if ((now - lastsend) < 2000) - return; - - lastsend = now; - int r = rand(); - currentValue = (r * 1.0) / (RAND_MAX * 1.0); - currentValue *= 100 * 100; - - // write new value to groupobject - goCurrent.value(currentValue); - - if (currentValue > maxValue) + void measureTemp() { - maxValue = currentValue; - goMax.value(maxValue); + long now = millis(); + if ((now - lastsend) < 2000) + return; + + lastsend = now; + int r = rand(); + currentValue = (r * 1.0) / (RAND_MAX * 1.0); + currentValue *= 100 * 100; + + // write new value to groupobject + goCurrent.value(currentValue); + + if (currentValue > maxValue) + { + maxValue = currentValue; + goMax.value(maxValue); + } + + if (currentValue < minValue) + { + minValue = currentValue; + goMin.value(minValue); + } } - if (currentValue < minValue) + // callback from reset-GO + void resetCallback(GroupObject& go) { - minValue = currentValue; - goMin.value(minValue); + if (go.value()) + { + maxValue = 0; + minValue = 10000; + } } -} - -// callback from reset-GO -void resetCallback(GroupObject& go) -{ - if (go.value()) - { - maxValue = 0; - minValue = 10000; - } -} +#endif void setup() { Serial.begin(115200); - ArduinoPlatform::SerialDebug = &Serial; - - randomSeed(millis()); - -#if MASK_VERSION != 0x07B0 && (defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32) - WiFiManager wifiManager; - wifiManager.autoConnect("knx-demo"); -#endif - - // read adress table, association table, groupobject table and parameters from eeprom - knx.readMemory(); - - // print values of parameters if device is already configured - if (knx.configured()) - { - // register callback for reset GO - goReset.callback(resetCallback); - goReset.dataPointType(DPT_Trigger); - goCurrent.dataPointType(DPT_Value_Temp); - goMin.dataPointType(DPT_Value_Temp); - goMax.dataPointType(DPT_Value_Temp); - - Serial.print("Timeout: "); - Serial.println(knx.paramByte(0)); - Serial.print("Zykl. senden: "); - Serial.println(knx.paramByte(1)); - Serial.print("Min/Max senden: "); - Serial.println(knx.paramByte(2)); - Serial.print("Aenderung senden: "); - Serial.println(knx.paramByte(3)); - Serial.print("Abgleich: "); - Serial.println(knx.paramByte(4)); + while (!Serial) { + delay(1000); // wait for serial port to connect. Needed for native USB port only, long for vscode stupid text } - // pin or GPIO the programming led is connected to. Default is LED_BUILTIN - // knx.ledPin(LED_BUILTIN); - // is the led active on HIGH or low? Default is LOW - // knx.ledPinActiveOn(HIGH); - // pin or GPIO programming button is connected to. Default is 0 - // knx.buttonPin(0); + // IP stuff + #if USE_W5X00 == 1 + println("****** Set SS to pin 4 ******"); + Ethernet.init(4); + byte _ma[6] = {0xC0, 0xFF, 0xEE, 0xC0, 0xDE, 0x00}; + println("****** Bring up ethernet connection ******"); + Ethernet.begin(_ma); + if (Ethernet.hardwareStatus() == EthernetNoHardware) { + println("****** No Ethernet shield found ******."); + println("****** Ideling forever... ******"); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware or link + } + } + if (Ethernet.hardwareStatus() != EthernetW5500) { + println("****** Currently only working on W5500 controller ******"); + println("****** Ideling forever... ******"); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware or link + } + } + if (Ethernet.linkStatus() == LinkOFF) { + println("Link status: Off (No network cable connected or port on switch down)"); + println("****** Ideling forever... ******"); + while (true) { + delay(1); // do nothing, no point running without Ethernet hardware or link + } + } + println("****** Ethernet shield connected ******"); + println("****** W5500 Ethernet controller detected ******"); + println("****** Link status: On ******"); + char ar[50]; + sprintf(ar, "****** Mac address used: %02X:%02X:%02X:%02X:%02X:%02X ******", _ma[0], _ma[1], _ma[2], _ma[3], _ma[4], _ma[5]); + println(ar); + println("****** Ethernet connection up ******"); + println("****** Connected with DHCP ******"); + IPAddress _ip = Ethernet.localIP(); + sprintf(ar, "****** IP address: %d.%d.%d.%d ******", _ip[0], _ip[1], _ip[2], _ip[3]); + println(ar); + _ip = Ethernet.subnetMask(); + sprintf(ar, "****** Subnet mask: %d.%d.%d.%d ******", _ip[0], _ip[1], _ip[2], _ip[3]); + println(ar); + _ip = Ethernet.gatewayIP(); + sprintf(ar, "****** Gateway: %d.%d.%d.%d ******", _ip[0], _ip[1], _ip[2], _ip[3]); + println(ar); + #endif - // start the framework. - knx.start(); + #ifdef USE_KNX + ArduinoPlatform::SerialDebug = &Serial; + println("****** Serial debug running ******"); + + randomSeed(millis()); + + #if ((MASK_VERSION != 0x07B0) && (defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32)) + WiFiManager wifiManager; + wifiManager.autoConnect("knx-demo"); + #endif + + println("****** Start reading configuration ******"); + // read adress table, association table, groupobject table and parameters from eeprom + knx.readMemory(); + + // print values of parameters if device is already configured + if (knx.configured()) + { + println("****** Configuration found ******"); + // register callback for reset GO + goReset.callback(resetCallback); + goReset.dataPointType(DPT_Trigger); + goCurrent.dataPointType(DPT_Value_Temp); + goMin.dataPointType(DPT_Value_Temp); + goMax.dataPointType(DPT_Value_Temp); + + Serial.print("Timeout: "); + Serial.println(knx.paramByte(0)); + Serial.print("Zykl. senden: "); + Serial.println(knx.paramByte(1)); + Serial.print("Min/Max senden: "); + Serial.println(knx.paramByte(2)); + Serial.print("Aenderung senden: "); + Serial.println(knx.paramByte(3)); + Serial.print("Abgleich: "); + Serial.println(knx.paramByte(4)); + } + else{ + println("****** No stored configuration found ******"); + } + + // pin or GPIO the programming led is connected to. Default is LED_BUILTIN + // knx.ledPin(LED_BUILTIN); + // is the led active on HIGH or low? Default is LOW + // knx.ledPinActiveOn(HIGH); + // pin or GPIO programming button is connected to. Default is 0 + println("****** Set KNX reset button to pin 1 ******"); + knx.buttonPin(1); + println("****** Starting knx framework ******"); + // start the framework. + knx.start(); + println("****** Knx framework started ******"); + #endif } void loop() { +#ifdef USE_KNX // don't delay here to much. Otherwise you might lose packages or mess up the timing with ETS knx.loop(); @@ -110,5 +182,7 @@ void loop() if (!knx.configured()) return; - measureTemp(); + // measureTemp(); +#endif + } diff --git a/platformio.ini b/platformio.ini index 23ac4f9..d3990e0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,17 +11,40 @@ [platformio] src_dir = examples/knx-demo - -[env] +[env:feather_m4_w5500] platform = atmelsam -board = zeroUSB +board = adafruit_feather_m4 framework = arduino build_type = debug monitor_speed = 115200 -lib_ldf_mode = deep+ +; lib_ldf_mode = deep+ lib_extra_dirs = - ${sysenv.USERPROFILE}/Documents/PlatformIO/Projects + ${sysenv.USERPROFILE}/Documents/Arduino/libraries +lib_compat_mode = strict +lib_deps = + build_flags = + ; -DMASK_VERSION=0x07B0 + -DMASK_VERSION=0x57B0 + -DUSE_W5X00=1 + -DKNX_NO_SPI=1 + ; -DKNX_NO_DEFAULT_UART=1 -Wno-unknown-pragmas +; [env:feather_esspresif32] +; platform = espressif32 +; board = esp32dev +; framework = arduino +; build_type = debug +; monitor_speed = 115200 +; ; lib_ldf_mode = deep+ +; lib_extra_dirs = +; ${sysenv.USERPROFILE}/Documents/Arduino/libraries +; lib_compat_mode = strict +; lib_deps = + +; build_flags = +; -DMASK_VERSION=0x57B0, +; -Wno-unknown-pragmas + [env:build] diff --git a/src/knx_facade.cpp b/src/knx_facade.cpp index 2c3b97e..b7eec68 100644 --- a/src/knx_facade.cpp +++ b/src/knx_facade.cpp @@ -42,8 +42,8 @@ KnxFacade knx(buttonEvent); #elif MASK_VERSION == 0x27B0 KnxFacade knx(buttonEvent); - // #elif MASK_VERSION == 0x57B0 - // KnxFacade knx(buttonEvent); + #elif MASK_VERSION == 0x57B0 + KnxFacade knx(buttonEvent); #else #error "Mask version not supported on SAMD51" #endif diff --git a/src/knx_facade.h b/src/knx_facade.h index 428b63d..41eb1e5 100644 --- a/src/knx_facade.h +++ b/src/knx_facade.h @@ -479,8 +479,8 @@ template class KnxFacade : private SaveRestore extern KnxFacade knx; #elif MASK_VERSION == 0x27B0 extern KnxFacade knx; - // #elif MASK_VERSION == 0x57B0 - // extern KnxFacade knx; + #elif MASK_VERSION == 0x57B0 + extern KnxFacade knx; #else #error "Mask version not supported on SAMD51" #endif diff --git a/src/samd51_platform.cpp b/src/samd51_platform.cpp index 0a30973..f2ad8bf 100644 --- a/src/samd51_platform.cpp +++ b/src/samd51_platform.cpp @@ -43,6 +43,110 @@ void Samd51Platform::restart() NVIC_SystemReset(); } +#if USE_W5X00 == 1 + + uint32_t Samd51Platform::currentIpAddress() + { + // IPAddress _ip = Ethernet.localIP(); + // _ipAddress = htonl(_ip); + // return _ipAddress; + + return Ethernet.localIP(); + + // _ipAddress = 0x0A063232; + // return _ipAddress; + + // return 0x0A063232; + } + + uint32_t Samd51Platform::currentSubnetMask() + { + // IPAddress _nm = Ethernet.subnetMask(); + // _netmask = htonl(_nm); + // return _netmask; + + return Ethernet.subnetMask(); + + // _netmask = 0xFFFFFF00; + // return _netmask; + + // return 0xFFFFFF00; + } + + uint32_t Samd51Platform::currentDefaultGateway() + { + // IPAddress _gw = Ethernet.gatewayIP(); + // _defaultGateway = htonl(_gw); + // return _defaultGateway; + + return Ethernet.gatewayIP(); + + // _defaultGateway = 0x0A063201; + // return _defaultGateway; + + // return 0x0A063201; + } + + void Samd51Platform::macAddress(uint8_t * mac_address) + { + //Ethernet.macAddress(mac_address); //try this first, not sure if this will work, is for ethernet3 lib + memcpy(mac_address, _macAddress, sizeof(_macAddress) / sizeof(_macAddress[0])); //sizeof should resolve to be just 6 + } + + void Samd51Platform::setupMultiCast(uint32_t addr, uint16_t port) + { + IPAddress _mcastaddr(htonl(addr)); + + KNX_DEBUG_SERIAL.printf("setup multicast on %d.%d.%d.%d:%d\n", _mcastaddr[0], _mcastaddr[1], _mcastaddr[2], _mcastaddr[3], port); + uint8_t result = _udp.beginMulticast(_multicastAddr, _multicastPort); + KNX_DEBUG_SERIAL.printf("result %d\n", result); + } + + void Samd51Platform::closeMultiCast() + { + _udp.stop(); + } + + bool Samd51Platform::sendBytesMultiCast(uint8_t * buffer, uint16_t len) + { + //printHex("<- ",buffer, len); + _udp.beginPacket(_multicastAddr, _multicastPort); + _udp.write(buffer, len); + _udp.endPacket(); + return true; + } + + int Samd51Platform::readBytesMultiCast(uint8_t * buffer, uint16_t maxLen) + { + int len = _udp.parsePacket(); + if (len == 0) + return 0; + + if (len > maxLen) + { + KNX_DEBUG_SERIAL.printf("udp buffer to small. was %d, needed %d\n", maxLen, len); + fatalError(); + } + + _udp.read(buffer, len); + printHex("-> ", buffer, len); + return len; + } + + bool Samd51Platform::sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) + { + IPAddress ucastaddr(htonl(addr)); + println("sendBytesUniCast endPacket fail"); + if(_udp.beginPacket(ucastaddr, port) == 1) { + _udp.write(buffer, len); + if(_udp.endPacket() == 0) println("sendBytesUniCast endPacket fail"); + } + else println("sendBytesUniCast beginPacket fail"); + return true; + } + +#endif + extern uint32_t __etext; extern uint32_t __data_start__; extern uint32_t __data_end__; @@ -51,6 +155,17 @@ static const uint32_t pageSizes[] = {8, 16, 32, 64, 128, 256, 512, 1024}; void Samd51Platform::init() { + // println("Entered Init .h variables active, rest and .cpp commented"); + + // #if USE_W5X00 == 1 + // IPAddress _ip = Ethernet.localIP(); + // _ipAddress = htonl(_ip); + // _ip = Ethernet.subnetMask(); + // _netmask = htonl(_ip); + // _ip = Ethernet.gatewayIP(); + // _defaultGateway = htonl(_ip); + // #endif + _memoryType = Flash; _pageSize = pageSizes[NVMCTRL->PARAM.bit.PSZ]; _pageCnt = NVMCTRL->PARAM.bit.NVMP; diff --git a/src/samd51_platform.h b/src/samd51_platform.h index 491a63b..5a58268 100644 --- a/src/samd51_platform.h +++ b/src/samd51_platform.h @@ -1,5 +1,8 @@ -#include "Arduino.h" +#include #include "arduino_platform.h" +#include +#include +#include #ifdef __SAMD51__ @@ -14,6 +17,22 @@ public: void restart(); + #if USE_W5X00 == 1 + // ip config + uint32_t currentIpAddress() override; + uint32_t currentSubnetMask() override; + uint32_t currentDefaultGateway() override; + void macAddress(uint8_t* data) 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; + + bool sendBytesUniCast(uint32_t addr, uint16_t port, uint8_t* buffer, uint16_t len) override; + #endif + // size of one EraseBlock in pages virtual size_t flashEraseBlockSize(); // size of one flash page in bytes @@ -42,6 +61,17 @@ private: void write(const volatile void* flash_ptr, const void* data, uint32_t size); void erase(const volatile void* flash_ptr, uint32_t size); void eraseRow(const volatile void* flash_ptr); + + #if USE_W5X00 == 1 + uint8_t _macAddress[6] = {0xC0, 0xFF, 0xEE, 0xC0, 0xDE, 0x00}; + uint32_t _ipAddress = 0; + uint32_t _netmask = 0; + uint32_t _defaultGateway = 0; + + uint32_t _multicastAddr = -1; + uint16_t _multicastPort = -1; + EthernetUDP _udp; + #endif }; #endif