diff --git a/usermods/seven_segment_display_reloaded/readme.md b/usermods/seven_segment_display_reloaded/readme.md new file mode 100644 index 000000000..09479754c --- /dev/null +++ b/usermods/seven_segment_display_reloaded/readme.md @@ -0,0 +1,129 @@ +# Seven Segment Display Reloaded + +Usermod that uses the overlay feature to create a configurable seven segment display. +Optimized for maximum configurability and use with seven segment clocks by parallyze (https://www.instructables.com/member/parallyze/instructables/) +Very loosely based on the existing usermod "seven segment display". + + +## Installation + +Add the compile-time option `-D USERMOD_SSDR` to your `platformio.ini` (or `platformio_override.ini`) or use `#define USERMOD_SSDR` in `my_config.h`. + +For the auto brightness option, the usermod SN_Photoresistor has to be installed as well. See SN_Photoresistor/readme.md for instructions. + +## Settings +All settings can be controlled the usermod setting page. +Part of the settings can be controlled through MQTT with a raw payload or through a json request to /json/state. + +### enabled +Enables/disables this overlay usermod + +### inverted +Enables the inverted mode in which the background should be enabled and the digits should be black (leds off) + +### Colon-blinking +Enables the blinking colon(s) if they are defined + +### enable-auto-brightness +Enables the auto brightness feature. Can be only used with the usermod SN_Photoresistor installed. + +### auto-brightness-min / auto-brightness-max +The lux value calculated from usermod SN_Photoresistor will be mapped to the values defined here. +The mapping is 0 - 1000 lux will be mapped to auto-brightness-min - auto-brightness-max + +The mA current protection of WLED will override the calculated value if it is too high. + +### Display-Mask +Defines the type of the time/date display. +For example "H:m" (default) +- H - 00-23 hours +- h - 01-12 hours +- k - 01-24 hours +- m - 00-59 minutes +- s - 00-59 seconds +- d - 01-31 day of month +- M - 01-12 month +- y - 21 last two positions of year +- Y - 2021 year +- : for a colon + +### LED-Numbers +- LED-Numbers-Hours +- LED-Numbers-Minutes +- LED-Numbers-Seconds +- LED-Numbers-Colons +- LED-Numbers-Day +- LED-Numbers-Month +- LED-Numbers-Year + +See following example for usage. + + +## Example + +Example for Leds definition +``` + < A > +/\ /\ +F B +\/ \/ + < G > +/\ /\ +E C +\/ \/ + < D > +``` + +Leds or Range of Leds are seperated by a comma "," + +Segments are seperated by a semicolon ";" and are read as A;B;C;D;E;F;G + +Digits are seperated by colon ":" -> A;B;C;D;E;F;G:A;B;C;D;E;F;G + +Ranges are defined as lower to higher (lower first) + +For example, an clock definition for the following clock (https://www.instructables.com/Lazy-7-Quick-Build-Edition/) is + +- hour "59,46;47-48;50-51;52-53;54-55;57-58;49,56:0,13;1-2;4-5;6-7;8-9;11-12;3,10" + +- minute "37-38;39-40;42-43;44,31;32-33;35-36;34,41:21-22;23-24;26-27;28,15;16-17;19-20;18,25" + +or + +- hour "6,7;8,9;11,12;13,0;1,2;4,5;3,10:52,53;54,55;57,58;59,46;47,48;50,51;49,56" + +- minute "15,28;16,17;19,20;21,22;23,24;26,27;18,25:31,44;32,33;35,36;37,38;39,40;42,43;34,41" + +depending on the orientation. + +# The example detailed: +hour "59,46;47-48;50-51;52-53;54-55;57-58;49,56:0,13;1-2;4-5;6-7;8-9;11-12;3,10" + +there are two digits seperated by ":" + +- 59,46;47-48;50-51;52-53;54-55;57-58;49,56 +- 0,13;1-2;4-5;6-7;8-9;11-12;3,10 + +In the first digit, +the **segment A** consists of the leds number **59 and 46**., **segment B** consists of the leds number **47, 48** and so on + +The second digit starts again with **segment A** and leds **0 and 13**, **segment B** consists of the leds number **1 and 2** and so on + +### first digit of the hour +- Segment A: 59, 46 +- Segment B: 47, 48 +- Segment C: 50, 51 +- Segment D: 52, 53 +- Segment E: 54, 55 +- Segment F: 57, 58 +- Segment G: 49, 56 + +### second digit of the hour + +- Segment A: 0, 13 +- Segment B: 1, 2 +- Segment C: 4, 5 +- Segment D: 6, 7 +- Segment E: 8, 9 +- Segment F: 11, 12 +- Segment G: 3, 10 \ No newline at end of file diff --git a/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h new file mode 100644 index 000000000..c4a648868 --- /dev/null +++ b/usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h @@ -0,0 +1,544 @@ +#pragma once + +#include "wled.h" + +class UsermodSSDR : public Usermod { + +//#define REFRESHTIME 497 + +private: + //Runtime variables. + unsigned long umSSDRLastRefresh = 0; + unsigned long umSSDRResfreshTime = 3000; + bool umSSDRDisplayTime = false; + bool umSSDRInverted = false; + bool umSSDRColonblink = true; + bool umSSDREnableLDR = false; + String umSSDRHours = ""; + String umSSDRMinutes = ""; + String umSSDRSeconds = ""; + String umSSDRColons = ""; + String umSSDRDays = ""; + String umSSDRMonths = ""; + String umSSDRYears = ""; + uint16_t umSSDRLength = 0; + uint16_t umSSDRBrightnessMin = 0; + uint16_t umSSDRBrightnessMax = 255; + + bool* umSSDRMask = 0; + + /*// H - 00-23 hours + // h - 01-12 hours + // k - 01-24 hours + // m - 00-59 minutes + // s - 00-59 seconds + // d - 01-31 day of month + // M - 01-12 month + // y - 21 last two positions of year + // Y - 2021 year + // : for a colon + */ + String umSSDRDisplayMask = "H:m"; //This should reflect physical equipment. + + /* Segment order, seen from the front: + + < A > + /\ /\ + F B + \/ \/ + < G > + /\ /\ + E C + \/ \/ + < D > + + */ + + uint8_t umSSDRNumbers[11][7] = { + // A B C D E F G + { 1, 1, 1, 1, 1, 1, 0 }, // 0 + { 0, 1, 1, 0, 0, 0, 0 }, // 1 + { 1, 1, 0, 1, 1, 0, 1 }, // 2 + { 1, 1, 1, 1, 0, 0, 1 }, // 3 + { 0, 1, 1, 0, 0, 1, 1 }, // 4 + { 1, 0, 1, 1, 0, 1, 1 }, // 5 + { 1, 0, 1, 1, 1, 1, 1 }, // 6 + { 1, 1, 1, 0, 0, 0, 0 }, // 7 + { 1, 1, 1, 1, 1, 1, 1 }, // 8 + { 1, 1, 1, 1, 0, 1, 1 } // 9 + }; + + //String to reduce flash memory usage + static const char _str_name[]; + static const char _str_ldrEnabled[]; + static const char _str_timeEnabled[]; + static const char _str_inverted[]; + static const char _str_colonblink[]; + static const char _str_displayMask[]; + static const char _str_hours[]; + static const char _str_minutes[]; + static const char _str_seconds[]; + static const char _str_colons[]; + static const char _str_days[]; + static const char _str_months[]; + static const char _str_years[]; + static const char _str_minBrightness[]; + static const char _str_maxBrightness[]; + +#ifdef USERMOD_ID_SN_PHOTORESISTOR + Usermod_SN_Photoresistor *ptr; +#else + void* ptr = nullptr; +#endif + + void _overlaySevenSegmentDraw() { + int displayMaskLen = static_cast(umSSDRDisplayMask.length()); + bool colonsDone = false; + _setAllFalse(); + for (int index = 0; index < displayMaskLen; index++) { + int timeVar = 0; + switch (umSSDRDisplayMask[index]) { + case 'h': + timeVar = hourFormat12(localTime); + _showElements(&umSSDRHours, timeVar, 0); + break; + case 'H': + timeVar = hour(localTime); + _showElements(&umSSDRHours, timeVar, 0); + break; + case 'k': + timeVar = hour(localTime) + 1; + _showElements(&umSSDRHours, timeVar, 0); + break; + case 'm': + timeVar = minute(localTime); + _showElements(&umSSDRMinutes, timeVar, 0); + break; + case 's': + timeVar = second(localTime); + _showElements(&umSSDRSeconds, timeVar, 0); + break; + case 'd': + timeVar = day(localTime); + _showElements(&umSSDRDays, timeVar, 0); + break; + case 'M': + timeVar = month(localTime); + _showElements(&umSSDRMonths, timeVar, 0); + break; + case 'y': + timeVar = second(localTime); + _showElements(&umSSDRYears, timeVar, 0); + break; + case 'Y': + timeVar = year(localTime); + _showElements(&umSSDRYears, timeVar, 0); + break; + case ':': + if (!colonsDone) { // only call _setColons once as all colons are printed when the first colon is found + _setColons(); + colonsDone = true; + } + break; + } + } + _setMaskToLeds(); + } + + void _setColons() { + if ( umSSDRColonblink ) { + if ( second(localTime) % 2 == 0 ) { + _showElements(&umSSDRColons, 0, 1); + } + } else { + _showElements(&umSSDRColons, 0, 1); + } + } + + void _showElements(String *map, int timevar, bool isColon) { + if (!(*map).equals("") && !(*map) == NULL) { + int length = String(timevar).length(); + bool addZero = false; + if (length == 1) { + length = 2; + addZero = true; + } + int timeArr[length]; + if(addZero) { + timeArr[1] = 0; + timeArr[0] = timevar; + } else { + int count = 0; + while (timevar) { + timeArr[count] = timevar%10; + timevar /= 10; + count++; + }; + } + + + int colonsLen = static_cast((*map).length()); + int count = 0; + int countSegments = 0; + int countDigit = 0; + bool range = false; + int lastSeenLedNr = 0; + + for (int index = 0; index < colonsLen; index++) { + switch ((*map)[index]) { + case '-': + lastSeenLedNr = _checkForNumber(count, index, map); + count = 0; + range = true; + break; + case ':': + _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); + count = 0; + range = false; + countDigit++; + countSegments = 0; + break; + case ';': + _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); + count = 0; + range = false; + countSegments++; + break; + case ',': + _setLeds(_checkForNumber(count, index, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); + count = 0; + range = false; + break; + default: + count++; + break; + } + } + _setLeds(_checkForNumber(count, colonsLen, map), lastSeenLedNr, range, countSegments, timeArr[countDigit], isColon); + } + } + + void _setLeds(int lednr, int lastSeenLedNr, bool range, int countSegments, int number, bool colon) { + + if ((colon && umSSDRColonblink) || umSSDRNumbers[number][countSegments]) { + + if (range) { + for(int i = lastSeenLedNr; i <= lednr; i++) { + umSSDRMask[i] = true; + } + } else { + umSSDRMask[lednr] = true; + } + } + } + + void _setMaskToLeds() { + for(int i = 0; i <= umSSDRLength; i++) { + if ((!umSSDRInverted && !umSSDRMask[i]) || (umSSDRInverted && umSSDRMask[i])) { + strip.setPixelColor(i, 0x000000); + } + } + } + + void _setAllFalse() { + for(int i = 0; i <= umSSDRLength; i++) { + umSSDRMask[i] = false; + } + } + + int _checkForNumber(int count, int index, String *map) { + String number = (*map).substring(index - count, index); + return number.toInt(); + } + + void _publishMQTTint_P(const char *subTopic, int value) + { + if(mqtt == NULL) return; + + char buffer[64]; + char valBuffer[12]; + sprintf_P(buffer, PSTR("%s/%S/%S"), mqttDeviceTopic, _str_name, subTopic); + sprintf_P(valBuffer, PSTR("%d"), value); + mqtt->publish(buffer, 2, true, valBuffer); + } + + void _publishMQTTstr_P(const char *subTopic, String Value) + { + if(mqtt == NULL) return; + char buffer[64]; + sprintf_P(buffer, PSTR("%s/%S/%S"), mqttDeviceTopic, _str_name, subTopic); + mqtt->publish(buffer, 2, true, Value.c_str(), Value.length()); + } + + bool _cmpIntSetting_P(char *topic, char *payload, const char *setting, void *value) + { + if (strcmp_P(topic, setting) == 0) + { + *((int *)value) = strtol(payload, NULL, 10); + _publishMQTTint_P(setting, *((int *)value)); + return true; + } + return false; + } + + bool _handleSetting(char *topic, char *payload) { + if (_cmpIntSetting_P(topic, payload, _str_timeEnabled, &umSSDRDisplayTime)) { + return true; + } + if (_cmpIntSetting_P(topic, payload, _str_ldrEnabled, &umSSDREnableLDR)) { + return true; + } + if (_cmpIntSetting_P(topic, payload, _str_inverted, &umSSDRInverted)) { + return true; + } + if (_cmpIntSetting_P(topic, payload, _str_colonblink, &umSSDRColonblink)) { + return true; + } + if (strcmp_P(topic, _str_displayMask) == 0) { + umSSDRDisplayMask = String(payload); + _publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask); + return true; + } + return false; + } + + void _updateMQTT() + { + _publishMQTTint_P(_str_timeEnabled, umSSDRDisplayTime); + _publishMQTTint_P(_str_ldrEnabled, umSSDREnableLDR); + _publishMQTTint_P(_str_inverted, umSSDRInverted); + _publishMQTTint_P(_str_colonblink, umSSDRColonblink); + + _publishMQTTstr_P(_str_hours, umSSDRHours); + _publishMQTTstr_P(_str_minutes, umSSDRMinutes); + _publishMQTTstr_P(_str_seconds, umSSDRSeconds); + _publishMQTTstr_P(_str_colons, umSSDRColons); + _publishMQTTstr_P(_str_days, umSSDRDays); + _publishMQTTstr_P(_str_months, umSSDRMonths); + _publishMQTTstr_P(_str_years, umSSDRYears); + _publishMQTTstr_P(_str_displayMask, umSSDRDisplayMask); + + _publishMQTTint_P(_str_minBrightness, umSSDRBrightnessMin); + _publishMQTTint_P(_str_maxBrightness, umSSDRBrightnessMax); + } + + void _addJSONObject(JsonObject& root) { + JsonObject ssdrObj = root[FPSTR(_str_name)]; + if (ssdrObj.isNull()) { + ssdrObj = root.createNestedObject(FPSTR(_str_name)); + } + + ssdrObj[FPSTR(_str_timeEnabled)] = umSSDRDisplayTime; + ssdrObj[FPSTR(_str_ldrEnabled)] = umSSDREnableLDR; + ssdrObj[FPSTR(_str_inverted)] = umSSDRInverted; + ssdrObj[FPSTR(_str_colonblink)] = umSSDRColonblink; + ssdrObj[FPSTR(_str_displayMask)] = umSSDRDisplayMask; + ssdrObj[FPSTR(_str_hours)] = umSSDRHours; + ssdrObj[FPSTR(_str_minutes)] = umSSDRMinutes; + ssdrObj[FPSTR(_str_seconds)] = umSSDRSeconds; + ssdrObj[FPSTR(_str_colons)] = umSSDRColons; + ssdrObj[FPSTR(_str_days)] = umSSDRDays; + ssdrObj[FPSTR(_str_months)] = umSSDRMonths; + ssdrObj[FPSTR(_str_years)] = umSSDRYears; + ssdrObj[FPSTR(_str_minBrightness)] = umSSDRBrightnessMin; + ssdrObj[FPSTR(_str_maxBrightness)] = umSSDRBrightnessMax; + } + +public: + //Functions called by WLED + + /* + * setup() is called once at boot. WiFi is not yet connected at this point. + * You can use it to initialize variables, sensors or similar. + */ + void setup() { + umSSDRLength = strip.getLengthTotal(); + if (umSSDRMask != 0) { + umSSDRMask = (bool*) realloc(umSSDRMask, umSSDRLength * sizeof(bool)); + } else { + umSSDRMask = (bool*) malloc(umSSDRLength * sizeof(bool)); + } + _setAllFalse(); + + #ifdef USERMOD_ID_SN_PHOTORESISTOR + ptr = (Usermod_SN_Photoresistor*) usermods.lookup(USERMOD_ID_SN_PHOTORESISTOR); + #endif + DEBUG_PRINTLN(F("Setup done")); + } + + /* + * loop() is called continuously. Here you can check for events, read sensors, etc. + */ + void loop() { + if (!umSSDRDisplayTime || strip.isUpdating()) { + return; + } + #ifdef USERMOD_ID_SN_PHOTORESISTOR + if(bri != 0 && umSSDREnableLDR && (millis() - umSSDRLastRefresh > umSSDRResfreshTime)) { + if (ptr != nullptr) { + uint16_t lux = ptr->getLastLDRValue(); + uint16_t brightness = map(lux, 0, 1000, umSSDRBrightnessMin, umSSDRBrightnessMax); + if (bri != brightness) { + bri = brightness; + colorUpdated(1); + } + } + umSSDRLastRefresh = millis(); + } + #endif + } + + void handleOverlayDraw() { + if (umSSDRDisplayTime) { + _overlaySevenSegmentDraw(); + } + } + +/* + * addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API. + * Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI. + * Below it is shown how this could be used for e.g. a light sensor + */ + void addToJsonInfo(JsonObject& root) { + JsonObject user = root[F("u")]; + if (user.isNull()) { + user = root.createNestedObject(F("u")); + } + JsonArray enabled = user.createNestedArray("Time enabled"); + enabled.add(umSSDRDisplayTime); + JsonArray invert = user.createNestedArray("Time inverted"); + invert.add(umSSDRInverted); + JsonArray blink = user.createNestedArray("Blinking colon"); + blink.add(umSSDRColonblink); + JsonArray ldrEnable = user.createNestedArray("Auto Brightness enabled"); + ldrEnable.add(umSSDREnableLDR); + + } + + /* + * addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + */ + void addToJsonState(JsonObject& root) { + JsonObject user = root[F("u")]; + if (user.isNull()) { + user = root.createNestedObject(F("u")); + } + _addJSONObject(user); + } + + /* + * readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object). + * Values in the state object may be modified by connected clients + */ + void readFromJsonState(JsonObject& root) { + JsonObject user = root[F("u")]; + if (!user.isNull()) { + JsonObject ssdrObj = user[FPSTR(_str_name)]; + umSSDRDisplayTime = ssdrObj[FPSTR(_str_timeEnabled)] | umSSDRDisplayTime; + umSSDREnableLDR = ssdrObj[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR; + umSSDRInverted = ssdrObj[FPSTR(_str_inverted)] | umSSDRInverted; + umSSDRColonblink = ssdrObj[FPSTR(_str_colonblink)] | umSSDRColonblink; + umSSDRDisplayMask = ssdrObj[FPSTR(_str_displayMask)] | umSSDRDisplayMask; + } + } + + void onMqttConnect(bool sessionPresent) { + char subBuffer[48]; + if (mqttDeviceTopic[0] != 0) + { + _updateMQTT(); + //subscribe for sevenseg messages on the device topic + sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttDeviceTopic, _str_name); + mqtt->subscribe(subBuffer, 2); + } + + if (mqttGroupTopic[0] != 0) + { + //subcribe for sevenseg messages on the group topic + sprintf_P(subBuffer, PSTR("%s/%S/+/set"), mqttGroupTopic, _str_name); + mqtt->subscribe(subBuffer, 2); + } + } + + bool onMqttMessage(char *topic, char *payload) { + //If topic beings iwth sevenSeg cut it off, otherwise not our message. + size_t topicPrefixLen = strlen_P(PSTR("/wledSS/")); + if (strncmp_P(topic, PSTR("/wledSS/"), topicPrefixLen) == 0) { + topic += topicPrefixLen; + } else { + return false; + } + //We only care if the topic ends with /set + size_t topicLen = strlen(topic); + if (topicLen > 4 && + topic[topicLen - 4] == '/' && + topic[topicLen - 3] == 's' && + topic[topicLen - 2] == 'e' && + topic[topicLen - 1] == 't') + { + //Trim /set and handle it + topic[topicLen - 4] = '\0'; + _handleSetting(topic, payload); + } + return true; + } + + void addToConfig(JsonObject &root) { + _addJSONObject(root); + } + + bool readFromConfig(JsonObject &root) { + JsonObject top = root[FPSTR(_str_name)]; + + if (top.isNull()) { + DEBUG_PRINT(FPSTR(_str_name)); + DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); + return false; + } + + umSSDRDisplayTime = (top[FPSTR(_str_timeEnabled)] | umSSDRDisplayTime); + umSSDREnableLDR = (top[FPSTR(_str_ldrEnabled)] | umSSDREnableLDR); + umSSDRInverted = (top[FPSTR(_str_inverted)] | umSSDRInverted); + umSSDRColonblink = (top[FPSTR(_str_colonblink)] | umSSDRColonblink); + + umSSDRDisplayMask = top[FPSTR(_str_displayMask)] | umSSDRDisplayMask; + umSSDRHours = top[FPSTR(_str_hours)] | umSSDRHours; + umSSDRMinutes = top[FPSTR(_str_minutes)] | umSSDRMinutes; + umSSDRSeconds = top[FPSTR(_str_seconds)] | umSSDRSeconds; + umSSDRColons = top[FPSTR(_str_colons)] | umSSDRColons; + umSSDRDays = top[FPSTR(_str_days)] | umSSDRDays; + umSSDRMonths = top[FPSTR(_str_months)] | umSSDRMonths; + umSSDRYears = top[FPSTR(_str_years)] | umSSDRYears; + umSSDRBrightnessMin = top[FPSTR(_str_minBrightness)] | umSSDRBrightnessMin; + umSSDRBrightnessMax = top[FPSTR(_str_maxBrightness)] | umSSDRBrightnessMax; + + DEBUG_PRINT(FPSTR(_str_name)); + DEBUG_PRINTLN(F(" config (re)loaded.")); + + return true; + } + /* + * getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!). + * This could be used in the future for the system to determine whether your usermod is installed. + */ + uint16_t getId() { + return USERMOD_ID_SSDR; + } +}; + +const char UsermodSSDR::_str_name[] PROGMEM = "UsermodSSDR"; +const char UsermodSSDR::_str_timeEnabled[] PROGMEM = "enabled"; +const char UsermodSSDR::_str_inverted[] PROGMEM = "inverted"; +const char UsermodSSDR::_str_colonblink[] PROGMEM = "Colon-blinking"; +const char UsermodSSDR::_str_displayMask[] PROGMEM = "Display-Mask"; +const char UsermodSSDR::_str_hours[] PROGMEM = "LED-Numbers-Hours"; +const char UsermodSSDR::_str_minutes[] PROGMEM = "LED-Numbers-Minutes"; +const char UsermodSSDR::_str_seconds[] PROGMEM = "LED-Numbers-Seconds"; +const char UsermodSSDR::_str_colons[] PROGMEM = "LED-Numbers-Colons"; +const char UsermodSSDR::_str_days[] PROGMEM = "LED-Numbers-Day"; +const char UsermodSSDR::_str_months[] PROGMEM = "LED-Numbers-Month"; +const char UsermodSSDR::_str_years[] PROGMEM = "LED-Numbers-Year"; +const char UsermodSSDR::_str_ldrEnabled[] PROGMEM = "enable-auto-brightness"; +const char UsermodSSDR::_str_minBrightness[] PROGMEM = "auto-brightness-min"; +const char UsermodSSDR::_str_maxBrightness[] PROGMEM = "auto-brightness-max"; diff --git a/wled00/const.h b/wled00/const.h index 67fce864b..3d3cf1cbc 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -64,6 +64,7 @@ #define USERMOD_ID_SEVEN_SEGMENT_DISPLAY 21 //Usermod "usermod_v2_seven_segment_display.h" #define USERMOD_RGB_ROTARY_ENCODER 22 //Usermod "rgb-rotary-encoder.h" #define USERMOD_ID_QUINLED_AN_PENTA 23 //Usermod "quinled-an-penta.h" +#define USERMOD_ID_SSDR 24 //Usermod "usermod_v2_seven_segment_display_reloaded.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 431ac9656..a4a7f031f 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -100,6 +100,10 @@ #include "../usermods/seven_segment_display/usermod_v2_seven_segment_display.h" #endif +#ifdef USERMOD_SSDR +#include "../usermods/seven_segment_display_reloaded/usermod_seven_segment_reloaded.h" +#endif + #ifdef QUINLED_AN_PENTA #include "../usermods/quinled-an-penta/quinled-an-penta.h" #endif @@ -192,6 +196,10 @@ void registerUsermods() usermods.add(new SevenSegmentDisplay()); #endif + #ifdef USERMOD_SSDR + usermods.add(new UsermodSSDR()); + #endif + #ifdef QUINLED_AN_PENTA usermods.add(new QuinLEDAnPentaUsermod()); #endif