From 702d0851176e73762fce651ad7ff32b357c9f4ee Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 13:28:34 +0200 Subject: [PATCH 01/35] rename global dmx... variables to dmxInput... This is the first step in supporting both dmx input and dmx output on different pins. --- wled00/cfg.cpp | 12 +++++++++ wled00/dmx.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ wled00/set.cpp | 6 +++++ wled00/wled.cpp | 5 ++++ wled00/wled.h | 8 +++++- wled00/xml.cpp | 11 ++++++++ 6 files changed, 108 insertions(+), 1 deletion(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 38e804ed97..1105077ca6 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -522,6 +522,13 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { tdd = if_live[F("timeout")] | -1; if (tdd >= 0) realtimeTimeoutMs = tdd * 100; + + #ifdef WLED_ENABLE_DMX_INPUT + CJSON(dmxInputTransmitPin, if_live_dmx[F("inputRxPin")]); + CJSON(dmxInputReceivePin, if_live_dmx[F("inputTxPin")]); + CJSON(dmxInputEnablePin, if_live_dmx[F("enablePin")]); + #endif + CJSON(arlsForceMaxBri, if_live[F("maxbri")]); CJSON(arlsDisableGammaCorrection, if_live[F("no-gc")]); // false CJSON(arlsOffset, if_live[F("offset")]); // 0 @@ -1001,6 +1008,11 @@ void serializeConfig() { if_live_dmx[F("addr")] = DMXAddress; if_live_dmx[F("dss")] = DMXSegmentSpacing; if_live_dmx["mode"] = DMXMode; + #ifdef WLED_ENABLE_DMX_INPUT + if_live_dmx[F("rxPin")] = dmxInputTransmitPin; + if_live_dmx[F("txPin")] = dmxInputReceivePin; + if_live_dmx[F("enablePin")] = dmxInputEnablePin; + #endif if_live[F("timeout")] = realtimeTimeoutMs / 100; if_live[F("maxbri")] = arlsForceMaxBri; diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index dbe70f2aac..305d5130d3 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -76,3 +76,70 @@ void initDMX() { #endif } #endif + + +#ifdef WLED_ENABLE_DMX_INPUT + +#include + + +dmx_port_t dmxPort = 2; +void initDMX() { +/* Set the DMX hardware pins to the pins that we want to use. */ + if(dmxInputReceivePin > 0) { + USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); + dmx_set_pin(dmxPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); + } + else { + USER_PRINTLN("DMX input disabled due to dmxReceivePin not being set"); + return; + } + + /* Now we can install the DMX driver! We'll tell it which DMX port to use and + which interrupt priority it should have. If you aren't sure which interrupt + priority to use, you can use the macro `DMX_DEFAULT_INTR_FLAG` to set the + interrupt to its default settings.*/ + dmx_driver_install(dmxPort, ESP_INTR_FLAG_LEVEL3); +} + +bool dmxIsConnected = false; +unsigned long dmxLastUpdate = 0; + +void handleDMXInput() { + if(dmxInputReceivePin < 1) { + return; + } + byte dmxdata[DMX_PACKET_SIZE]; + dmx_packet_t packet; + unsigned long now = millis(); + if (dmx_receive(dmxPort, &packet, 0)) { + + /* We should check to make sure that there weren't any DMX errors. */ + if (!packet.err) { + /* If this is the first DMX data we've received, lets log it! */ + if (!dmxIsConnected) { + USER_PRINTLN("DMX is connected!"); + dmxIsConnected = true; + } + + dmx_read(dmxPort, dmxdata, packet.size); + handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); + dmxLastUpdate = now; + + } else { + /* Oops! A DMX error occurred! Don't worry, this can happen when you first + connect or disconnect your DMX devices. If you are consistently getting + DMX errors, then something may have gone wrong with your code or + something is seriously wrong with your DMX transmitter. */ + DEBUG_PRINT("A DMX error occurred - "); + DEBUG_PRINTLN(packet.err); + } + } + else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { + dmxIsConnected = false; + USER_PRINTLN("DMX was disconnected."); + } +} +#else +void initDMX(); +#endif diff --git a/wled00/set.cpp b/wled00/set.cpp index 160eb48f07..9a12cdc215 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -420,6 +420,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) t = request->arg(F("WO")).toInt(); if (t >= -255 && t <= 255) arlsOffset = t; +#ifdef WLED_ENABLE_DMX_INPUT + dmxInputTransmitPin = request->arg(F("IDMT")).toInt(); + dmxInputReceivePin = request->arg(F("IDMR")).toInt(); + dmxInputEnablePin= request->arg(F("IDME")).toInt(); +#endif + #ifndef WLED_DISABLE_ALEXA alexaEnabled = request->hasArg(F("AL")); strlcpy(alexaInvocationName, request->arg(F("AI")).c_str(), 33); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 1f978a39b4..8144b0cd41 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -423,6 +423,11 @@ void WLED::setup() #ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin PinManager::allocatePin(2, true, PinOwner::DMX); #endif +#ifdef WLED_ENABLE_DMX_INPUT + if(dmxInputTransmitPin > 0) PinManager::allocatePin(dmxInputTransmitPin, true, PinOwner::DMX); + if(dmxInputReceivePin > 0) PinManager::allocatePin(dmxInputReceivePin, true, PinOwner::DMX); + if(dmxInputEnablePin > 0) PinManager::allocatePin(dmxInputEnablePin, true, PinOwner::DMX); +#endif DEBUG_PRINTLN(F("Registering usermods ...")); registerUsermods(); diff --git a/wled00/wled.h b/wled00/wled.h index 533b120632..8adbd1ba5c 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -459,7 +459,13 @@ WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to f WLED_GLOBAL uint16_t DMXStart _INIT(10); // start address of the first fixture WLED_GLOBAL uint16_t DMXStartLED _INIT(0); // LED from which DMX fixtures start #endif -WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consecutive universes) +#ifdef WLED_ENABLE_DMX_INPUT + WLED_GLOBAL int dmxInputTransmitPin _INIT(0); + WLED_GLOBAL int dmxInputReceivePin _INIT(0); + WLED_GLOBAL int dmxInputEnablePin _INIT(0); +#endif + +WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes) WLED_GLOBAL uint16_t e131Port _INIT(5568); // DMX in port. E1.31 default is 5568, Art-Net is 6454 WLED_GLOBAL byte e131Priority _INIT(0); // E1.31 port priority (if != 0 priority handling is active) WLED_GLOBAL E131Priority highPriority _INIT(3); // E1.31 highest priority tracking, init = timeout in seconds diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 2a19cdfabc..62de534250 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -436,6 +436,17 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormCheckbox(settingsScript,PSTR("ES"),e131SkipOutOfSequence); printSetFormCheckbox(settingsScript,PSTR("EM"),e131Multicast); printSetFormValue(settingsScript,PSTR("EU"),e131Universe); +#ifdef WLED_ENABLE_DMX + oappend(SET_F("hideNoDMX();")); // WLEDMM hide "not compiled in" message +#endif +#ifndef WLED_ENABLE_DMX_INPUT + oappend(SET_F("hideDMXInput();")); // WLEDMM hide "dmx input" settings +#else + oappend(SET_F("hideNoDMXInput();")); // WLEDMM hide "not compiled in" message + sappend('v',SET_F("IDMT"),dmxInputTransmitPin); + sappend('v',SET_F("IDMR"),dmxInputReceivePin); + sappend('v',SET_F("IDME"),dmxInputEnablePin); +#endif printSetFormValue(settingsScript,PSTR("DA"),DMXAddress); printSetFormValue(settingsScript,PSTR("XX"),DMXSegmentSpacing); printSetFormValue(settingsScript,PSTR("PY"),e131Priority); From 9e2268bd74bb35c2695d22668ca191f2242b041d Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 13:38:04 +0200 Subject: [PATCH 02/35] Adapt to new api of esp_dmx v3.1 --- wled00/dmx.cpp | 55 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index 305d5130d3..1bb1b250dd 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -1,7 +1,7 @@ #include "wled.h" /* - * Support for DMX Output via MAX485. + * Support for DMX input and output via MAX485. * Change the output pin in src/dependencies/ESPDMX.cpp, if needed (ESP8266) * Change the output pin in src/dependencies/SparkFunDMX.cpp, if needed (ESP32) * ESP8266 Library from: @@ -83,36 +83,61 @@ void initDMX() { #include -dmx_port_t dmxPort = 2; +static dmx_port_t dmxInputPort = 2; //TODO make this configurable +bool dmxInputInitialized = false; //true once initDmx finished successfully + void initDMX() { -/* Set the DMX hardware pins to the pins that we want to use. */ - if(dmxInputReceivePin > 0) { + + + if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) + { + dmx_config_t config{ + 255, /*alloc_size*/ + 0, /*model_id*/ + RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ + VERSION, /*software_version_id*/ + "undefined", /*software_version_label*/ + 1, /*current_personality*/ + {{15, "WLED Effect Mode"}}, /*personalities*/ + 1, /*personality_count*/ + 1, /*dmx_start_address*/ + }; + const std::string versionString = "WLED_V" + std::to_string(VERSION); + strncpy(config.software_version_label, versionString.c_str(), 32); + config.software_version_label[32] = '\0';//zero termination in case our string was longer than 32 chars + + if(!dmx_driver_install(dmxInputPort, &config, DMX_INTR_FLAGS_DEFAULT)) + { + USER_PRINTF("Error: Failed to install dmx driver\n"); + return; + } + USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); - dmx_set_pin(dmxPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); + USER_PRINTF("Sending DMX on pin %u\n", dmxInputTransmitPin); + USER_PRINTF("DMX enable pin is: %u\n", dmxInputEnablePin); + dmx_set_pin(dmxInputPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); + + dmxInputInitialized = true; } - else { - USER_PRINTLN("DMX input disabled due to dmxReceivePin not being set"); + else + { + USER_PRINTLN("DMX input disabled due to dmxInputReceivePin, dmxInputEnablePin or dmxInputTransmitPin not set"); return; } - /* Now we can install the DMX driver! We'll tell it which DMX port to use and - which interrupt priority it should have. If you aren't sure which interrupt - priority to use, you can use the macro `DMX_DEFAULT_INTR_FLAG` to set the - interrupt to its default settings.*/ - dmx_driver_install(dmxPort, ESP_INTR_FLAG_LEVEL3); } bool dmxIsConnected = false; unsigned long dmxLastUpdate = 0; void handleDMXInput() { - if(dmxInputReceivePin < 1) { + if(!dmxInputInitialized) { return; } byte dmxdata[DMX_PACKET_SIZE]; dmx_packet_t packet; unsigned long now = millis(); - if (dmx_receive(dmxPort, &packet, 0)) { + if (dmx_receive(dmxInputPort, &packet, 0)) { /* We should check to make sure that there weren't any DMX errors. */ if (!packet.err) { @@ -122,7 +147,7 @@ void handleDMXInput() { dmxIsConnected = true; } - dmx_read(dmxPort, dmxdata, packet.size); + dmx_read(dmxInputPort, dmxdata, packet.size); handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); dmxLastUpdate = now; From a0ca243955d6ccefb68be3d6b99c83f7f3400593 Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 13:58:22 +0200 Subject: [PATCH 03/35] Move dmx_input pin allocations from wled.cpp to dmx.cpp --- wled00/dmx.cpp | 18 +++++++++++++++++- wled00/pin_manager.cpp | 4 +++- wled00/pin_manager.h | 19 ++++++++++--------- wled00/wled.cpp | 3 +++ wled00/xml.cpp | 6 +++--- 5 files changed, 36 insertions(+), 14 deletions(-) diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index 1bb1b250dd..f2f7d50337 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -88,9 +88,25 @@ bool dmxInputInitialized = false; //true once initDmx finished successfully void initDMX() { - if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) { + + const managed_pin_type pins[] = { + {dmxInputTransmitPin, false}, //these are not used as gpio pins, this isOutput is always false. + {dmxInputReceivePin, false}, + {dmxInputEnablePin, false} + }; + const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); + if(!pinsAllocated) + { + USER_PRINTF("Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); + USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(dmxInputReceivePin).c_str()); + USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(dmxInputTransmitPin).c_str()); + USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(dmxInputEnablePin).c_str()); + return; + } + + dmx_config_t config{ 255, /*alloc_size*/ 0, /*model_id*/ diff --git a/wled00/pin_manager.cpp b/wled00/pin_manager.cpp index 37ebd41ec0..6f16523010 100644 --- a/wled00/pin_manager.cpp +++ b/wled00/pin_manager.cpp @@ -141,7 +141,9 @@ bool PinManager::allocateMultiplePins(const managed_pin_type * mptArray, byte ar bool PinManager::allocatePin(byte gpio, bool output, PinOwner tag) { // HW I2C & SPI pins have to be allocated using allocateMultiplePins variant since there is always SCL/SDA pair - if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI) { + // DMX_INPUT pins have to be allocated using allocateMultiplePins variant since there is always RX/TX/EN triple + if (!isPinOk(gpio, output) || (gpio >= WLED_NUM_PINS) || tag==PinOwner::HW_I2C || tag==PinOwner::HW_SPI + || tag==PinOwner::DMX_INPUT) { #ifdef WLED_DEBUG if (gpio < 255) { // 255 (-1) is the "not defined GPIO" if (!isPinOk(gpio, output)) { diff --git a/wled00/pin_manager.h b/wled00/pin_manager.h index c8fb165ced..b285b6ee5d 100644 --- a/wled00/pin_manager.h +++ b/wled00/pin_manager.h @@ -35,15 +35,16 @@ enum struct PinOwner : uint8_t { Ethernet = 0x81, BusDigital = 0x82, BusOnOff = 0x83, - BusPwm = 0x84, // 'BusP' == PWM output using BusPwm - Button = 0x85, // 'Butn' == button from configuration - IR = 0x86, // 'IR' == IR receiver pin from configuration - Relay = 0x87, // 'Rly' == Relay pin from configuration - SPI_RAM = 0x88, // 'SpiR' == SPI RAM - DebugOut = 0x89, // 'Dbg' == debug output always IO1 - DMX = 0x8A, // 'DMX' == hard-coded to IO2 - HW_I2C = 0x8B, // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32) - HW_SPI = 0x8C, // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32) + BusPwm = 0x84, // 'BusP' == PWM output using BusPwm + Button = 0x85, // 'Butn' == button from configuration + IR = 0x86, // 'IR' == IR receiver pin from configuration + Relay = 0x87, // 'Rly' == Relay pin from configuration + SPI_RAM = 0x88, // 'SpiR' == SPI RAM + DebugOut = 0x89, // 'Dbg' == debug output always IO1 + DMX = 0x8A, // 'DMX' == hard-coded to IO2 + HW_I2C = 0x8B, // 'I2C' == hardware I2C pins (4&5 on ESP8266, 21&22 on ESP32) + HW_SPI = 0x8C, // 'SPI' == hardware (V)SPI pins (13,14&15 on ESP8266, 5,18&23 on ESP32) + DMX_INPUT = 0x8D, // 'DMX_INPUT' == DMX input via serial // Use UserMod IDs from const.h here UM_Unspecified = USERMOD_ID_UNSPECIFIED, // 0x01 UM_Example = USERMOD_ID_EXAMPLE, // 0x02 // Usermod "usermod_v2_example.h" diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 8144b0cd41..a8748162ef 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -423,11 +423,14 @@ void WLED::setup() #ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin PinManager::allocatePin(2, true, PinOwner::DMX); #endif +<<<<<<< HEAD #ifdef WLED_ENABLE_DMX_INPUT if(dmxInputTransmitPin > 0) PinManager::allocatePin(dmxInputTransmitPin, true, PinOwner::DMX); if(dmxInputReceivePin > 0) PinManager::allocatePin(dmxInputReceivePin, true, PinOwner::DMX); if(dmxInputEnablePin > 0) PinManager::allocatePin(dmxInputEnablePin, true, PinOwner::DMX); #endif +======= +>>>>>>> a516a7b8 (Move dmx_input pin allocations from wled.cpp to dmx.cpp) DEBUG_PRINTLN(F("Registering usermods ...")); registerUsermods(); diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 62de534250..5caa7159c4 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -437,12 +437,12 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormCheckbox(settingsScript,PSTR("EM"),e131Multicast); printSetFormValue(settingsScript,PSTR("EU"),e131Universe); #ifdef WLED_ENABLE_DMX - oappend(SET_F("hideNoDMX();")); // WLEDMM hide "not compiled in" message + settingsScript.print(SET_F("hideNoDMX();")); // hide "not compiled in" message #endif #ifndef WLED_ENABLE_DMX_INPUT - oappend(SET_F("hideDMXInput();")); // WLEDMM hide "dmx input" settings + settingsScript.print(SET_F("hideDMXInput();")); // hide "dmx input" settings #else - oappend(SET_F("hideNoDMXInput();")); // WLEDMM hide "not compiled in" message + settingsScript.print(SET_F("hideNoDMXInput();")); //hide "not comp iled in" message sappend('v',SET_F("IDMT"),dmxInputTransmitPin); sappend('v',SET_F("IDMR"),dmxInputReceivePin); sappend('v',SET_F("IDME"),dmxInputEnablePin); From f06a1e8b49697bdca84e9228c51fafda78b7cbae Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 14:12:08 +0200 Subject: [PATCH 04/35] Extract dmx_input from dmx.cpp into dmx_input.cpp. This greatly improves readability because it gets rid of most of the ifdefs. --- wled00/dmx.cpp | 111 ++------------------------------------ wled00/dmx_input.cpp | 124 +++++++++++++++++++++++++++++++++++++++++++ wled00/fcn_declare.h | 7 +++ wled00/wled.cpp | 3 ++ 4 files changed, 137 insertions(+), 108 deletions(-) create mode 100644 wled00/dmx_input.cpp diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index f2f7d50337..aa05c0113d 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -1,7 +1,7 @@ #include "wled.h" /* - * Support for DMX input and output via MAX485. + * Support for DMX input and output via serial (e.g. MAX485). * Change the output pin in src/dependencies/ESPDMX.cpp, if needed (ESP8266) * Change the output pin in src/dependencies/SparkFunDMX.cpp, if needed (ESP32) * ESP8266 Library from: @@ -75,112 +75,7 @@ void initDMX() { dmx.initWrite(512); // initialize with bus length #endif } -#endif - - -#ifdef WLED_ENABLE_DMX_INPUT - -#include - - -static dmx_port_t dmxInputPort = 2; //TODO make this configurable -bool dmxInputInitialized = false; //true once initDmx finished successfully - -void initDMX() { - - if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) - { - - const managed_pin_type pins[] = { - {dmxInputTransmitPin, false}, //these are not used as gpio pins, this isOutput is always false. - {dmxInputReceivePin, false}, - {dmxInputEnablePin, false} - }; - const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); - if(!pinsAllocated) - { - USER_PRINTF("Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); - USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(dmxInputReceivePin).c_str()); - USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(dmxInputTransmitPin).c_str()); - USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(dmxInputEnablePin).c_str()); - return; - } - - - dmx_config_t config{ - 255, /*alloc_size*/ - 0, /*model_id*/ - RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ - VERSION, /*software_version_id*/ - "undefined", /*software_version_label*/ - 1, /*current_personality*/ - {{15, "WLED Effect Mode"}}, /*personalities*/ - 1, /*personality_count*/ - 1, /*dmx_start_address*/ - }; - const std::string versionString = "WLED_V" + std::to_string(VERSION); - strncpy(config.software_version_label, versionString.c_str(), 32); - config.software_version_label[32] = '\0';//zero termination in case our string was longer than 32 chars - - if(!dmx_driver_install(dmxInputPort, &config, DMX_INTR_FLAGS_DEFAULT)) - { - USER_PRINTF("Error: Failed to install dmx driver\n"); - return; - } - - USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); - USER_PRINTF("Sending DMX on pin %u\n", dmxInputTransmitPin); - USER_PRINTF("DMX enable pin is: %u\n", dmxInputEnablePin); - dmx_set_pin(dmxInputPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); - - dmxInputInitialized = true; - } - else - { - USER_PRINTLN("DMX input disabled due to dmxInputReceivePin, dmxInputEnablePin or dmxInputTransmitPin not set"); - return; - } - -} - -bool dmxIsConnected = false; -unsigned long dmxLastUpdate = 0; - -void handleDMXInput() { - if(!dmxInputInitialized) { - return; - } - byte dmxdata[DMX_PACKET_SIZE]; - dmx_packet_t packet; - unsigned long now = millis(); - if (dmx_receive(dmxInputPort, &packet, 0)) { - - /* We should check to make sure that there weren't any DMX errors. */ - if (!packet.err) { - /* If this is the first DMX data we've received, lets log it! */ - if (!dmxIsConnected) { - USER_PRINTLN("DMX is connected!"); - dmxIsConnected = true; - } - - dmx_read(dmxInputPort, dmxdata, packet.size); - handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); - dmxLastUpdate = now; - - } else { - /* Oops! A DMX error occurred! Don't worry, this can happen when you first - connect or disconnect your DMX devices. If you are consistently getting - DMX errors, then something may have gone wrong with your code or - something is seriously wrong with your DMX transmitter. */ - DEBUG_PRINT("A DMX error occurred - "); - DEBUG_PRINTLN(packet.err); - } - } - else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { - dmxIsConnected = false; - USER_PRINTLN("DMX was disconnected."); - } -} #else -void initDMX(); +void initDMX(){} +void handleDMX() {} #endif diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp new file mode 100644 index 0000000000..8ed1d7ac33 --- /dev/null +++ b/wled00/dmx_input.cpp @@ -0,0 +1,124 @@ +#include "wled.h" + +#ifdef WLED_ENABLE_DMX_INPUT +#include +/* + * Support for DMX/RDM input via serial (e.g. max485) on ESP32 + * ESP32 Library from: + * https://github.com/sparkfun/SparkFunDMX + */ + +static dmx_port_t dmxInputPort = 2; //TODO make this configurable +bool dmxInputInitialized = false; //true once initDmx finished successfully + +void initDMXInput() { + + /** + * TODOS: + * - add personalities for all supported dmx input modes + * - select the personality that is stored in flash on startup + * - attach callback for personality change and store in flash if changed + * - attach callback for address change and store in flash + * - load dmx address from flash and set in config on startup + * - attach callback to rdm identify and flash leds when on + */ + if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) + { + + const managed_pin_type pins[] = { + {(int8_t)dmxInputTransmitPin, false}, //these are not used as gpio pins, this isOutput is always false. + {(int8_t)dmxInputReceivePin, false}, + {(int8_t)dmxInputEnablePin, false} + }; + const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); + if(!pinsAllocated) + { + USER_PRINTF("Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); + USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(dmxInputReceivePin).c_str()); + USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(dmxInputTransmitPin).c_str()); + USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(dmxInputEnablePin).c_str()); + return; + } + + + dmx_config_t config{ + 255, /*alloc_size*/ + 0, /*model_id*/ + RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ + VERSION, /*software_version_id*/ + "undefined", /*software_version_label*/ + 1, /*current_personality*/ + {{15, "WLED Effect Mode"}}, /*personalities*/ + 1, /*personality_count*/ + 1, /*dmx_start_address*/ + }; + const std::string versionString = "WLED_V" + std::to_string(VERSION); + strncpy(config.software_version_label, versionString.c_str(), 32); + config.software_version_label[32] = '\0';//zero termination in case our string was longer than 32 chars + + if(!dmx_driver_install(dmxInputPort, &config, DMX_INTR_FLAGS_DEFAULT)) + { + USER_PRINTF("Error: Failed to install dmx driver\n"); + return; + } + + USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); + USER_PRINTF("Sending DMX on pin %u\n", dmxInputTransmitPin); + USER_PRINTF("DMX enable pin is: %u\n", dmxInputEnablePin); + dmx_set_pin(dmxInputPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); + + dmxInputInitialized = true; + } + else + { + USER_PRINTLN("DMX input disabled due to dmxInputReceivePin, dmxInputEnablePin or dmxInputTransmitPin not set"); + return; + } + +} + +static bool dmxIsConnected = false; +static unsigned long dmxLastUpdate = 0; + +void handleDMXInput() { + if(!dmxInputInitialized) { + return; + } + byte dmxdata[DMX_PACKET_SIZE]; + dmx_packet_t packet; + unsigned long now = millis(); + if (dmx_receive(dmxInputPort, &packet, 0)) { + + /* We should check to make sure that there weren't any DMX errors. */ + if (!packet.err) { + /* If this is the first DMX data we've received, lets log it! */ + if (!dmxIsConnected) { + USER_PRINTLN("DMX is connected!"); + dmxIsConnected = true; + } + + dmx_read(dmxInputPort, dmxdata, packet.size); + handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); + dmxLastUpdate = now; + + } else { + /* Oops! A DMX error occurred! Don't worry, this can happen when you first + connect or disconnect your DMX devices. If you are consistently getting + DMX errors, then something may have gone wrong with your code or + something is seriously wrong with your DMX transmitter. */ + DEBUG_PRINT("A DMX error occurred - "); + DEBUG_PRINTLN(packet.err); + } + } + else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { + dmxIsConnected = false; + USER_PRINTLN("DMX was disconnected."); + } +} + + +#else +void initDMXInput(){} +void handleDMXInput(){} + +#endif \ No newline at end of file diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index cb21e8c2ed..c3ada1a578 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -186,6 +186,13 @@ void setRandomColor(byte* rgb); //dmx.cpp void initDMX(); void handleDMX(); +<<<<<<< HEAD +======= + +//dmx_input.cpp +void initDMXInput(); +void handleDMXInput(); +>>>>>>> b4bbf0a5 (Extract dmx_input from dmx.cpp into dmx_input.cpp.) //e131.cpp void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index a8748162ef..5e15394790 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -534,6 +534,9 @@ void WLED::setup() #ifdef WLED_ENABLE_DMX initDMX(); #endif +#ifdef WLED_ENABLE_DMX_INPUT + initDMXInput(); +#endif #ifdef WLED_ENABLE_ADALIGHT if (serialCanRX && Serial.available() > 0 && Serial.peek() == 'I') handleImprovPacket(); From 789d68e80d12a4be2d3e98cd75e6e6b0f9e4da2d Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 14:14:33 +0200 Subject: [PATCH 05/35] Move globals to top of file and change scope to compile unit only. Some minor cleanup changes --- wled00/dmx_input.cpp | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 8ed1d7ac33..009112b737 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -9,7 +9,9 @@ */ static dmx_port_t dmxInputPort = 2; //TODO make this configurable -bool dmxInputInitialized = false; //true once initDmx finished successfully +static bool dmxInputInitialized = false; //true once initDmx finished successfully +static bool dmxIsConnected = false; +static unsigned long dmxLastUpdate = 0; void initDMXInput() { @@ -21,6 +23,8 @@ void initDMXInput() { * - attach callback for address change and store in flash * - load dmx address from flash and set in config on startup * - attach callback to rdm identify and flash leds when on + * - Turn this into a class + * - Make all important config variables available via rdm */ if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) { @@ -40,7 +44,6 @@ void initDMXInput() { return; } - dmx_config_t config{ 255, /*alloc_size*/ 0, /*model_id*/ @@ -54,7 +57,7 @@ void initDMXInput() { }; const std::string versionString = "WLED_V" + std::to_string(VERSION); strncpy(config.software_version_label, versionString.c_str(), 32); - config.software_version_label[32] = '\0';//zero termination in case our string was longer than 32 chars + config.software_version_label[32] = '\0';//zero termination in case versionString string was longer than 32 chars if(!dmx_driver_install(dmxInputPort, &config, DMX_INTR_FLAGS_DEFAULT)) { @@ -74,12 +77,8 @@ void initDMXInput() { USER_PRINTLN("DMX input disabled due to dmxInputReceivePin, dmxInputEnablePin or dmxInputTransmitPin not set"); return; } - } -static bool dmxIsConnected = false; -static unsigned long dmxLastUpdate = 0; - void handleDMXInput() { if(!dmxInputInitialized) { return; @@ -88,10 +87,7 @@ void handleDMXInput() { dmx_packet_t packet; unsigned long now = millis(); if (dmx_receive(dmxInputPort, &packet, 0)) { - - /* We should check to make sure that there weren't any DMX errors. */ if (!packet.err) { - /* If this is the first DMX data we've received, lets log it! */ if (!dmxIsConnected) { USER_PRINTLN("DMX is connected!"); dmxIsConnected = true; @@ -102,12 +98,10 @@ void handleDMXInput() { dmxLastUpdate = now; } else { - /* Oops! A DMX error occurred! Don't worry, this can happen when you first - connect or disconnect your DMX devices. If you are consistently getting - DMX errors, then something may have gone wrong with your code or - something is seriously wrong with your DMX transmitter. */ + /*This can happen when you first connect or disconnect your DMX devices. + If you are consistently getting DMX errors, then something may have gone wrong. */ DEBUG_PRINT("A DMX error occurred - "); - DEBUG_PRINTLN(packet.err); + DEBUG_PRINTLN(packet.err); //TODO translate err code to string for output } } else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { From 0ad31c90f62961de6a03533d94ab7aeb6fa81067 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 16 Jan 2025 11:26:42 +0000 Subject: [PATCH 06/35] fix merge error --- wled00/wled.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 5e15394790..7b49b8b5da 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -423,14 +423,6 @@ void WLED::setup() #ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin PinManager::allocatePin(2, true, PinOwner::DMX); #endif -<<<<<<< HEAD -#ifdef WLED_ENABLE_DMX_INPUT - if(dmxInputTransmitPin > 0) PinManager::allocatePin(dmxInputTransmitPin, true, PinOwner::DMX); - if(dmxInputReceivePin > 0) PinManager::allocatePin(dmxInputReceivePin, true, PinOwner::DMX); - if(dmxInputEnablePin > 0) PinManager::allocatePin(dmxInputEnablePin, true, PinOwner::DMX); -#endif -======= ->>>>>>> a516a7b8 (Move dmx_input pin allocations from wled.cpp to dmx.cpp) DEBUG_PRINTLN(F("Registering usermods ...")); registerUsermods(); From a3bcf92ea5496e3ce56a9bed1eb74d06e0d03ec6 Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 15:18:54 +0200 Subject: [PATCH 07/35] Turn dmx_into into class with state. This is much nicer to read and in the future more state will be added to support all the rdm stuff. --- wled00/dmx_input.cpp | 147 +++++++++++++++++++++++-------------------- wled00/dmx_input.h | 23 +++++++ wled00/wled.cpp | 6 +- wled00/wled.h | 5 ++ 4 files changed, 111 insertions(+), 70 deletions(-) create mode 100644 wled00/dmx_input.h diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 009112b737..dcb04781cf 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -1,118 +1,127 @@ #include "wled.h" #ifdef WLED_ENABLE_DMX_INPUT +#include "dmx_input.h" #include -/* - * Support for DMX/RDM input via serial (e.g. max485) on ESP32 - * ESP32 Library from: - * https://github.com/sparkfun/SparkFunDMX - */ -static dmx_port_t dmxInputPort = 2; //TODO make this configurable -static bool dmxInputInitialized = false; //true once initDmx finished successfully -static bool dmxIsConnected = false; -static unsigned long dmxLastUpdate = 0; +#ifdef ESP8266 +#error DMX input is only supported on ESP32 +#endif -void initDMXInput() { +void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum) +{ - /** - * TODOS: - * - add personalities for all supported dmx input modes - * - select the personality that is stored in flash on startup - * - attach callback for personality change and store in flash if changed - * - attach callback for address change and store in flash - * - load dmx address from flash and set in config on startup - * - attach callback to rdm identify and flash leds when on - * - Turn this into a class - * - Make all important config variables available via rdm - */ - if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) + if (inputPortNum < 3 && inputPortNum > 0) + { + this->inputPortNum = inputPortNum; + } + else + { + USER_PRINTF("DMXInput: Error: invalid inputPortNum: %d\n", inputPortNum); + return; + } + + /** + * TODOS: + * - add personalities for all supported dmx input modes + * - select the personality that is stored in flash on startup + * - attach callback for personality change and store in flash if changed + * - attach callback for address change and store in flash + * - load dmx address from flash and set in config on startup + * - attach callback to rdm identify and flash leds when on + * - Make all important config variables available via rdm + */ + if (rxPin > 0 && enPin > 0 && txPin > 0) { const managed_pin_type pins[] = { - {(int8_t)dmxInputTransmitPin, false}, //these are not used as gpio pins, this isOutput is always false. - {(int8_t)dmxInputReceivePin, false}, - {(int8_t)dmxInputEnablePin, false} - }; + {(int8_t)txPin, false}, // these are not used as gpio pins, this isOutput is always false. + {(int8_t)rxPin, false}, + {(int8_t)enPin, false}}; const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); - if(!pinsAllocated) + if (!pinsAllocated) { - USER_PRINTF("Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); - USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(dmxInputReceivePin).c_str()); - USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(dmxInputTransmitPin).c_str()); - USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(dmxInputEnablePin).c_str()); + USER_PRINTF("DMXInput: Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); + USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(rxPin).c_str()); + USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(txPin).c_str()); + USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(enPin).c_str()); return; } - dmx_config_t config{ - 255, /*alloc_size*/ - 0, /*model_id*/ - RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ - VERSION, /*software_version_id*/ - "undefined", /*software_version_label*/ - 1, /*current_personality*/ - {{15, "WLED Effect Mode"}}, /*personalities*/ - 1, /*personality_count*/ - 1, /*dmx_start_address*/ + dmx_config_t config{ + 255, /*alloc_size*/ + 0, /*model_id*/ + RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ + VERSION, /*software_version_id*/ + "undefined", /*software_version_label*/ + 1, /*current_personality*/ + {{15, "WLED Effect Mode"}}, /*personalities*/ + 1, /*personality_count*/ + 1, /*dmx_start_address*/ }; const std::string versionString = "WLED_V" + std::to_string(VERSION); strncpy(config.software_version_label, versionString.c_str(), 32); - config.software_version_label[32] = '\0';//zero termination in case versionString string was longer than 32 chars + config.software_version_label[32] = '\0'; // zero termination in case versionString string was longer than 32 chars - if(!dmx_driver_install(dmxInputPort, &config, DMX_INTR_FLAGS_DEFAULT)) + if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { USER_PRINTF("Error: Failed to install dmx driver\n"); return; } - - USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); - USER_PRINTF("Sending DMX on pin %u\n", dmxInputTransmitPin); - USER_PRINTF("DMX enable pin is: %u\n", dmxInputEnablePin); - dmx_set_pin(dmxInputPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); - dmxInputInitialized = true; + USER_PRINTF("Listening for DMX on pin %u\n", rxPin); + USER_PRINTF("Sending DMX on pin %u\n", txPin); + USER_PRINTF("DMX enable pin is: %u\n", enPin); + dmx_set_pin(inputPortNum, txPin, rxPin, enPin); + + initialized = true; } - else + else { - USER_PRINTLN("DMX input disabled due to dmxInputReceivePin, dmxInputEnablePin or dmxInputTransmitPin not set"); + USER_PRINTLN("DMX input disabled due to rxPin, enPin or txPin not set"); return; } } -void handleDMXInput() { - if(!dmxInputInitialized) { +void DMXInput::update() +{ + if (!initialized) + { return; } byte dmxdata[DMX_PACKET_SIZE]; dmx_packet_t packet; unsigned long now = millis(); - if (dmx_receive(dmxInputPort, &packet, 0)) { - if (!packet.err) { - if (!dmxIsConnected) { + if (dmx_receive(inputPortNum, &packet, 0)) + { + if (!packet.err) + { + if (!connected) + { USER_PRINTLN("DMX is connected!"); - dmxIsConnected = true; + connected = true; } - dmx_read(dmxInputPort, dmxdata, packet.size); + dmx_read(inputPortNum, dmxdata, packet.size); handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); - dmxLastUpdate = now; - - } else { + lastUpdate = now; + } + else + { /*This can happen when you first connect or disconnect your DMX devices. If you are consistently getting DMX errors, then something may have gone wrong. */ - DEBUG_PRINT("A DMX error occurred - "); - DEBUG_PRINTLN(packet.err); //TODO translate err code to string for output + DEBUG_PRINT("A DMX error occurred - "); + DEBUG_PRINTLN(packet.err); // TODO translate err code to string for output } } - else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { - dmxIsConnected = false; + else if (connected && (now - lastUpdate > 5000)) + { + connected = false; USER_PRINTLN("DMX was disconnected."); } } - #else -void initDMXInput(){} -void handleDMXInput(){} - +void DMXInput::init(uint8_t, uint8_t, uint8_t, uint8_t) {} +void DMXInput::update() {} #endif \ No newline at end of file diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h new file mode 100644 index 0000000000..ac67bc206d --- /dev/null +++ b/wled00/dmx_input.h @@ -0,0 +1,23 @@ +#pragma once +#include + +/* + * Support for DMX/RDM input via serial (e.g. max485) on ESP32 + * ESP32 Library from: + * https://github.com/sparkfun/SparkFunDMX + */ +class DMXInput +{ +public: + void init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum); + void update(); + +private: + uint8_t inputPortNum = 255; // TODO make this configurable + /// True once the dmx input has been initialized successfully + bool initialized = false; // true once init finished successfully + /// True if dmx is currently connected + bool connected = false; + /// Timestamp of the last time a dmx frame was received + unsigned long lastUpdate = 0; +}; diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 7b49b8b5da..f9dfa55f30 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -67,6 +67,9 @@ void WLED::loop() #ifdef WLED_ENABLE_DMX handleDMX(); #endif + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.update(); + #endif #ifdef WLED_DEBUG unsigned long usermodMillis = millis(); @@ -527,7 +530,8 @@ void WLED::setup() initDMX(); #endif #ifdef WLED_ENABLE_DMX_INPUT - initDMXInput(); + const uint8_t dmxInputPortNumber = 2; //TODO turn into config variable?! + dmxInput.init(dmxInputReceivePin, dmxInputTransmitPin, dmxInputEnablePin, dmxInputPortNumber); #endif #ifdef WLED_ENABLE_ADALIGHT diff --git a/wled00/wled.h b/wled00/wled.h index 8adbd1ba5c..b366e82a15 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -144,6 +144,10 @@ #endif #endif +#ifdef WLED_ENABLE_DMX_INPUT + #include "dmx_input.h" +#endif + #include "src/dependencies/e131/ESPAsyncE131.h" #ifndef WLED_DISABLE_MQTT #include "src/dependencies/async-mqtt-client/AsyncMqttClient.h" @@ -463,6 +467,7 @@ WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to f WLED_GLOBAL int dmxInputTransmitPin _INIT(0); WLED_GLOBAL int dmxInputReceivePin _INIT(0); WLED_GLOBAL int dmxInputEnablePin _INIT(0); + WLED_GLOBAL DMXInput dmxInput; #endif WLED_GLOBAL uint16_t e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes) From 5a5661f136417eea1e19ce82541e034b8ca79228 Mon Sep 17 00:00:00 2001 From: Arne Date: Mon, 14 Aug 2023 15:54:19 +0200 Subject: [PATCH 08/35] handle dmx rdm identify --- wled00/dmx_input.cpp | 37 ++++++++++++++++++++++++++++++------- wled00/dmx_input.h | 8 ++++++-- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index dcb04781cf..28c3372589 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -1,13 +1,14 @@ #include "wled.h" #ifdef WLED_ENABLE_DMX_INPUT -#include "dmx_input.h" -#include #ifdef ESP8266 #error DMX input is only supported on ESP32 #endif +#include "dmx_input.h" +#include + void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum) { @@ -102,8 +103,21 @@ void DMXInput::update() connected = true; } - dmx_read(inputPortNum, dmxdata, packet.size); - handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); + uint8_t identify = 0; + const bool gotIdentify = rdm_get_identify_device(inputPortNum, &identify); + // gotIdentify should never be false because it is a default parameter in rdm but just in case we check for it anyway + if (identify && gotIdentify) + { + turnOnAllLeds(); + } + else + { + if (!packet.is_rdm) + { + dmx_read(inputPortNum, dmxdata, packet.size); + handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); + } + } lastUpdate = now; } else @@ -121,7 +135,16 @@ void DMXInput::update() } } -#else -void DMXInput::init(uint8_t, uint8_t, uint8_t, uint8_t) {} -void DMXInput::update() {} +void DMXInput::turnOnAllLeds() +{ + // TODO not sure if this is the correct way? + const uint16_t numPixels = strip.getLengthTotal(); + for (uint16_t i = 0; i < numPixels; ++i) + { + strip.setPixelColor(i, 255, 255, 255, 255); + } + strip.setBrightness(255, true); + strip.show(); +} + #endif \ No newline at end of file diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index ac67bc206d..b33c2a16ff 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -1,6 +1,6 @@ #pragma once #include - +#include /* * Support for DMX/RDM input via serial (e.g. max485) on ESP32 * ESP32 Library from: @@ -10,9 +10,13 @@ class DMXInput { public: void init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum); - void update(); + void update(); private: + + /// overrides everything and turns on all leds + void turnOnAllLeds(); + uint8_t inputPortNum = 255; // TODO make this configurable /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully From aed03cd03baca7100f7eef713905bc3bae6b55ce Mon Sep 17 00:00:00 2001 From: Arne Date: Thu, 17 Aug 2023 16:52:25 +0200 Subject: [PATCH 09/35] hack: disable dmx receiver while wifi is being activated This fixes a crash in the dmx receiver. The dmx receiver cannot work while cache is disabled. For some reason activating wifi disables the cache. In theory, the driver is placed in iram and should work, but it doesn't. This might be a bug in the driver. --- wled00/wled.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index f9dfa55f30..376cb6b28d 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -783,6 +783,9 @@ void WLED::initConnection() { DEBUG_PRINTF_P(PSTR("initConnection() called @ %lus.\n"), millis()/1000); + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.disable(); + #endif #ifdef WLED_ENABLE_WEBSOCKETS ws.onEvent(wsEvent); #endif @@ -811,6 +814,11 @@ void WLED::initConnection() if (!WLED_WIFI_CONFIGURED) { DEBUG_PRINTLN(F("No connection configured.")); if (!apActive) initAP(); // instantly go to ap mode + + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.enable(); + #endif + return; } else if (!apActive) { if (apBehavior == AP_BEHAVIOR_ALWAYS) { DEBUG_PRINTLN(F("Access point ALWAYS enabled.")); @@ -860,6 +868,10 @@ void WLED::initConnection() statusESPNow = espNowOK ? ESP_NOW_STATE_ON : ESP_NOW_STATE_ERROR; } #endif + + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.enable(); + #endif } void WLED::initInterfaces() From 5525a216969ab2150ffecef1659135887422fd24 Mon Sep 17 00:00:00 2001 From: Arne Date: Thu, 17 Aug 2023 16:53:02 +0200 Subject: [PATCH 10/35] rename settings --- wled00/cfg.cpp | 8 ++++---- wled00/data/settings_sync.htm | 12 ++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 1105077ca6..d3a8a0c6d3 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -526,7 +526,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { #ifdef WLED_ENABLE_DMX_INPUT CJSON(dmxInputTransmitPin, if_live_dmx[F("inputRxPin")]); CJSON(dmxInputReceivePin, if_live_dmx[F("inputTxPin")]); - CJSON(dmxInputEnablePin, if_live_dmx[F("enablePin")]); + CJSON(dmxInputEnablePin, if_live_dmx[F("inputEnablePin")]); #endif CJSON(arlsForceMaxBri, if_live[F("maxbri")]); @@ -1009,9 +1009,9 @@ void serializeConfig() { if_live_dmx[F("dss")] = DMXSegmentSpacing; if_live_dmx["mode"] = DMXMode; #ifdef WLED_ENABLE_DMX_INPUT - if_live_dmx[F("rxPin")] = dmxInputTransmitPin; - if_live_dmx[F("txPin")] = dmxInputReceivePin; - if_live_dmx[F("enablePin")] = dmxInputEnablePin; + if_live_dmx[F("inputRxPin")] = dmxInputTransmitPin; + if_live_dmx[F("inputTxPin")] = dmxInputReceivePin; + if_live_dmx[F("inputEnablePin")] = dmxInputEnablePin; #endif if_live[F("timeout")] = realtimeTimeoutMs / 100; diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 34b9fc6cdb..16bd3f7f68 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -151,6 +151,18 @@

Realtime

Force max brightness:
Disable realtime gamma correction:
Realtime LED offset: +
+ DMX Input Pins
+ DMX RX:
+ DMX TX:
+ DMX Enable:
+
+
+
This firmware build does not include DMX Input support.
+
+
+
This firmware build does not include DMX output support.
+

Alexa Voice Assistant

From 033c7abe62198052a53e8c29f04ec9b56a66ecf3 Mon Sep 17 00:00:00 2001 From: Arne Date: Thu, 17 Aug 2023 16:53:48 +0200 Subject: [PATCH 11/35] add enable/disable methods for dmxInput --- wled00/dmx_input.cpp | 15 +++++++++++++++ wled00/dmx_input.h | 4 ++++ 2 files changed, 19 insertions(+) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 28c3372589..a150fa780b 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -147,4 +147,19 @@ void DMXInput::turnOnAllLeds() strip.show(); } +void DMXInput::disable() +{ + if (initialized) + { + dmx_driver_disable(inputPortNum); + } +} +void DMXInput::enable() +{ + if(initialized) + { + dmx_driver_enable(inputPortNum); + } +} + #endif \ No newline at end of file diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index b33c2a16ff..b96077c1bd 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -12,6 +12,10 @@ class DMXInput void init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum); void update(); + /**disable dmx receiver (do this before disabling the cache)*/ + void disable(); + void enable(); + private: /// overrides everything and turns on all leds From 9d8fdd0b20e407948b975d847cd1eecbd062f0cf Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 18 Aug 2023 15:43:14 +0200 Subject: [PATCH 12/35] extract test for rdm identify into own method --- wled00/dmx_input.cpp | 15 +++++++++++---- wled00/dmx_input.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index a150fa780b..d46e3bebbe 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -103,11 +103,9 @@ void DMXInput::update() connected = true; } - uint8_t identify = 0; - const bool gotIdentify = rdm_get_identify_device(inputPortNum, &identify); - // gotIdentify should never be false because it is a default parameter in rdm but just in case we check for it anyway - if (identify && gotIdentify) + if (isIdentifyOn()) { + DEBUG_PRINTLN("RDM Identify active"); turnOnAllLeds(); } else @@ -162,4 +160,13 @@ void DMXInput::enable() } } +bool DMXInput::isIdentifyOn() const +{ + + uint8_t identify = 0; + const bool gotIdentify = rdm_get_identify_device(inputPortNum, &identify); + // gotIdentify should never be false because it is a default parameter in rdm + // but just in case we check for it anyway + return bool(identify) && gotIdentify; +} #endif \ No newline at end of file diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index b96077c1bd..27425d0d46 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -17,6 +17,8 @@ class DMXInput void enable(); private: + /// @return true if rdm identify is active + bool isIdentifyOn() const; /// overrides everything and turns on all leds void turnOnAllLeds(); From be3e331afba624182625d3d8dceddb4b550bc79e Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 18 Aug 2023 15:44:27 +0200 Subject: [PATCH 13/35] Monitor dmx personality and dmx start address for change and update rdm --- wled00/dmx_input.cpp | 28 ++++++++++++++++++++++++++++ wled00/dmx_input.h | 5 +++++ 2 files changed, 33 insertions(+) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index d46e3bebbe..e60be42002 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -90,6 +90,9 @@ void DMXInput::update() { return; } + + checkAndUpdateConfig(); + byte dmxdata[DMX_PACKET_SIZE]; dmx_packet_t packet; unsigned long now = millis(); @@ -169,4 +172,29 @@ bool DMXInput::isIdentifyOn() const // but just in case we check for it anyway return bool(identify) && gotIdentify; } + +void DMXInput::checkAndUpdateConfig() +{ + + /** + * The global configuration variables are modified by the web interface. + * If they differ from the driver configuration, we have to update the driver + * configuration. + */ + + const uint8_t currentPersonality = dmx_get_current_personality(inputPortNum); + if (currentPersonality != DMXMode) + { + DEBUG_PRINTF("DMX personality has changed from %d to %d\n", currentPersonality, DMXMode); + dmx_set_current_personality(inputPortNum, DMXMode); + } + + const uint16_t currentAddr = dmx_get_start_address(inputPortNum); + if (currentAddr != DMXAddress) + { + DEBUG_PRINTF("DMX address has changed from %d to %d\n", currentAddr, DMXAddress); + dmx_set_start_address(inputPortNum, DMXAddress); + } +} + #endif \ No newline at end of file diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 27425d0d46..1871176e97 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -20,6 +20,11 @@ class DMXInput /// @return true if rdm identify is active bool isIdentifyOn() const; + /** + * Checks if the global dmx config has changed and updates the changes in rdm + */ + void checkAndUpdateConfig(); + /// overrides everything and turns on all leds void turnOnAllLeds(); From 50b56c64f5af3be65395682949d05439f92a5b8a Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 18 Aug 2023 15:46:18 +0200 Subject: [PATCH 14/35] extract creation of dmx config into own method --- wled00/dmx_input.cpp | 59 +++++++++++++++++++++++++++++++++----------- wled00/dmx_input.h | 1 + 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index e60be42002..b60f56cdd4 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -9,6 +9,49 @@ #include "dmx_input.h" #include + +dmx_config_t DMXInput::createConfig() const +{ + + dmx_config_t config; + config.pd_size = 255; + config.dmx_start_address = DMXAddress; // TODO split between input and output address + config.model_id = 0; + config.product_category = RDM_PRODUCT_CATEGORY_FIXTURE; + config.software_version_id = VERSION; + + const std::string versionString = "WLED_V" + std::to_string(VERSION); + strncpy(config.software_version_label, versionString.c_str(), 32); + config.software_version_label[32] = '\0'; // zero termination in case versionString string was longer than 32 chars + + config.personalities[0].description = "SINGLE_RGB"; + config.personalities[0].footprint = 3; + config.personalities[1].description = "SINGLE_DRGB"; + config.personalities[1].footprint = 4; + config.personalities[2].description = "EFFECT"; + config.personalities[2].footprint = 15; + config.personalities[3].description = "MULTIPLE_RGB"; + config.personalities[3].footprint = std::min(512, int(strip.getLengthTotal()) * 3); + config.personalities[4].description = "MULTIPLE_DRGB"; + config.personalities[4].footprint = std::min(512, int(strip.getLengthTotal()) * 3 + 1); + config.personalities[5].description = "MULTIPLE_RGBW"; + config.personalities[5].footprint = std::min(512, int(strip.getLengthTotal()) * 4); + config.personalities[6].description = "EFFECT_W"; + config.personalities[6].footprint = 18; + config.personalities[7].description = "EFFECT_SEGMENT"; + config.personalities[7].footprint = std::min(512, strip.getSegmentsNum() * 15); + config.personalities[8].description = "EFFECT_SEGMENT_W"; + config.personalities[8].footprint = std::min(512, strip.getSegmentsNum() * 18); + config.personalities[9].description = "PRESET"; + config.personalities[9].footprint = 1; + + config.personality_count = 10; + // rdm personalities are numbered from 1, thus we can just set the DMXMode directly. + config.current_personality = DMXMode; + + return config; +} + void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum) { @@ -49,21 +92,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo return; } - dmx_config_t config{ - 255, /*alloc_size*/ - 0, /*model_id*/ - RDM_PRODUCT_CATEGORY_FIXTURE, /*product_category*/ - VERSION, /*software_version_id*/ - "undefined", /*software_version_label*/ - 1, /*current_personality*/ - {{15, "WLED Effect Mode"}}, /*personalities*/ - 1, /*personality_count*/ - 1, /*dmx_start_address*/ - }; - const std::string versionString = "WLED_V" + std::to_string(VERSION); - strncpy(config.software_version_label, versionString.c_str(), 32); - config.software_version_label[32] = '\0'; // zero termination in case versionString string was longer than 32 chars - + const auto config = createConfig(); if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { USER_PRINTF("Error: Failed to install dmx driver\n"); diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 1871176e97..88b1755c17 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -28,6 +28,7 @@ class DMXInput /// overrides everything and turns on all leds void turnOnAllLeds(); + dmx_config_t createConfig() const; uint8_t inputPortNum = 255; // TODO make this configurable /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully From 2989155f0567df45f9eca6cf644b7b2523f9fcbd Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 18 Aug 2023 15:47:01 +0200 Subject: [PATCH 15/35] handle rdm dmx address changes --- wled00/dmx_input.cpp | 19 +++++++++++++++++++ wled00/dmx_input.h | 5 +++++ 2 files changed, 24 insertions(+) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index b60f56cdd4..3cb9090b2d 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -9,6 +9,24 @@ #include "dmx_input.h" #include +void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, + void *context) +{ + DMXInput *dmx = static_cast(context); + + if (!dmx) + { + USER_PRINTLN("DMX: Error: no context in rdmAddressChangedCb"); + return; + } + + if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) + { + const uint16_t addr = dmx_get_start_address(dmx->inputPortNum); + DMXAddress = std::min(512, int(addr)); + USER_PRINTF("DMX start addr changed to: %d\n", DMXAddress); + } +} dmx_config_t DMXInput::createConfig() const { @@ -104,6 +122,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo USER_PRINTF("DMX enable pin is: %u\n", enPin); dmx_set_pin(inputPortNum, txPin, rxPin, enPin); + rdm_register_dmx_start_address(inputPortNum, rdmAddressChangedCb, this); initialized = true; } else diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 88b1755c17..df6c31d6f4 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -29,6 +29,11 @@ class DMXInput void turnOnAllLeds(); dmx_config_t createConfig() const; + + //is invoked whenver the dmx start address is changed via rdm + friend void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, + void *context); + uint8_t inputPortNum = 255; // TODO make this configurable /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully From 9a3b208ac5ed1a0bf12c6e1cefc73172d9bf3757 Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 18 Aug 2023 15:47:43 +0200 Subject: [PATCH 16/35] comments and cleanup --- wled00/dmx_input.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 3cb9090b2d..4294a3483d 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -85,19 +85,22 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo /** * TODOS: - * - add personalities for all supported dmx input modes - * - select the personality that is stored in flash on startup * - attach callback for personality change and store in flash if changed * - attach callback for address change and store in flash * - load dmx address from flash and set in config on startup * - attach callback to rdm identify and flash leds when on * - Make all important config variables available via rdm + * - RDM_PID_DEVICE_LABEL does not seem to be supported, yet? Implement in esp_dmx and create PR + * - implement changing personality in rdm. (not yet implemented in esp_dmx?) + * - This is more complicated because get personality requests two bytes but + * set personality only contains one byte. Thus the default parameter callback will + * not work. Need to think about this :D */ if (rxPin > 0 && enPin > 0 && txPin > 0) { const managed_pin_type pins[] = { - {(int8_t)txPin, false}, // these are not used as gpio pins, this isOutput is always false. + {(int8_t)txPin, false}, // these are not used as gpio pins, thus isOutput is always false. {(int8_t)rxPin, false}, {(int8_t)enPin, false}}; const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); @@ -159,14 +162,12 @@ void DMXInput::update() DEBUG_PRINTLN("RDM Identify active"); turnOnAllLeds(); } - else + else if (!packet.is_rdm) { - if (!packet.is_rdm) - { - dmx_read(inputPortNum, dmxdata, packet.size); - handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); - } + dmx_read(inputPortNum, dmxdata, packet.size); + handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); } + lastUpdate = now; } else @@ -205,7 +206,7 @@ void DMXInput::disable() } void DMXInput::enable() { - if(initialized) + if (initialized) { dmx_driver_enable(inputPortNum); } From b178c082714ce8c34b2eda92aab38a000e7e5811 Mon Sep 17 00:00:00 2001 From: Arne Date: Tue, 22 Aug 2023 22:09:21 +0200 Subject: [PATCH 17/35] Support dmx rdm personality change --- wled00/dmx_input.cpp | 35 ++++++++++++++++++++++------------- wled00/dmx_input.h | 6 +++++- wled00/wled.cpp | 11 +++++++++++ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 4294a3483d..0de1337e2a 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -9,6 +9,25 @@ #include "dmx_input.h" #include +void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, + void *context) +{ + DMXInput *dmx = static_cast(context); + + if (!dmx) + { + USER_PRINTLN("DMX: Error: no context in rdmPersonalityChangedCb"); + return; + } + + if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) + { + const uint8_t personality = dmx_get_current_personality(dmx->inputPortNum); + DMXMode = std::min(DMX_MODE_PRESET, std::max(DMX_MODE_SINGLE_RGB, int(personality))); + doSerializeConfig = true; + USER_PRINTF("DMX personality changed to to: %d\n", DMXMode); + } +} void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, void *context) { @@ -24,6 +43,7 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, { const uint16_t addr = dmx_get_start_address(dmx->inputPortNum); DMXAddress = std::min(512, int(addr)); + doSerializeConfig = true; USER_PRINTF("DMX start addr changed to: %d\n", DMXAddress); } } @@ -37,6 +57,7 @@ dmx_config_t DMXInput::createConfig() const config.model_id = 0; config.product_category = RDM_PRODUCT_CATEGORY_FIXTURE; config.software_version_id = VERSION; + strcpy(config.device_label, "WLED_MM"); const std::string versionString = "WLED_V" + std::to_string(VERSION); strncpy(config.software_version_label, versionString.c_str(), 32); @@ -83,19 +104,6 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo return; } - /** - * TODOS: - * - attach callback for personality change and store in flash if changed - * - attach callback for address change and store in flash - * - load dmx address from flash and set in config on startup - * - attach callback to rdm identify and flash leds when on - * - Make all important config variables available via rdm - * - RDM_PID_DEVICE_LABEL does not seem to be supported, yet? Implement in esp_dmx and create PR - * - implement changing personality in rdm. (not yet implemented in esp_dmx?) - * - This is more complicated because get personality requests two bytes but - * set personality only contains one byte. Thus the default parameter callback will - * not work. Need to think about this :D - */ if (rxPin > 0 && enPin > 0 && txPin > 0) { @@ -126,6 +134,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo dmx_set_pin(inputPortNum, txPin, rxPin, enPin); rdm_register_dmx_start_address(inputPortNum, rdmAddressChangedCb, this); + rdm_register_dmx_personality(inputPortNum, rdmPersonalityChangedCb, this); initialized = true; } else diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index df6c31d6f4..b762e59be2 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -30,10 +30,14 @@ class DMXInput dmx_config_t createConfig() const; - //is invoked whenver the dmx start address is changed via rdm + // is invoked whenver the dmx start address is changed via rdm friend void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, void *context); + // is invoked whenever the personality is changed via rdm + friend void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, + void *context); + uint8_t inputPortNum = 255; // TODO make this configurable /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 376cb6b28d..8b2b33762f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -256,6 +256,17 @@ void WLED::loop() } #endif +if (doSerializeConfig) + { + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.disable(); + #endif + + #ifdef WLED_ENABLE_DMX_INPUT + dmxInput.enable(); + #endif + } + if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration reset(); From 2cc5a29b8633dcb04e0bd2b68b54756e57cb63d6 Mon Sep 17 00:00:00 2001 From: Arne Date: Tue, 22 Aug 2023 22:24:31 +0200 Subject: [PATCH 18/35] keep dmx rdm identify on if dmx disconnects. Some rdm testers disconnect after setting it. --- wled00/dmx_input.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 0de1337e2a..f90515fd08 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -165,12 +165,6 @@ void DMXInput::update() USER_PRINTLN("DMX is connected!"); connected = true; } - - if (isIdentifyOn()) - { - DEBUG_PRINTLN("RDM Identify active"); - turnOnAllLeds(); - } else if (!packet.is_rdm) { dmx_read(inputPortNum, dmxdata, packet.size); @@ -192,6 +186,12 @@ void DMXInput::update() connected = false; USER_PRINTLN("DMX was disconnected."); } + + if (isIdentifyOn()) + { + DEBUG_PRINTLN("RDM Identify active"); + turnOnAllLeds(); + } } void DMXInput::turnOnAllLeds() From 84eb6fd460cbbb87712e67d789a079c9fb60e48a Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 23 Aug 2023 14:33:12 +0200 Subject: [PATCH 19/35] Add dmx input port to configuration --- wled00/data/settings_sync.htm | 1 + wled00/set.cpp | 4 +++- wled00/wled.cpp | 3 +-- wled00/wled.h | 1 + wled00/xml.cpp | 1 + 5 files changed, 7 insertions(+), 3 deletions(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 16bd3f7f68..8e142dc9be 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -156,6 +156,7 @@

Realtime

DMX RX:
DMX TX:
DMX Enable:
+ DMX Port:

This firmware build does not include DMX Input support.
diff --git a/wled00/set.cpp b/wled00/set.cpp index 9a12cdc215..08a0180ad5 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -423,7 +423,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) #ifdef WLED_ENABLE_DMX_INPUT dmxInputTransmitPin = request->arg(F("IDMT")).toInt(); dmxInputReceivePin = request->arg(F("IDMR")).toInt(); - dmxInputEnablePin= request->arg(F("IDME")).toInt(); + dmxInputEnablePin = request->arg(F("IDME")).toInt(); + dmxInputPort = request->arg(F("IDMP")).toInt(); + if(dmxInputPort <= 0 || dmxInputPort > 2) dmxInputPort = 2; #endif #ifndef WLED_DISABLE_ALEXA diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 8b2b33762f..341036abf7 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -541,8 +541,7 @@ void WLED::setup() initDMX(); #endif #ifdef WLED_ENABLE_DMX_INPUT - const uint8_t dmxInputPortNumber = 2; //TODO turn into config variable?! - dmxInput.init(dmxInputReceivePin, dmxInputTransmitPin, dmxInputEnablePin, dmxInputPortNumber); + dmxInput.init(dmxInputReceivePin, dmxInputTransmitPin, dmxInputEnablePin, dmxInputPort); #endif #ifdef WLED_ENABLE_ADALIGHT diff --git a/wled00/wled.h b/wled00/wled.h index b366e82a15..b7f1ae710b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -467,6 +467,7 @@ WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to f WLED_GLOBAL int dmxInputTransmitPin _INIT(0); WLED_GLOBAL int dmxInputReceivePin _INIT(0); WLED_GLOBAL int dmxInputEnablePin _INIT(0); + WLED_GLOBAL int dmxInputPort _INIT(2); WLED_GLOBAL DMXInput dmxInput; #endif diff --git a/wled00/xml.cpp b/wled00/xml.cpp index 5caa7159c4..aa49de0228 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -446,6 +446,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) sappend('v',SET_F("IDMT"),dmxInputTransmitPin); sappend('v',SET_F("IDMR"),dmxInputReceivePin); sappend('v',SET_F("IDME"),dmxInputEnablePin); + sappend('v',SET_F("IDMP"),dmxInputPort); #endif printSetFormValue(settingsScript,PSTR("DA"),DMXAddress); printSetFormValue(settingsScript,PSTR("XX"),DMXSegmentSpacing); From 7f9cc6751875dd4882f91bf58adcb820d76cab8c Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 23 Aug 2023 14:50:22 +0200 Subject: [PATCH 20/35] Rename WLED_ENABLE_DMX to WLED_ENABLE_DMX_OUTPUT --- tools/cdata.js | 2 +- wled00/cfg.cpp | 6 +++--- wled00/const.h | 7 +++++++ wled00/dmx.cpp | 2 +- wled00/e131.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.cpp | 6 +++--- wled00/wled.h | 7 ++++--- wled00/wled_eeprom.cpp | 4 ++-- wled00/wled_server.cpp | 10 +++++----- wled00/xml.cpp | 8 ++++---- 11 files changed, 32 insertions(+), 24 deletions(-) diff --git a/tools/cdata.js b/tools/cdata.js index c5d3c6aa52..b9f29694cc 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -358,7 +358,7 @@ writeChunks( method: "plaintext", filter: "html-minify", mangle: (str) => ` -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT ${str.replace(/function FM\(\)[ ]?\{/gms, "function FM() {%DMXVARS%\n")} #else const char PAGE_dmxmap[] PROGMEM = R"=====()====="; diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index d3a8a0c6d3..4d8918db4d 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -651,7 +651,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { getStringFromJson(otaPass, pwd, 33); //normally not present due to security } - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT JsonObject dmx = doc["dmx"]; CJSON(DMXChannels, dmx[F("chan")]); CJSON(DMXGap,dmx[F("gap")]); @@ -1116,8 +1116,8 @@ void serializeConfig() { ota[F("pskl")] = strlen(otaPass); ota[F("aota")] = aOtaEnabled; - #ifdef WLED_ENABLE_DMX - JsonObject dmx = root.createNestedObject("dmx"); + #ifdef WLED_ENABLE_DMX_OUTPUT + JsonObject dmx = doc.createNestedObject("dmx"); dmx[F("chan")] = DMXChannels; dmx[F("gap")] = DMXGap; dmx["start"] = DMXStart; diff --git a/wled00/const.h b/wled00/const.h index bdd20beba1..e0e4916d33 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -583,6 +583,13 @@ #define DEFAULT_LED_COUNT 30 #define INTERFACE_UPDATE_COOLDOWN 1000 // time in ms to wait between websockets, alexa, and MQTT updates +#ifdef WLED_ENABLE_DMX_OUTPUT +#if (LEDPIN == 2) + #undef LEDPIN + #define LEDPIN 1 + #warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1." +#endif +#endif #define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct #define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes diff --git a/wled00/dmx.cpp b/wled00/dmx.cpp index aa05c0113d..efdd902ec1 100644 --- a/wled00/dmx.cpp +++ b/wled00/dmx.cpp @@ -10,7 +10,7 @@ * https://github.com/sparkfun/SparkFunDMX */ -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT void handleDMX() { diff --git a/wled00/e131.cpp b/wled00/e131.cpp index bc26a0639e..98ba5dfd95 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -93,7 +93,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ return; } - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT // does not act on out-of-order packets yet if (e131ProxyUniverse > 0 && uni == e131ProxyUniverse) { for (uint16_t i = 1; i <= dmxChannels; i++) diff --git a/wled00/set.cpp b/wled00/set.cpp index 08a0180ad5..7ffd806538 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -598,7 +598,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) } } - #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled if (subPage == SUBPAGE_DMX) { int t = request->arg(F("PU")).toInt(); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 341036abf7..e19361a18b 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -64,7 +64,7 @@ void WLED::loop() handleImprovWifiScan(); handleNotifications(); handleTransitions(); - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT handleDMX(); #endif #ifdef WLED_ENABLE_DMX_INPUT @@ -434,7 +434,7 @@ void WLED::setup() #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) PinManager::allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output #endif -#ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin +#ifdef WLED_ENABLE_DMX_OUTPUT //reserve GPIO2 as hardcoded DMX pin PinManager::allocatePin(2, true, PinOwner::DMX); #endif @@ -537,7 +537,7 @@ void WLED::setup() ArduinoOTA.setHostname(cmDNS); } #endif -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT initDMX(); #endif #ifdef WLED_ENABLE_DMX_INPUT diff --git a/wled00/wled.h b/wled00/wled.h index b7f1ae710b..af4a0a84d6 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -34,7 +34,8 @@ #else #undef WLED_ENABLE_ADALIGHT // disable has priority over enable #endif -//#define WLED_ENABLE_DMX // uses 3.5kb +//#define WLED_ENABLE_DMX_OUTPUT // uses 3.5kb (use LEDPIN other than 2) +//#define WLED_ENABLE_DMX_INPUT // Listen for DMX over Serial #ifndef WLED_DISABLE_LOXONE #define WLED_ENABLE_LOXONE // uses 1.2kb #endif @@ -136,7 +137,7 @@ #include "src/dependencies/espalexa/EspalexaDevice.h" #endif -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 @@ -448,7 +449,7 @@ WLED_GLOBAL int arlsOffset _INIT(0); // realtime LE WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if gamma correction is handled by the source WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp index 8582b49df9..99995debd5 100644 --- a/wled00/wled_eeprom.cpp +++ b/wled00/wled_eeprom.cpp @@ -313,7 +313,7 @@ void loadSettingsFromEEPROM() e131Port = EEPROM.read(2187) + ((EEPROM.read(2188) << 8) & 0xFF00); } - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT if (lastEEPROMversion > 19) { e131ProxyUniverse = EEPROM.read(2185) + ((EEPROM.read(2186) << 8) & 0xFF00); @@ -342,7 +342,7 @@ void loadSettingsFromEEPROM() //custom macro memory (16 slots/ each 64byte) //1024-2047 reserved - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT // DMX (2530 - 2549)2535 DMXChannels = EEPROM.read(2530); DMXGap = EEPROM.read(2531) + ((EEPROM.read(2532) << 8) & 0xFF00); diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index e8cbb41ae5..327cff2c33 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -96,7 +96,7 @@ static void handleStaticContent(AsyncWebServerRequest *request, const String &pa request->send(response); } -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT static String dmxProcessor(const String& var) { String mapJS; @@ -426,7 +426,7 @@ void initServer() #endif -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor); }); @@ -554,7 +554,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { else if (url.indexOf( "sync") > 0) subPage = SUBPAGE_SYNC; else if (url.indexOf( "time") > 0) subPage = SUBPAGE_TIME; else if (url.indexOf(F("sec")) > 0) subPage = SUBPAGE_SEC; -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT else if (url.indexOf( "dmx") > 0) subPage = SUBPAGE_DMX; #endif else if (url.indexOf( "um") > 0) subPage = SUBPAGE_UM; @@ -591,7 +591,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { case SUBPAGE_SYNC : strcpy_P(s, PSTR("Sync")); break; case SUBPAGE_TIME : strcpy_P(s, PSTR("Time")); break; case SUBPAGE_SEC : strcpy_P(s, PSTR("Security")); if (doReboot) strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break; -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT case SUBPAGE_DMX : strcpy_P(s, PSTR("DMX")); break; #endif case SUBPAGE_UM : strcpy_P(s, PSTR("Usermods")); break; @@ -626,7 +626,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { case SUBPAGE_SYNC : content = PAGE_settings_sync; len = PAGE_settings_sync_length; break; case SUBPAGE_TIME : content = PAGE_settings_time; len = PAGE_settings_time_length; break; case SUBPAGE_SEC : content = PAGE_settings_sec; len = PAGE_settings_sec_length; break; -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT case SUBPAGE_DMX : content = PAGE_settings_dmx; len = PAGE_settings_dmx_length; break; #endif case SUBPAGE_UM : content = PAGE_settings_um; len = PAGE_settings_um_length; break; diff --git a/wled00/xml.cpp b/wled00/xml.cpp index aa49de0228..b3ba4a0e81 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -100,7 +100,7 @@ void appendGPIOinfo(Print& settingsScript) { firstPin = false; } } - #ifdef WLED_ENABLE_DMX + #ifdef WLED_ENABLE_DMX_OUTPUT if (!firstPin) settingsScript.print(','); settingsScript.print(2); // DMX hardcoded pin firstPin = false; @@ -164,7 +164,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) #ifdef WLED_DISABLE_2D // include only if 2D is not compiled in settingsScript.print(F("gId('2dbtn').style.display='none';")); #endif - #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled settingsScript.print(F("gId('dmxbtn').style.display='';")); #endif } @@ -436,7 +436,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormCheckbox(settingsScript,PSTR("ES"),e131SkipOutOfSequence); printSetFormCheckbox(settingsScript,PSTR("EM"),e131Multicast); printSetFormValue(settingsScript,PSTR("EU"),e131Universe); -#ifdef WLED_ENABLE_DMX +#ifdef WLED_ENABLE_DMX_OUTPUT settingsScript.print(SET_F("hideNoDMX();")); // hide "not compiled in" message #endif #ifndef WLED_ENABLE_DMX_INPUT @@ -596,7 +596,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) settingsScript.printf_P(PSTR("sd=\"%s\";"), serverDescription); } - #ifdef WLED_ENABLE_DMX // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled if (subPage == SUBPAGE_DMX) { printSetFormValue(settingsScript,PSTR("PU"),e131ProxyUniverse); From fa80c62b2862352ac073e8a3067900e0541d4a4d Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 23 Aug 2023 14:50:53 +0200 Subject: [PATCH 21/35] rename dmx.cpp -> dmx_output.cpp --- wled00/{dmx.cpp => dmx_output.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename wled00/{dmx.cpp => dmx_output.cpp} (100%) diff --git a/wled00/dmx.cpp b/wled00/dmx_output.cpp similarity index 100% rename from wled00/dmx.cpp rename to wled00/dmx_output.cpp From 11b48bc3745a7dd1b20857486c9d2c43e8ce294e Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 23 Aug 2023 14:52:57 +0200 Subject: [PATCH 22/35] rename handleDMX() handleDMXOutput() --- wled00/dmx_output.cpp | 4 ++-- wled00/fcn_declare.h | 5 +---- wled00/wled.cpp | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index efdd902ec1..1c883c15a8 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -12,7 +12,7 @@ #ifdef WLED_ENABLE_DMX_OUTPUT -void handleDMX() +void handleDMXOutput() { // don't act, when in DMX Proxy mode if (e131ProxyUniverse != 0) return; @@ -77,5 +77,5 @@ void initDMX() { } #else void initDMX(){} -void handleDMX() {} +void handleDMXOutput() {} #endif diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index c3ada1a578..831cc68f84 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -185,14 +185,11 @@ void setRandomColor(byte* rgb); //dmx.cpp void initDMX(); -void handleDMX(); -<<<<<<< HEAD -======= +void handleDMXOutput(); //dmx_input.cpp void initDMXInput(); void handleDMXInput(); ->>>>>>> b4bbf0a5 (Extract dmx_input from dmx.cpp into dmx_input.cpp.) //e131.cpp void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index e19361a18b..27f74af026 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -65,7 +65,7 @@ void WLED::loop() handleNotifications(); handleTransitions(); #ifdef WLED_ENABLE_DMX_OUTPUT - handleDMX(); + handleDMXOutput(); #endif #ifdef WLED_ENABLE_DMX_INPUT dmxInput.update(); From 67e8a00b6dfd7673076d3617c339a8d41e59e51f Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 23 Aug 2023 15:04:28 +0200 Subject: [PATCH 23/35] rename initDmx() -> initDmxOutput() --- wled00/dmx_output.cpp | 4 ++-- wled00/fcn_declare.h | 4 ++-- wled00/wled.cpp | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index 1c883c15a8..12095965e1 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -68,7 +68,7 @@ void handleDMXOutput() dmx.update(); // update the DMX bus } -void initDMX() { +void initDMXOutput() { #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) dmx.init(512); // initialize with bus length #else @@ -76,6 +76,6 @@ void initDMX() { #endif } #else -void initDMX(){} +void initDMXOutput(){} void handleDMXOutput() {} #endif diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index 831cc68f84..db6c6b872a 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -183,8 +183,8 @@ uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb); uint16_t approximateKelvinFromRGB(uint32_t rgb); void setRandomColor(byte* rgb); -//dmx.cpp -void initDMX(); +//dmx_output.cpp +void initDMXOutput(); void handleDMXOutput(); //dmx_input.cpp diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 27f74af026..44e2faf5aa 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -538,7 +538,7 @@ void WLED::setup() } #endif #ifdef WLED_ENABLE_DMX_OUTPUT - initDMX(); + initDMXOutput(); #endif #ifdef WLED_ENABLE_DMX_INPUT dmxInput.init(dmxInputReceivePin, dmxInputTransmitPin, dmxInputEnablePin, dmxInputPort); From 68e9d701dea5620a4daa503ee8672e8707e7cbe7 Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 25 Aug 2023 20:59:03 +0200 Subject: [PATCH 24/35] Do no longer disable dmx_input when cache is disabled. No longer needed because missing ISR_ATTR have been added to esp_dmx. --- wled00/wled.cpp | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 44e2faf5aa..46d156e79f 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -256,17 +256,6 @@ void WLED::loop() } #endif -if (doSerializeConfig) - { - #ifdef WLED_ENABLE_DMX_INPUT - dmxInput.disable(); - #endif - - #ifdef WLED_ENABLE_DMX_INPUT - dmxInput.enable(); - #endif - } - if (doReboot && (!doInitBusses || !doSerializeConfig)) // if busses have to be inited & saved, wait until next iteration reset(); @@ -792,10 +781,6 @@ int8_t WLED::findWiFi(bool doScan) { void WLED::initConnection() { DEBUG_PRINTF_P(PSTR("initConnection() called @ %lus.\n"), millis()/1000); - - #ifdef WLED_ENABLE_DMX_INPUT - dmxInput.disable(); - #endif #ifdef WLED_ENABLE_WEBSOCKETS ws.onEvent(wsEvent); #endif @@ -824,10 +809,6 @@ void WLED::initConnection() if (!WLED_WIFI_CONFIGURED) { DEBUG_PRINTLN(F("No connection configured.")); if (!apActive) initAP(); // instantly go to ap mode - - #ifdef WLED_ENABLE_DMX_INPUT - dmxInput.enable(); - #endif return; } else if (!apActive) { if (apBehavior == AP_BEHAVIOR_ALWAYS) { @@ -878,10 +859,6 @@ void WLED::initConnection() statusESPNow = espNowOK ? ESP_NOW_STATE_ON : ESP_NOW_STATE_ERROR; } #endif - - #ifdef WLED_ENABLE_DMX_INPUT - dmxInput.enable(); - #endif } void WLED::initInterfaces() From 8f398dfd08e44497b17ed16f0432995858a0c363 Mon Sep 17 00:00:00 2001 From: Arne Date: Fri, 25 Aug 2023 20:59:46 +0200 Subject: [PATCH 25/35] Move dmx_input into its own task on core 0. This was necessary because otherwise it is not able to respond to rdm in time. --- wled00/dmx_input.cpp | 110 +++++++++++++++++++++++++++++-------------- wled00/dmx_input.h | 31 ++++++++++-- 2 files changed, 103 insertions(+), 38 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index f90515fd08..4ccfbab76b 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -28,6 +28,7 @@ void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, USER_PRINTF("DMX personality changed to to: %d\n", DMXMode); } } + void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, void *context) { @@ -48,9 +49,8 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, } } -dmx_config_t DMXInput::createConfig() const +static dmx_config_t createConfig() { - dmx_config_t config; config.pd_size = 255; config.dmx_start_address = DMXAddress; // TODO split between input and output address @@ -91,9 +91,55 @@ dmx_config_t DMXInput::createConfig() const return config; } +void dmxReceiverTask(void *context) +{ + DMXInput *instance = static_cast(context); + if (instance == nullptr) + { + return; + } + + if (instance->installDriver()) + { + while (true) + { + instance->updateInternal(); + } + } +} + +bool DMXInput::installDriver() +{ + + const auto config = createConfig(); + if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) + { + USER_PRINTF("Error: Failed to install dmx driver\n"); + return false; + } + + USER_PRINTF("Listening for DMX on pin %u\n", rxPin); + USER_PRINTF("Sending DMX on pin %u\n", txPin); + USER_PRINTF("DMX enable pin is: %u\n", enPin); + dmx_set_pin(inputPortNum, txPin, rxPin, enPin); + + rdm_register_dmx_start_address(inputPortNum, rdmAddressChangedCb, this); + rdm_register_dmx_personality(inputPortNum, rdmPersonalityChangedCb, this); + initialized = true; + return true; +} + void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum) { +#ifdef WLED_ENABLE_DMX_OUTPUT + if(inputPortNum == dmxOutputPort) + { + USER_PRINTF("DMXInput: Error: Input port == output port"); + return; + } +#endif + if (inputPortNum < 3 && inputPortNum > 0) { this->inputPortNum = inputPortNum; @@ -121,21 +167,17 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo return; } - const auto config = createConfig(); - if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) + this->rxPin = rxPin; + this->txPin = txPin; + this->enPin = enPin; + + // put dmx receiver into seperate task because it should not be blocked + // pin to core 0 because wled is running on core 1 + xTaskCreatePinnedToCore(dmxReceiverTask, "DMX_RCV_TASK", 10240, this, 2, &task, 0); + if (!task) { - USER_PRINTF("Error: Failed to install dmx driver\n"); - return; + USER_PRINTF("Error: Failed to create dmx rcv task"); } - - USER_PRINTF("Listening for DMX on pin %u\n", rxPin); - USER_PRINTF("Sending DMX on pin %u\n", txPin); - USER_PRINTF("DMX enable pin is: %u\n", enPin); - dmx_set_pin(inputPortNum, txPin, rxPin, enPin); - - rdm_register_dmx_start_address(inputPortNum, rdmAddressChangedCb, this); - rdm_register_dmx_personality(inputPortNum, rdmPersonalityChangedCb, this); - initialized = true; } else { @@ -144,7 +186,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo } } -void DMXInput::update() +void DMXInput::updateInternal() { if (!initialized) { @@ -153,45 +195,43 @@ void DMXInput::update() checkAndUpdateConfig(); - byte dmxdata[DMX_PACKET_SIZE]; dmx_packet_t packet; unsigned long now = millis(); - if (dmx_receive(inputPortNum, &packet, 0)) + if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) { if (!packet.err) { - if (!connected) - { - USER_PRINTLN("DMX is connected!"); - connected = true; - } - else if (!packet.is_rdm) + connected = true; + identify = isIdentifyOn(); + if (!packet.is_rdm) { + const std::lock_guard lock(dmxDataLock); dmx_read(inputPortNum, dmxdata, packet.size); - handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); } - - lastUpdate = now; } else { - /*This can happen when you first connect or disconnect your DMX devices. - If you are consistently getting DMX errors, then something may have gone wrong. */ - DEBUG_PRINT("A DMX error occurred - "); - DEBUG_PRINTLN(packet.err); // TODO translate err code to string for output + connected = false; } } - else if (connected && (now - lastUpdate > 5000)) + else { connected = false; - USER_PRINTLN("DMX was disconnected."); } +} - if (isIdentifyOn()) + +void DMXInput::update() +{ + if (identify) { - DEBUG_PRINTLN("RDM Identify active"); turnOnAllLeds(); } + else if (connected) + { + const std::lock_guard lock(dmxDataLock); + handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); + } } void DMXInput::turnOnAllLeds() diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index b762e59be2..7a6266c50e 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -1,6 +1,9 @@ #pragma once #include #include +#include +#include + /* * Support for DMX/RDM input via serial (e.g. max485) on ESP32 * ESP32 Library from: @@ -28,7 +31,12 @@ class DMXInput /// overrides everything and turns on all leds void turnOnAllLeds(); - dmx_config_t createConfig() const; + /// installs the dmx driver + /// @return false on fail + bool installDriver(); + + /// is called by the dmx receive task regularly to receive new dmx data + void updateInternal(); // is invoked whenver the dmx start address is changed via rdm friend void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, @@ -38,11 +46,28 @@ class DMXInput friend void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, void *context); - uint8_t inputPortNum = 255; // TODO make this configurable + /// The internal dmx task. + /// This is the main loop of the dmx receiver. It never returns. + friend void dmxReceiverTask(void * context); + + uint8_t inputPortNum = 255; + uint8_t rxPin = 255; + uint8_t txPin = 255; + uint8_t enPin = 255; + + /// is written to by the dmx receive task. + byte dmxdata[DMX_PACKET_SIZE]; //TODO add locking somehow? maybe double buffer? /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully /// True if dmx is currently connected - bool connected = false; + std::atomic connected{false}; + std::atomic identify{false}; /// Timestamp of the last time a dmx frame was received unsigned long lastUpdate = 0; + + /// Taskhandle of the dmx task that is running in the background + TaskHandle_t task; + /// Guards access to dmxData + std::mutex dmxDataLock; + }; From 6598265f9bf6d2c0de6cea38c4091eb8bafa5167 Mon Sep 17 00:00:00 2001 From: Arne Date: Sun, 3 Sep 2023 16:37:19 +0200 Subject: [PATCH 26/35] make compile after rebase --- wled00/dmx_input.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 4ccfbab76b..902303bb77 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -133,11 +133,12 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo { #ifdef WLED_ENABLE_DMX_OUTPUT - if(inputPortNum == dmxOutputPort) - { - USER_PRINTF("DMXInput: Error: Input port == output port"); - return; - } + //TODO add again once dmx output has been merged + // if(inputPortNum == dmxOutputPort) + // { + // USER_PRINTF("DMXInput: Error: Input port == output port"); + // return; + // } #endif if (inputPortNum < 3 && inputPortNum > 0) From 8570922dccc3c3cf2ffa27130c3a500b9ebacd0a Mon Sep 17 00:00:00 2001 From: Arne Date: Sun, 22 Oct 2023 20:32:46 +0200 Subject: [PATCH 27/35] chore: adapt code style --- wled00/dmx_input.cpp | 80 +++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 53 deletions(-) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index 902303bb77..af0bb679dc 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -14,14 +14,12 @@ void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, { DMXInput *dmx = static_cast(context); - if (!dmx) - { + if (!dmx) { USER_PRINTLN("DMX: Error: no context in rdmPersonalityChangedCb"); return; } - if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) - { + if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) { const uint8_t personality = dmx_get_current_personality(dmx->inputPortNum); DMXMode = std::min(DMX_MODE_PRESET, std::max(DMX_MODE_SINGLE_RGB, int(personality))); doSerializeConfig = true; @@ -34,14 +32,12 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, { DMXInput *dmx = static_cast(context); - if (!dmx) - { + if (!dmx) { USER_PRINTLN("DMX: Error: no context in rdmAddressChangedCb"); return; } - if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) - { + if (header->cc == RDM_CC_SET_COMMAND_RESPONSE) { const uint16_t addr = dmx_get_start_address(dmx->inputPortNum); DMXAddress = std::min(512, int(addr)); doSerializeConfig = true; @@ -53,7 +49,7 @@ static dmx_config_t createConfig() { dmx_config_t config; config.pd_size = 255; - config.dmx_start_address = DMXAddress; // TODO split between input and output address + config.dmx_start_address = DMXAddress; config.model_id = 0; config.product_category = RDM_PRODUCT_CATEGORY_FIXTURE; config.software_version_id = VERSION; @@ -94,15 +90,12 @@ static dmx_config_t createConfig() void dmxReceiverTask(void *context) { DMXInput *instance = static_cast(context); - if (instance == nullptr) - { + if (instance == nullptr) { return; } - if (instance->installDriver()) - { - while (true) - { + if (instance->installDriver()) { + while (true) { instance->updateInternal(); } } @@ -112,8 +105,7 @@ bool DMXInput::installDriver() { const auto config = createConfig(); - if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) - { + if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { USER_PRINTF("Error: Failed to install dmx driver\n"); return false; } @@ -141,26 +133,22 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo // } #endif - if (inputPortNum < 3 && inputPortNum > 0) - { + if (inputPortNum < 3 && inputPortNum > 0) { this->inputPortNum = inputPortNum; } - else - { + else { USER_PRINTF("DMXInput: Error: invalid inputPortNum: %d\n", inputPortNum); return; } - if (rxPin > 0 && enPin > 0 && txPin > 0) - { + if (rxPin > 0 && enPin > 0 && txPin > 0) { const managed_pin_type pins[] = { {(int8_t)txPin, false}, // these are not used as gpio pins, thus isOutput is always false. {(int8_t)rxPin, false}, {(int8_t)enPin, false}}; const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); - if (!pinsAllocated) - { + if (!pinsAllocated) { USER_PRINTF("DMXInput: Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(rxPin).c_str()); USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(txPin).c_str()); @@ -175,13 +163,11 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo // put dmx receiver into seperate task because it should not be blocked // pin to core 0 because wled is running on core 1 xTaskCreatePinnedToCore(dmxReceiverTask, "DMX_RCV_TASK", 10240, this, 2, &task, 0); - if (!task) - { + if (!task) { USER_PRINTF("Error: Failed to create dmx rcv task"); } } - else - { + else { USER_PRINTLN("DMX input disabled due to rxPin, enPin or txPin not set"); return; } @@ -189,8 +175,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo void DMXInput::updateInternal() { - if (!initialized) - { + if (!initialized) { return; } @@ -198,25 +183,20 @@ void DMXInput::updateInternal() dmx_packet_t packet; unsigned long now = millis(); - if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) - { - if (!packet.err) - { + if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) { + if (!packet.err) { connected = true; identify = isIdentifyOn(); - if (!packet.is_rdm) - { + if (!packet.is_rdm) { const std::lock_guard lock(dmxDataLock); dmx_read(inputPortNum, dmxdata, packet.size); } } - else - { + else { connected = false; } } - else - { + else { connected = false; } } @@ -224,12 +204,10 @@ void DMXInput::updateInternal() void DMXInput::update() { - if (identify) - { + if (identify) { turnOnAllLeds(); } - else if (connected) - { + else if (connected) { const std::lock_guard lock(dmxDataLock); handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0); } @@ -249,15 +227,13 @@ void DMXInput::turnOnAllLeds() void DMXInput::disable() { - if (initialized) - { + if (initialized) { dmx_driver_disable(inputPortNum); } } void DMXInput::enable() { - if (initialized) - { + if (initialized) { dmx_driver_enable(inputPortNum); } } @@ -282,15 +258,13 @@ void DMXInput::checkAndUpdateConfig() */ const uint8_t currentPersonality = dmx_get_current_personality(inputPortNum); - if (currentPersonality != DMXMode) - { + if (currentPersonality != DMXMode) { DEBUG_PRINTF("DMX personality has changed from %d to %d\n", currentPersonality, DMXMode); dmx_set_current_personality(inputPortNum, DMXMode); } const uint16_t currentAddr = dmx_get_start_address(inputPortNum); - if (currentAddr != DMXAddress) - { + if (currentAddr != DMXAddress) { DEBUG_PRINTF("DMX address has changed from %d to %d\n", currentAddr, DMXAddress); dmx_set_start_address(inputPortNum, DMXAddress); } From d637524bfccdc1ed7b7d6b340225aab64667543d Mon Sep 17 00:00:00 2001 From: Arne Date: Sun, 22 Oct 2023 20:45:58 +0200 Subject: [PATCH 28/35] chore: remove outdated comments --- wled00/dmx_input.h | 2 +- wled00/dmx_output.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 7a6266c50e..0a02f2d113 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -56,7 +56,7 @@ class DMXInput uint8_t enPin = 255; /// is written to by the dmx receive task. - byte dmxdata[DMX_PACKET_SIZE]; //TODO add locking somehow? maybe double buffer? + byte dmxdata[DMX_PACKET_SIZE]; /// True once the dmx input has been initialized successfully bool initialized = false; // true once init finished successfully /// True if dmx is currently connected diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index 12095965e1..a868c78980 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -1,7 +1,7 @@ #include "wled.h" /* - * Support for DMX input and output via serial (e.g. MAX485). + * Support for DMX output via serial (e.g. MAX485). * Change the output pin in src/dependencies/ESPDMX.cpp, if needed (ESP8266) * Change the output pin in src/dependencies/SparkFunDMX.cpp, if needed (ESP32) * ESP8266 Library from: From 3996f02dea6d41b70251a814470ad1e0b428c5ed Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 16 Jan 2025 12:19:25 +0000 Subject: [PATCH 29/35] Revert "Rename WLED_ENABLE_DMX to WLED_ENABLE_DMX_OUTPUT" This reverts commit 7f9cc6751875dd4882f91bf58adcb820d76cab8c. --- tools/cdata.js | 2 +- wled00/cfg.cpp | 6 +++--- wled00/const.h | 7 ------- wled00/dmx_output.cpp | 2 +- wled00/e131.cpp | 2 +- wled00/set.cpp | 2 +- wled00/wled.cpp | 6 +++--- wled00/wled.h | 7 +++---- wled00/wled_eeprom.cpp | 4 ++-- wled00/wled_server.cpp | 10 +++++----- wled00/xml.cpp | 8 ++++---- 11 files changed, 24 insertions(+), 32 deletions(-) diff --git a/tools/cdata.js b/tools/cdata.js index b9f29694cc..c5d3c6aa52 100644 --- a/tools/cdata.js +++ b/tools/cdata.js @@ -358,7 +358,7 @@ writeChunks( method: "plaintext", filter: "html-minify", mangle: (str) => ` -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX ${str.replace(/function FM\(\)[ ]?\{/gms, "function FM() {%DMXVARS%\n")} #else const char PAGE_dmxmap[] PROGMEM = R"=====()====="; diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 4d8918db4d..d3a8a0c6d3 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -651,7 +651,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { getStringFromJson(otaPass, pwd, 33); //normally not present due to security } - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX JsonObject dmx = doc["dmx"]; CJSON(DMXChannels, dmx[F("chan")]); CJSON(DMXGap,dmx[F("gap")]); @@ -1116,8 +1116,8 @@ void serializeConfig() { ota[F("pskl")] = strlen(otaPass); ota[F("aota")] = aOtaEnabled; - #ifdef WLED_ENABLE_DMX_OUTPUT - JsonObject dmx = doc.createNestedObject("dmx"); + #ifdef WLED_ENABLE_DMX + JsonObject dmx = root.createNestedObject("dmx"); dmx[F("chan")] = DMXChannels; dmx[F("gap")] = DMXGap; dmx["start"] = DMXStart; diff --git a/wled00/const.h b/wled00/const.h index e0e4916d33..bdd20beba1 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -583,13 +583,6 @@ #define DEFAULT_LED_COUNT 30 #define INTERFACE_UPDATE_COOLDOWN 1000 // time in ms to wait between websockets, alexa, and MQTT updates -#ifdef WLED_ENABLE_DMX_OUTPUT -#if (LEDPIN == 2) - #undef LEDPIN - #define LEDPIN 1 - #warning "Pin conflict compiling with DMX and LEDs on pin 2. The default LED pin has been changed to pin 1." -#endif -#endif #define PIN_RETRY_COOLDOWN 3000 // time in ms after an incorrect attempt PIN and OTA pass will be rejected even if correct #define PIN_TIMEOUT 900000 // time in ms after which the PIN will be required again, 15 minutes diff --git a/wled00/dmx_output.cpp b/wled00/dmx_output.cpp index a868c78980..eace2145e6 100644 --- a/wled00/dmx_output.cpp +++ b/wled00/dmx_output.cpp @@ -10,7 +10,7 @@ * https://github.com/sparkfun/SparkFunDMX */ -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX void handleDMXOutput() { diff --git a/wled00/e131.cpp b/wled00/e131.cpp index 98ba5dfd95..bc26a0639e 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -93,7 +93,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ return; } - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX // does not act on out-of-order packets yet if (e131ProxyUniverse > 0 && uni == e131ProxyUniverse) { for (uint16_t i = 1; i <= dmxChannels; i++) diff --git a/wled00/set.cpp b/wled00/set.cpp index 7ffd806538..08a0180ad5 100644 --- a/wled00/set.cpp +++ b/wled00/set.cpp @@ -598,7 +598,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage) } } - #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled if (subPage == SUBPAGE_DMX) { int t = request->arg(F("PU")).toInt(); diff --git a/wled00/wled.cpp b/wled00/wled.cpp index 46d156e79f..564f3e8c29 100644 --- a/wled00/wled.cpp +++ b/wled00/wled.cpp @@ -64,7 +64,7 @@ void WLED::loop() handleImprovWifiScan(); handleNotifications(); handleTransitions(); - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX handleDMXOutput(); #endif #ifdef WLED_ENABLE_DMX_INPUT @@ -423,7 +423,7 @@ void WLED::setup() #if defined(WLED_DEBUG) && !defined(WLED_DEBUG_HOST) PinManager::allocatePin(hardwareTX, true, PinOwner::DebugOut); // TX (GPIO1 on ESP32) reserved for debug output #endif -#ifdef WLED_ENABLE_DMX_OUTPUT //reserve GPIO2 as hardcoded DMX pin +#ifdef WLED_ENABLE_DMX //reserve GPIO2 as hardcoded DMX pin PinManager::allocatePin(2, true, PinOwner::DMX); #endif @@ -526,7 +526,7 @@ void WLED::setup() ArduinoOTA.setHostname(cmDNS); } #endif -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX initDMXOutput(); #endif #ifdef WLED_ENABLE_DMX_INPUT diff --git a/wled00/wled.h b/wled00/wled.h index af4a0a84d6..b7f1ae710b 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -34,8 +34,7 @@ #else #undef WLED_ENABLE_ADALIGHT // disable has priority over enable #endif -//#define WLED_ENABLE_DMX_OUTPUT // uses 3.5kb (use LEDPIN other than 2) -//#define WLED_ENABLE_DMX_INPUT // Listen for DMX over Serial +//#define WLED_ENABLE_DMX // uses 3.5kb #ifndef WLED_DISABLE_LOXONE #define WLED_ENABLE_LOXONE // uses 1.2kb #endif @@ -137,7 +136,7 @@ #include "src/dependencies/espalexa/EspalexaDevice.h" #endif -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) #include "src/dependencies/dmx/ESPDMX.h" #else //ESP32 @@ -449,7 +448,7 @@ WLED_GLOBAL int arlsOffset _INIT(0); // realtime LE WLED_GLOBAL bool arlsDisableGammaCorrection _INIT(true); // activate if gamma correction is handled by the source WLED_GLOBAL bool arlsForceMaxBri _INIT(false); // enable to force max brightness if source has very dark colors that would be black -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX #if defined(ESP8266) || defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S2) WLED_GLOBAL DMXESPSerial dmx; #else //ESP32 diff --git a/wled00/wled_eeprom.cpp b/wled00/wled_eeprom.cpp index 99995debd5..8582b49df9 100644 --- a/wled00/wled_eeprom.cpp +++ b/wled00/wled_eeprom.cpp @@ -313,7 +313,7 @@ void loadSettingsFromEEPROM() e131Port = EEPROM.read(2187) + ((EEPROM.read(2188) << 8) & 0xFF00); } - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX if (lastEEPROMversion > 19) { e131ProxyUniverse = EEPROM.read(2185) + ((EEPROM.read(2186) << 8) & 0xFF00); @@ -342,7 +342,7 @@ void loadSettingsFromEEPROM() //custom macro memory (16 slots/ each 64byte) //1024-2047 reserved - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX // DMX (2530 - 2549)2535 DMXChannels = EEPROM.read(2530); DMXGap = EEPROM.read(2531) + ((EEPROM.read(2532) << 8) & 0xFF00); diff --git a/wled00/wled_server.cpp b/wled00/wled_server.cpp index 327cff2c33..e8cbb41ae5 100644 --- a/wled00/wled_server.cpp +++ b/wled00/wled_server.cpp @@ -96,7 +96,7 @@ static void handleStaticContent(AsyncWebServerRequest *request, const String &pa request->send(response); } -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX static String dmxProcessor(const String& var) { String mapJS; @@ -426,7 +426,7 @@ void initServer() #endif -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX server.on(F("/dmxmap"), HTTP_GET, [](AsyncWebServerRequest *request){ request->send_P(200, FPSTR(CONTENT_TYPE_HTML), PAGE_dmxmap , dmxProcessor); }); @@ -554,7 +554,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { else if (url.indexOf( "sync") > 0) subPage = SUBPAGE_SYNC; else if (url.indexOf( "time") > 0) subPage = SUBPAGE_TIME; else if (url.indexOf(F("sec")) > 0) subPage = SUBPAGE_SEC; -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX else if (url.indexOf( "dmx") > 0) subPage = SUBPAGE_DMX; #endif else if (url.indexOf( "um") > 0) subPage = SUBPAGE_UM; @@ -591,7 +591,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { case SUBPAGE_SYNC : strcpy_P(s, PSTR("Sync")); break; case SUBPAGE_TIME : strcpy_P(s, PSTR("Time")); break; case SUBPAGE_SEC : strcpy_P(s, PSTR("Security")); if (doReboot) strcpy_P(s2, PSTR("Rebooting, please wait ~10 seconds...")); break; -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX case SUBPAGE_DMX : strcpy_P(s, PSTR("DMX")); break; #endif case SUBPAGE_UM : strcpy_P(s, PSTR("Usermods")); break; @@ -626,7 +626,7 @@ void serveSettings(AsyncWebServerRequest* request, bool post) { case SUBPAGE_SYNC : content = PAGE_settings_sync; len = PAGE_settings_sync_length; break; case SUBPAGE_TIME : content = PAGE_settings_time; len = PAGE_settings_time_length; break; case SUBPAGE_SEC : content = PAGE_settings_sec; len = PAGE_settings_sec_length; break; -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX case SUBPAGE_DMX : content = PAGE_settings_dmx; len = PAGE_settings_dmx_length; break; #endif case SUBPAGE_UM : content = PAGE_settings_um; len = PAGE_settings_um_length; break; diff --git a/wled00/xml.cpp b/wled00/xml.cpp index b3ba4a0e81..aa49de0228 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -100,7 +100,7 @@ void appendGPIOinfo(Print& settingsScript) { firstPin = false; } } - #ifdef WLED_ENABLE_DMX_OUTPUT + #ifdef WLED_ENABLE_DMX if (!firstPin) settingsScript.print(','); settingsScript.print(2); // DMX hardcoded pin firstPin = false; @@ -164,7 +164,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) #ifdef WLED_DISABLE_2D // include only if 2D is not compiled in settingsScript.print(F("gId('2dbtn').style.display='none';")); #endif - #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled settingsScript.print(F("gId('dmxbtn').style.display='';")); #endif } @@ -436,7 +436,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) printSetFormCheckbox(settingsScript,PSTR("ES"),e131SkipOutOfSequence); printSetFormCheckbox(settingsScript,PSTR("EM"),e131Multicast); printSetFormValue(settingsScript,PSTR("EU"),e131Universe); -#ifdef WLED_ENABLE_DMX_OUTPUT +#ifdef WLED_ENABLE_DMX settingsScript.print(SET_F("hideNoDMX();")); // hide "not compiled in" message #endif #ifndef WLED_ENABLE_DMX_INPUT @@ -596,7 +596,7 @@ void getSettingsJS(byte subPage, Print& settingsScript) settingsScript.printf_P(PSTR("sd=\"%s\";"), serverDescription); } - #ifdef WLED_ENABLE_DMX_OUTPUT // include only if DMX is enabled + #ifdef WLED_ENABLE_DMX // include only if DMX is enabled if (subPage == SUBPAGE_DMX) { printSetFormValue(settingsScript,PSTR("PU"),e131ProxyUniverse); From ebfc438bd4f7a18918de2a8b07fd467ab1a1d82d Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Tue, 16 Jan 2024 20:13:52 +0000 Subject: [PATCH 30/35] Tweak DMX settings UI --- wled00/data/settings_sync.htm | 8 ++++---- wled00/dmx_input.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 8e142dc9be..5502884886 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -152,10 +152,10 @@

