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.
This commit is contained in:
Arne 2023-08-14 15:18:54 +02:00 committed by Will Tatam
parent 0ad31c90f6
commit a3bcf92ea5
4 changed files with 111 additions and 70 deletions

View File

@ -1,19 +1,25 @@
#include "wled.h" #include "wled.h"
#ifdef WLED_ENABLE_DMX_INPUT #ifdef WLED_ENABLE_DMX_INPUT
#include "dmx_input.h"
#include <esp_dmx.h> #include <esp_dmx.h>
/*
* 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 #ifdef ESP8266
static bool dmxInputInitialized = false; //true once initDmx finished successfully #error DMX input is only supported on ESP32
static bool dmxIsConnected = false; #endif
static unsigned long dmxLastUpdate = 0;
void initDMXInput() { void DMXInput::init(uint8_t rxPin, uint8_t txPin, uint8_t enPin, uint8_t inputPortNum)
{
if (inputPortNum < 3 && inputPortNum > 0)
{
this->inputPortNum = inputPortNum;
}
else
{
USER_PRINTF("DMXInput: Error: invalid inputPortNum: %d\n", inputPortNum);
return;
}
/** /**
* TODOS: * TODOS:
@ -23,24 +29,22 @@ void initDMXInput() {
* - attach callback for address change and store in flash * - attach callback for address change and store in flash
* - load dmx address from flash and set in config on startup * - load dmx address from flash and set in config on startup
* - attach callback to rdm identify and flash leds when on * - attach callback to rdm identify and flash leds when on
* - Turn this into a class
* - Make all important config variables available via rdm * - Make all important config variables available via rdm
*/ */
if(dmxInputReceivePin > 0 && dmxInputEnablePin > 0 && dmxInputTransmitPin > 0) if (rxPin > 0 && enPin > 0 && txPin > 0)
{ {
const managed_pin_type pins[] = { const managed_pin_type pins[] = {
{(int8_t)dmxInputTransmitPin, false}, //these are not used as gpio pins, this isOutput is always false. {(int8_t)txPin, false}, // these are not used as gpio pins, this isOutput is always false.
{(int8_t)dmxInputReceivePin, false}, {(int8_t)rxPin, false},
{(int8_t)dmxInputEnablePin, 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) if (!pinsAllocated)
{ {
USER_PRINTF("Error: Failed to allocate pins for DMX_INPUT. Pins already in use:\n"); 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(dmxInputReceivePin).c_str()); USER_PRINTF("rx in use by: %s\n", pinManager.getPinOwnerText(rxPin).c_str());
USER_PRINTF("tx in use by: %s\n", pinManager.getPinOwnerText(dmxInputTransmitPin).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(dmxInputEnablePin).c_str()); USER_PRINTF("en in use by: %s\n", pinManager.getPinOwnerText(enPin).c_str());
return; return;
} }
@ -59,60 +63,65 @@ void initDMXInput() {
strncpy(config.software_version_label, versionString.c_str(), 32); 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"); USER_PRINTF("Error: Failed to install dmx driver\n");
return; return;
} }
USER_PRINTF("Listening for DMX on pin %u\n", dmxInputReceivePin); USER_PRINTF("Listening for DMX on pin %u\n", rxPin);
USER_PRINTF("Sending DMX on pin %u\n", dmxInputTransmitPin); USER_PRINTF("Sending DMX on pin %u\n", txPin);
USER_PRINTF("DMX enable pin is: %u\n", dmxInputEnablePin); USER_PRINTF("DMX enable pin is: %u\n", enPin);
dmx_set_pin(dmxInputPort, dmxInputTransmitPin, dmxInputReceivePin, dmxInputEnablePin); dmx_set_pin(inputPortNum, txPin, rxPin, enPin);
dmxInputInitialized = true; 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; return;
} }
} }
void handleDMXInput() { void DMXInput::update()
if(!dmxInputInitialized) { {
if (!initialized)
{
return; return;
} }
byte dmxdata[DMX_PACKET_SIZE]; byte dmxdata[DMX_PACKET_SIZE];
dmx_packet_t packet; dmx_packet_t packet;
unsigned long now = millis(); unsigned long now = millis();
if (dmx_receive(dmxInputPort, &packet, 0)) { if (dmx_receive(inputPortNum, &packet, 0))
if (!packet.err) { {
if (!dmxIsConnected) { if (!packet.err)
{
if (!connected)
{
USER_PRINTLN("DMX is 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); handleDMXData(1, 512, dmxdata, REALTIME_MODE_DMX, 0);
dmxLastUpdate = now; lastUpdate = now;
}
} else { else
{
/*This can happen when you first connect or disconnect your DMX devices. /*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. */ If you are consistently getting DMX errors, then something may have gone wrong. */
DEBUG_PRINT("A DMX error occurred - "); DEBUG_PRINT("A DMX error occurred - ");
DEBUG_PRINTLN(packet.err); // TODO translate err code to string for output DEBUG_PRINTLN(packet.err); // TODO translate err code to string for output
} }
} }
else if (dmxIsConnected && (now - dmxLastUpdate > 5000)) { else if (connected && (now - lastUpdate > 5000))
dmxIsConnected = false; {
connected = false;
USER_PRINTLN("DMX was disconnected."); USER_PRINTLN("DMX was disconnected.");
} }
} }
#else #else
void initDMXInput(){} void DMXInput::init(uint8_t, uint8_t, uint8_t, uint8_t) {}
void handleDMXInput(){} void DMXInput::update() {}
#endif #endif

23
wled00/dmx_input.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <cstdint>
/*
* 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;
};

View File

@ -67,6 +67,9 @@ void WLED::loop()
#ifdef WLED_ENABLE_DMX #ifdef WLED_ENABLE_DMX
handleDMX(); handleDMX();
#endif #endif
#ifdef WLED_ENABLE_DMX_INPUT
dmxInput.update();
#endif
#ifdef WLED_DEBUG #ifdef WLED_DEBUG
unsigned long usermodMillis = millis(); unsigned long usermodMillis = millis();
@ -527,7 +530,8 @@ void WLED::setup()
initDMX(); initDMX();
#endif #endif
#ifdef WLED_ENABLE_DMX_INPUT #ifdef WLED_ENABLE_DMX_INPUT
initDMXInput(); const uint8_t dmxInputPortNumber = 2; //TODO turn into config variable?!
dmxInput.init(dmxInputReceivePin, dmxInputTransmitPin, dmxInputEnablePin, dmxInputPortNumber);
#endif #endif
#ifdef WLED_ENABLE_ADALIGHT #ifdef WLED_ENABLE_ADALIGHT

View File

@ -144,6 +144,10 @@
#endif #endif
#endif #endif
#ifdef WLED_ENABLE_DMX_INPUT
#include "dmx_input.h"
#endif
#include "src/dependencies/e131/ESPAsyncE131.h" #include "src/dependencies/e131/ESPAsyncE131.h"
#ifndef WLED_DISABLE_MQTT #ifndef WLED_DISABLE_MQTT
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h" #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 dmxInputTransmitPin _INIT(0);
WLED_GLOBAL int dmxInputReceivePin _INIT(0); WLED_GLOBAL int dmxInputReceivePin _INIT(0);
WLED_GLOBAL int dmxInputEnablePin _INIT(0); WLED_GLOBAL int dmxInputEnablePin _INIT(0);
WLED_GLOBAL DMXInput dmxInput;
#endif #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 e131Universe _INIT(1); // settings for E1.31 (sACN) protocol (only DMX_MODE_MULTIPLE_* can span over consequtive universes)