diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index 38e804ed9..1105077ca 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 dbe70f2aa..305d5130d 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 160eb48f0..9a12cdc21 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 1f978a39b..8144b0cd4 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 533b12063..8adbd1ba5 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 2a19cdfab..62de53425 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);