Realtime

Disable realtime gamma correction:
Realtime LED offset:
- DMX Input Pins
- DMX RX:
- DMX TX:
- DMX Enable:
+

Wired DMX Input Pins

+ DMX RX: RO
+ DMX TX: DI
+ DMX Enable: RE+DE
DMX Port:
diff --git a/wled00/dmx_input.h b/wled00/dmx_input.h index 0a02f2d113..7845778d78 100644 --- a/wled00/dmx_input.h +++ b/wled00/dmx_input.h @@ -7,7 +7,7 @@ /* * Support for DMX/RDM input via serial (e.g. max485) on ESP32 * ESP32 Library from: - * https://github.com/sparkfun/SparkFunDMX + * https://github.com/someweisguy/esp_dmx */ class DMXInput { From a56014bb668d4871f997971d571be330b6f39952 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Wed, 17 Jan 2024 18:03:16 +0000 Subject: [PATCH 31/35] Hide DMX port as just confusing to users --- wled00/data/settings_sync.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 5502884886..fabb2d5dd4 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -156,7 +156,7 @@

Wired DMX Input Pins

DMX RX: RO
DMX TX: DI
DMX Enable: RE+DE
- DMX Port:
+
DMX Port:

This firmware build does not include DMX Input support.
From fc4e7a2deeb5e4db10ee3e05f113131bf19d7d73 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 7 Mar 2024 10:44:07 +0000 Subject: [PATCH 32/35] Swap DMX port to 1, persist user choice of port, validate port vs UART count --- wled00/cfg.cpp | 2 ++ wled00/data/settings_sync.htm | 2 +- wled00/dmx_input.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index d3a8a0c6d3..443f16c73b 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -527,6 +527,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(dmxInputTransmitPin, if_live_dmx[F("inputRxPin")]); CJSON(dmxInputReceivePin, if_live_dmx[F("inputTxPin")]); CJSON(dmxInputEnablePin, if_live_dmx[F("inputEnablePin")]); + CJSON(dmxInputPort, if_live_dmx[F("dmxInputPort")]); #endif CJSON(arlsForceMaxBri, if_live[F("maxbri")]); @@ -1012,6 +1013,7 @@ void serializeConfig() { if_live_dmx[F("inputRxPin")] = dmxInputTransmitPin; if_live_dmx[F("inputTxPin")] = dmxInputReceivePin; if_live_dmx[F("inputEnablePin")] = dmxInputEnablePin; + if_live_dmx[F("dmxInputPort")] = dmxInputPort; #endif if_live[F("timeout")] = realtimeTimeoutMs / 100; diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index fabb2d5dd4..5502884886 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -156,7 +156,7 @@

Wired DMX Input Pins

DMX RX: RO
DMX TX: DI
DMX Enable: RE+DE
-
DMX Port:
+ DMX Port:

This firmware build does not include DMX Input support.
diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index af0bb679dc..facafe17c5 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -105,6 +105,7 @@ bool DMXInput::installDriver() { const auto config = createConfig(); + USER_PRINTF("DMX port: %u\n", inputPortNum); if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { USER_PRINTF("Error: Failed to install dmx driver\n"); return false; @@ -133,7 +134,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo // } #endif - if (inputPortNum < 3 && inputPortNum > 0) { + if (inputPortNum <= (SOC_UART_NUM - 1) && inputPortNum > 0) { this->inputPortNum = inputPortNum; } else { From 9a6e91d3e5039f252b347c314a2a69526c8cc34a Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Tue, 30 Jul 2024 19:15:08 +0100 Subject: [PATCH 33/35] DMX Input - reinstate loggers for connection state change --- wled00/dmx_input.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index facafe17c5..ffdea63216 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -186,6 +186,9 @@ void DMXInput::updateInternal() unsigned long now = millis(); if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) { if (!packet.err) { + if(!connected) { + USER_PRINTLN("DMX Input - connected"); + } connected = true; identify = isIdentifyOn(); if (!packet.is_rdm) { @@ -198,6 +201,9 @@ void DMXInput::updateInternal() } } else { + if(connected) { + USER_PRINTLN("DMX Input - disconnected"); + } connected = false; } } From 953e994c88abf5e6b62f5026730635c96a0d8278 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 16 Jan 2025 12:24:42 +0000 Subject: [PATCH 34/35] Add DMX Input support to builds --- platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platformio.ini b/platformio.ini index 9b9b693f54..18a2db8aa8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -282,8 +282,10 @@ build_flags = -g -DARDUINO_ARCH_ESP32 -DESP32 -D CONFIG_ASYNC_TCP_USE_WDT=0 -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when building with arduino-esp32 >=2.0.3 + -D WLED_ENABLE_DMX_INPUT lib_deps = https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 + https://github.com/someweisguy/esp_dmx.git#47db25d ${env.lib_deps} board_build.partitions = ${esp32.default_partitions} ;; default partioning for 4MB Flash - can be overridden in build envs From a58278665568eff509df0b721bc8ce23cc04e412 Mon Sep 17 00:00:00 2001 From: Will Tatam Date: Thu, 16 Jan 2025 12:48:36 +0000 Subject: [PATCH 35/35] Port over remaining WLEDMM part of DMX Input and adapt for AC --- wled00/const.h | 1 + wled00/data/settings_sync.htm | 6 +++--- wled00/dmx_input.cpp | 40 +++++++++++++++++------------------ wled00/e131.cpp | 11 +++++++--- wled00/fcn_declare.h | 1 + wled00/xml.cpp | 10 ++++----- 6 files changed, 38 insertions(+), 31 deletions(-) diff --git a/wled00/const.h b/wled00/const.h index bdd20beba1..b5eb20f814 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -249,6 +249,7 @@ #define REALTIME_MODE_ARTNET 6 #define REALTIME_MODE_TPM2NET 7 #define REALTIME_MODE_DDP 8 +#define REALTIME_MODE_DMX 9 //realtime override modes #define REALTIME_OVERRIDE_NONE 0 diff --git a/wled00/data/settings_sync.htm b/wled00/data/settings_sync.htm index 5502884886..775f87a964 100644 --- a/wled00/data/settings_sync.htm +++ b/wled00/data/settings_sync.htm @@ -151,17 +151,17 @@

Realtime

Force max brightness:
Disable realtime gamma correction:
Realtime LED offset: -
+

Wired DMX Input Pins

DMX RX: RO
DMX TX: DI
DMX Enable: RE+DE
DMX Port:
-
+

This firmware build does not include DMX Input support.
-
+

This firmware build does not include DMX output support.

diff --git a/wled00/dmx_input.cpp b/wled00/dmx_input.cpp index ffdea63216..afbc9f0d0b 100644 --- a/wled00/dmx_input.cpp +++ b/wled00/dmx_input.cpp @@ -15,7 +15,7 @@ void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, DMXInput *dmx = static_cast(context); if (!dmx) { - USER_PRINTLN("DMX: Error: no context in rdmPersonalityChangedCb"); + DEBUG_PRINTLN("DMX: Error: no context in rdmPersonalityChangedCb"); return; } @@ -23,7 +23,7 @@ void rdmPersonalityChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, const uint8_t personality = dmx_get_current_personality(dmx->inputPortNum); DMXMode = std::min(DMX_MODE_PRESET, std::max(DMX_MODE_SINGLE_RGB, int(personality))); doSerializeConfig = true; - USER_PRINTF("DMX personality changed to to: %d\n", DMXMode); + DEBUG_PRINTF("DMX personality changed to to: %d\n", DMXMode); } } @@ -33,7 +33,7 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, DMXInput *dmx = static_cast(context); if (!dmx) { - USER_PRINTLN("DMX: Error: no context in rdmAddressChangedCb"); + DEBUG_PRINTLN("DMX: Error: no context in rdmAddressChangedCb"); return; } @@ -41,7 +41,7 @@ void rdmAddressChangedCb(dmx_port_t dmxPort, const rdm_header_t *header, const uint16_t addr = dmx_get_start_address(dmx->inputPortNum); DMXAddress = std::min(512, int(addr)); doSerializeConfig = true; - USER_PRINTF("DMX start addr changed to: %d\n", DMXAddress); + DEBUG_PRINTF("DMX start addr changed to: %d\n", DMXAddress); } } @@ -105,15 +105,15 @@ bool DMXInput::installDriver() { const auto config = createConfig(); - USER_PRINTF("DMX port: %u\n", inputPortNum); + DEBUG_PRINTF("DMX port: %u\n", inputPortNum); if (!dmx_driver_install(inputPortNum, &config, DMX_INTR_FLAGS_DEFAULT)) { - USER_PRINTF("Error: Failed to install dmx driver\n"); + DEBUG_PRINTF("Error: Failed to install dmx driver\n"); return false; } - USER_PRINTF("Listening for DMX on pin %u\n", rxPin); - USER_PRINTF("Sending DMX on pin %u\n", txPin); - USER_PRINTF("DMX enable pin is: %u\n", enPin); + DEBUG_PRINTF("Listening for DMX on pin %u\n", rxPin); + DEBUG_PRINTF("Sending DMX on pin %u\n", txPin); + DEBUG_PRINTF("DMX enable pin is: %u\n", enPin); dmx_set_pin(inputPortNum, txPin, rxPin, enPin); rdm_register_dmx_start_address(inputPortNum, rdmAddressChangedCb, this); @@ -129,7 +129,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo //TODO add again once dmx output has been merged // if(inputPortNum == dmxOutputPort) // { - // USER_PRINTF("DMXInput: Error: Input port == output port"); + // DEBUG_PRINTF("DMXInput: Error: Input port == output port"); // return; // } #endif @@ -138,7 +138,7 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo this->inputPortNum = inputPortNum; } else { - USER_PRINTF("DMXInput: Error: invalid inputPortNum: %d\n", inputPortNum); + DEBUG_PRINTF("DMXInput: Error: invalid inputPortNum: %d\n", inputPortNum); return; } @@ -148,12 +148,12 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo {(int8_t)txPin, false}, // these are not used as gpio pins, thus isOutput is always false. {(int8_t)rxPin, false}, {(int8_t)enPin, false}}; - const bool pinsAllocated = pinManager.allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); + const bool pinsAllocated = PinManager::allocateMultiplePins(pins, 3, PinOwner::DMX_INPUT); if (!pinsAllocated) { - USER_PRINTF("DMXInput: Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); - USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(rxPin).c_str()); - USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(txPin).c_str()); - USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(enPin).c_str()); + DEBUG_PRINTF("DMXInput: Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); + DEBUG_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(rxPin).c_str()); + DEBUG_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(txPin).c_str()); + DEBUG_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(enPin).c_str()); return; } @@ -165,11 +165,11 @@ void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPo // pin to core 0 because wled is running on core 1 xTaskCreatePinnedToCore(dmxReceiverTask, "DMX_RCV_TASK", 10240, this, 2, &task, 0); if (!task) { - USER_PRINTF("Error: Failed to create dmx rcv task"); + DEBUG_PRINTF("Error: Failed to create dmx rcv task"); } } else { - USER_PRINTLN("DMX input disabled due to rxPin, enPin or txPin not set"); + DEBUG_PRINTLN("DMX input disabled due to rxPin, enPin or txPin not set"); return; } } @@ -187,7 +187,7 @@ void DMXInput::updateInternal() if (dmx_receive(inputPortNum, &packet, DMX_TIMEOUT_TICK)) { if (!packet.err) { if(!connected) { - USER_PRINTLN("DMX Input - connected"); + DEBUG_PRINTLN("DMX Input - connected"); } connected = true; identify = isIdentifyOn(); @@ -202,7 +202,7 @@ void DMXInput::updateInternal() } else { if(connected) { - USER_PRINTLN("DMX Input - disconnected"); + DEBUG_PRINTLN("DMX Input - disconnected"); } connected = false; } diff --git a/wled00/e131.cpp b/wled00/e131.cpp index bc26a0639e..c16ed9332e 100644 --- a/wled00/e131.cpp +++ b/wled00/e131.cpp @@ -116,6 +116,11 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ // update status info realtimeIP = clientIP; + + handleDMXData(uni, dmxChannels, e131_data, mde, previousUniverses); +} + +void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8_t mde, uint8_t previousUniverses) { byte wChannel = 0; unsigned totalLen = strip.getLengthTotal(); unsigned availDMXLen = 0; @@ -130,7 +135,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ } // DMX data in Art-Net packet starts at index 0, for E1.31 at index 1 - if (protocol == P_ARTNET && dataOffset > 0) { + if (mde == REALTIME_MODE_ARTNET && dataOffset > 0) { dataOffset--; } @@ -211,7 +216,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ else dataOffset = DMXAddress; // Modify address for Art-Net data - if (protocol == P_ARTNET && dataOffset > 0) + if (mde == REALTIME_MODE_ARTNET && dataOffset > 0) dataOffset--; // Skip out of universe addresses if (dataOffset > dmxChannels - dmxEffectChannels + 1) @@ -285,7 +290,7 @@ void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol){ } } else { // All subsequent universes start at the first channel. - dmxOffset = (protocol == P_ARTNET) ? 0 : 1; + dmxOffset = (mde == REALTIME_MODE_ARTNET) ? 0 : 1; const unsigned dimmerOffset = (DMXMode == DMX_MODE_MULTIPLE_DRGB) ? 1 : 0; unsigned ledsInFirstUniverse = (((MAX_CHANNELS_PER_UNIVERSE - DMXAddress) + dmxLenOffset) - dimmerOffset) / dmxChannelsPerLed; previousLeds = ledsInFirstUniverse + (previousUniverses - 1) * ledsPerUniverse; diff --git a/wled00/fcn_declare.h b/wled00/fcn_declare.h index db6c6b872a..c7fa9daaea 100644 --- a/wled00/fcn_declare.h +++ b/wled00/fcn_declare.h @@ -193,6 +193,7 @@ void handleDMXInput(); //e131.cpp void handleE131Packet(e131_packet_t* p, IPAddress clientIP, byte protocol); +void handleDMXData(uint16_t uni, uint16_t dmxChannels, uint8_t* e131_data, uint8_t mde, uint8_t previousUniverses); void handleArtnetPollReply(IPAddress ipAddress); void prepareArtnetPollReply(ArtPollReply* reply); void sendArtnetPollReply(ArtPollReply* reply, IPAddress ipAddress, uint16_t portAddress); diff --git a/wled00/xml.cpp b/wled00/xml.cpp index aa49de0228..0ed32c04b9 100644 --- a/wled00/xml.cpp +++ b/wled00/xml.cpp @@ -442,11 +442,11 @@ void getSettingsJS(byte subPage, Print& settingsScript) #ifndef WLED_ENABLE_DMX_INPUT settingsScript.print(SET_F("hideDMXInput();")); // hide "dmx input" settings #else - settingsScript.print(SET_F("hideNoDMXInput();")); //hide "not comp iled in" message - sappend('v',SET_F("IDMT"),dmxInputTransmitPin); - sappend('v',SET_F("IDMR"),dmxInputReceivePin); - sappend('v',SET_F("IDME"),dmxInputEnablePin); - sappend('v',SET_F("IDMP"),dmxInputPort); + settingsScript.print(SET_F("hideNoDMXInput();")); //hide "not compiled in" message + printSetFormValue(settingsScript,SET_F("IDMT"),dmxInputTransmitPin); + printSetFormValue(settingsScript,SET_F("IDMR"),dmxInputReceivePin); + printSetFormValue(settingsScript,SET_F("IDME"),dmxInputEnablePin); + printSetFormValue(settingsScript,SET_F("IDMP"),dmxInputPort); #endif printSetFormValue(settingsScript,PSTR("DA"),DMXAddress); printSetFormValue(settingsScript,PSTR("XX"),DMXSegmentSpacing);