From 5cc9ebb9a203eff5ff8962c224061cd1d4bfd922 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Mon, 25 Dec 2023 12:30:39 +0100 Subject: [PATCH 1/9] added wordclock-16x16-nl - initial commit --- .../usermod_v2_word_clock_1616_nl/readme.md | 47 ++ .../usermod_v2_word_clock_1616_nl.h | 486 ++++++++++++++++++ wled00/usermods_list.cpp | 9 + 3 files changed, 542 insertions(+) create mode 100644 usermods/usermod_v2_word_clock_1616_nl/readme.md create mode 100644 usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h diff --git a/usermods/usermod_v2_word_clock_1616_nl/readme.md b/usermods/usermod_v2_word_clock_1616_nl/readme.md new file mode 100644 index 0000000000..ac99ecea59 --- /dev/null +++ b/usermods/usermod_v2_word_clock_1616_nl/readme.md @@ -0,0 +1,47 @@ +# Word Clock Usermod V2 + +This usermod drives an 16x16 pixel matrix wordclock with WLED. The text +resolution is in 1 minutes and the last line containes seconds. There is some +extra space for more words so i added part of the day and date: the day and +month. The index of the LEDs in the masks always starts at 0, even if the +ledOffset is not 0. There are 3 parameters that control behavior: + +active: enable/disable usermod +diplayItIs: enable/disable display of "Het is" on the clock +ledOffset: number of LEDs before the wordclock LEDs + +## Installation + +* `USERMOD_WORDCLOCK_1616NL` - define this to have this usermod included wled00\usermods_list.cpp + +### PlatformIO requirements + +No special requirements. + +## Full Dutch Matrix + +``` + | 0 1 2 3 4 5 6 7 8 9 A B C D E F +--+-------------------------------- +0 | H E T I S Z E V E N E G E N +1 | K W A R T W E E N V I E R Z E S +2 | V I J F D R I E L F M I N U U T +3 | A C H T W A A L F D E R T I E N +4 | V E E R T I E N M I N U T E N +5 | V O O R O V E R H A L F +6 | T I E N E G E N V I E R V I J F +7 | D R I E L F T W E E N Z E V E N +8 | A C H T W A A L F Z E S U U R +9 | S . N A C H T S . M I D D A G S +A | S . A V O N D S . M O R G E N S +B | . 0 1 2 3 0 1 2 3 4 5 6 7 8 9 . +C | . . J A N F E B M R T A P R . . +D | . . M E I J U N J U L A U G . . +E | . . S E P O K T N O V D E C . . +F | 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9 +``` + +## Change Log + +2023/12/25 cloned from usermod_v2_word_clock + diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h new file mode 100644 index 0000000000..a291436674 --- /dev/null +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -0,0 +1,486 @@ +#pragma once + +#include "wled.h" + +/* + * Usermods allow you to add own functionality to WLED more easily + * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality + * + * This usermod can be used to drive a wordclock with a 11x10 pixel matrix with WLED. There are also 4 additional dots for the minutes. + * The visualisation is described in 4 mask with LED numbers (single dots for minutes, minutes, hours and "clock/Uhr"). + * There are 2 parameters to change the behaviour: + * + * active: enable/disable usermod + * diplayItIs: enable/disable display of "Es ist" on the clock. + */ + +class WordClockUsermod1616NL : public Usermod +{ + private: + unsigned long lastTime = 0; + int lastTimeSeconds = -1; + + // set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer) + bool usermodActive = false; + bool displayItIs = false; + int ledOffset = 0; + + // defines for mask sizes + #define maskSizeLeds 256 + #define maskSizeMinutes 8 + #define maskSizeHours 6 + #define maskSizeSeconds 1 + #define maskSizeMonths 3 + + // "minute" masks (and some extra words) + // | 0123456789ABCDEF + // --+----------------- + // 0 | .......ZEVENEGEN + // 1 | KWARTWEENVIERZES + // 2 | VIJFDRIELFMINUUT + // 3 | ACHTWAALFDERTIEN + // 4 | VEERTIEN MINUTEN + // 5 | VOOROVER HALF + // 9 | S.NACHTS.MIDDAGS + // A | S.AVONDS.MORGENS + const int maskMinutes[26][maskSizeMinutes] = + { + { 141, 142, 143, -1, -1, -1, -1, -1 }, // 0 - uur + { 22, 23, 24, -1, -1, -1, -1, -1 }, // 1 - een + { 20, 21, 22, 23, -1, -1, -1, -1 }, // 2 - twee + { 36, 37, 38, 39, -1, -1, -1, -1 }, // 3 - drie + { 25, 26, 27, 28, -1, -1, -1, -1 }, // 4 - vier + { 32, 33, 34, 35, -1, -1, -1, -1 }, // 5 - vijf + { 29, 30, 31, -1, -1, -1, -1, -1 }, // 6 - zes + { 7, 8, 9, 10, 11, -1, -1, -1 }, // 7 - zeven + { 48, 49, 50, 51, -1, -1, -1, -1 }, // 8 - acht + { 11, 12, 13, 14, 15, -1, -1, -1 }, // 9 - negen + { 52, 53, 54, 55, -1, -1, -1, -1 }, // 10 - tien + { 39, 40, 41, -1, -1, -1, -1, -1 }, // 11 - elf + { 51, 52, 53, 54, 55, 56, -1, -1 }, // 12 - twaalf + { 57, 58, 59, 60, 61, 62, 63, -1 }, // 13 - dertien + { 64, 65, 66, 67, 68, 69, 70, 71 }, // 14 - veertien + { 16, 17, 18, 19, 20, -1, -1, -1 }, // 15 - kwart + { 89, 90, 91, 92, -1, -1, -1, -1 }, // 16 - half + { 42, 43, 44, 45, 46, 47, -1, -1 }, // 17 - minuut + { 73, 74, 75, 76, 77, 78, 79, -1 }, // 18 - minuten + { 80, 81, 82, 83, -1, -1, -1, -1 }, // 19 - voor + { 84, 85, 86, 87, -1, -1, -1, -1 }, // 20 - over + { 0, 1, 2, 4, 5, -1, -1, -1 }, // 21 - het is (it is) + { 144, 146, 147, 148, 149, 150, 151, -1 }, // 22 - snachts + { 151, 153, 154, 155, 156, 157, 158, 159 }, // 23 - smiddags + { 169, 172, 173, 174, 175, 176, 177, -1 }, // 24 - savonds + { 177, 179, 180, 181, 182, 183, 184, 185 } // 25 - smorgens + }; + + // hour masks + // | 0123456789ABCDEF + // --+----------------- + // 6 | TIENEGENVIERVIJF + // 7 | DRIELFTWEENZEVEN + // 8 | ACHTWAALFZES UUR + const int maskHours[12][maskSizeHours] = + { + { 131, 132, 133, 134, 135, 136}, // 00: twaalf + { 120, 121, 122, -1, -1, -1}, // 01: een + { 118, 119, 120, 121, -1, -1}, // 02: twee + { 112, 113, 114, 115, -1, -1}, // 03: drie + { 104, 105, 106, 107, -1, -1}, // 04: vier + { 108, 109, 110, 111, -1, -1}, // 05: vijf + { 137, 138, 139, -1, -1, -1}, // 06: zes + { 123, 124, 125, 126, 127, -1}, // 07: zeven + { 128, 129, 130, 131, -1, -1}, // 08: acht + { 99, 100, 101, 102, 103, -1}, // 09: negen + { 96, 97, 98, 99, -1, -1}, // 10: tien + { 115, 116, 117, -1, -1, -1} // 11: elf + }; + + const int maskSeconds[10][maskSizeSeconds] = + { + { 246 }, // 00 + { 247 }, // 01 + { 248 }, // 02 + { 249 }, // 03 + { 250 }, // 04 + { 251 }, // 05 + { 252 }, // 06 + { 253 }, // 07 + { 254 }, // 08 + { 255 } // 09 + }; + + const int maskSecondTens[6][maskSizeSeconds] = + { + { -1 }, // 00 + { 241 }, // 01 + { 242 }, // 02 + { 243 }, // 03 + { 244 }, // 04 + { 245 } // 05 + }; + + // month masks + // | 0123456789ABCDEF + // --+----------------- + // B | .01230123456789. + // C | ..JANFEBMRTAPR.. + // D | ..MEIJUNJULAUG.. + // E | ..SEPOKTNOVDEC.. + const int maskMonths[12][maskSizeMonths] = + { + { 194,195,196 }, // 00 jan + { 197,198,199 }, // 01 feb + { 200,201,202 }, // 02 mrt + { 203,204,205 }, // 03 apr + { 210,211,212 }, // 04 mei + { 213,214,215 }, // 05 jun + { 216,217,218 }, // 06 jul + { 219,220,221 }, // 07 aug + { 226,227,228 }, // 08 sep + { 229,230,231 }, // 09 okt + { 232,233,234 }, // 10 nov + { 235,236,237 } // 11 dec + }; + + const int maskDays[10][maskSizeSeconds] = + { + { 181 }, // 00 + { 182 }, // 01 + { 183 }, // 02 + { 184 }, // 03 + { 185 }, // 04 + { 186 }, // 05 + { 187 }, // 06 + { 188 }, // 07 + { 189 }, // 08 + { 190 } // 09 + }; + + const int maskDayTens[4][maskSizeSeconds] = + { + { -1 }, // 00 + { 178 }, // 01 + { 179 }, // 02 + { 180 }, // 03 + }; + + + + // overall mask to define which LEDs are on + int maskLedsOn[maskSizeLeds] = + { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + }; + + // update led mask + void updateLedMask(const int wordMask[], int arraySize) + { + // loop over array + for (int x=0; x < arraySize; x++) + { + // check if mask has a valid LED number + if (wordMask[x] >= 0 && wordMask[x] < maskSizeLeds) + { + // turn LED on + maskLedsOn[wordMask[x]] = 1; + } + } + } + + // update the display + void updateDisplay(uint8_t months, uint8_t days, uint8_t hours, uint8_t minutes, uint8_t seconds) + { + // disable complete matrix at the begin + for (int x = 0; x < maskSizeLeds; x++) + { + maskLedsOn[x] = 0; + } + + int secondTens = seconds/10; + int dayTens = days/10; + int hoursIndex = hours; + int minutesIndex = minutes; + bool voor = false; // before / to + bool over = false; // after / past + bool half = false; // "half"-o-clock ;-) + bool minuten = false; + int partOfDayIndex; + + // calc part of day + partOfDayIndex = 22; + if (hours<7) partOfDayIndex = 22; + if (hours>=7 && hours<13) partOfDayIndex = 25; + if (hours>=13 && hours<19) partOfDayIndex = 23; + if (hours>=19) partOfDayIndex = 24; + + // calc hours index + if ( minutes>15 ) hoursIndex++; + hoursIndex %= 12; + + // calc minutes index + if ( minutesIndex==15 ) { + over = true; + } + if ( minutes==30 ) minutesIndex = 16; + if ( minutes==45 ) { + minutesIndex = 15; + voor = true; + } + if( minutes > 0 && minutes < 15 ) { + over = true; + minuten = true; + } + if( minutes > 15 && minutes < 30 ) { + minutesIndex = 30 - minutes; + voor = true; + half = true; + minuten = true; + } + if( minutes > 30 && minutes < 45 ) { + minutesIndex = minutes%30; + over = true; + half = true; + minuten = true; + } + if( minutes > 45 && minutes < 60 ) { + minutesIndex = 60 - minutes; + voor = true; + minuten = true; + } + if( minutesIndex > 21 ) + minutesIndex = 0; + + // updateLedMask + if (half) + updateLedMask(maskMinutes[16], maskSizeMinutes); + if (minuten) { + if (minutesIndex==1) + updateLedMask(maskMinutes[17], maskSizeMinutes); + else + updateLedMask(maskMinutes[18], maskSizeMinutes); + } + if (voor) + updateLedMask(maskMinutes[19], maskSizeMinutes); + if (over) + updateLedMask(maskMinutes[20], maskSizeMinutes); + if (displayItIs) // display it is/het is if activated + updateLedMask(maskMinutes[21], maskSizeMinutes); + + updateLedMask(maskHours[hoursIndex], maskSizeHours); + updateLedMask(maskMinutes[minutesIndex], maskSizeMinutes); + updateLedMask(maskMinutes[partOfDayIndex], maskSizeMinutes); + updateLedMask(maskSeconds[(seconds%10)], maskSizeSeconds); + updateLedMask(maskSecondTens[secondTens], maskSizeSeconds); + updateLedMask(maskMonths[(months+11)%12], maskSizeMonths); + updateLedMask(maskDays[(days%10)], maskSizeSeconds); + updateLedMask(maskDayTens[dayTens], maskSizeSeconds); + + } + + 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() + { + } + + /* + * connected() is called every time the WiFi is (re)connected + * Use it to initialize network interfaces + */ + void connected() + { + } + + /* + * loop() is called continuously. Here you can check for events, read sensors, etc. + * + * Tips: + * 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection. + * Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker. + * + * 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds. + * Instead, use a timer check as shown here. + */ + void loop() { + + // do it every 1 seconds + if (millis() - lastTime > 1000) + { + // check the time + int seconds = second(localTime); + + // check if we already updated this minute + if (lastTimeSeconds != seconds) + { + // update the display with new time + updateDisplay(month(localTime), day(localTime), hour(localTime), minute(localTime), second(localTime)); + // remember last update time + lastTimeSeconds = seconds; + } + + // remember last update + lastTime = millis(); + } + } + + /* + * 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) + { + } + */ + + /* + * 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) + { + } + + /* + * 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) + { + } + + /* + * addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object. + * It will be called by WLED when settings are actually saved (for example, LED settings are saved) + * If you want to force saving the current state, use serializeConfig() in your loop(). + * + * CAUTION: serializeConfig() will initiate a filesystem write operation. + * It might cause the LEDs to stutter and will cause flash wear if called too often. + * Use it sparingly and always in the loop, never in network callbacks! + * + * addToConfig() will make your settings editable through the Usermod Settings page automatically. + * + * Usermod Settings Overview: + * - Numeric values are treated as floats in the browser. + * - If the numeric value entered into the browser contains a decimal point, it will be parsed as a C float + * before being returned to the Usermod. The float data type has only 6-7 decimal digits of precision, and + * doubles are not supported, numbers will be rounded to the nearest float value when being parsed. + * The range accepted by the input field is +/- 1.175494351e-38 to +/- 3.402823466e+38. + * - If the numeric value entered into the browser doesn't contain a decimal point, it will be parsed as a + * C int32_t (range: -2147483648 to 2147483647) before being returned to the usermod. + * Overflows or underflows are truncated to the max/min value for an int32_t, and again truncated to the type + * used in the Usermod when reading the value from ArduinoJson. + * - Pin values can be treated differently from an integer value by using the key name "pin" + * - "pin" can contain a single or array of integer values + * - On the Usermod Settings page there is simple checking for pin conflicts and warnings for special pins + * - Red color indicates a conflict. Yellow color indicates a pin with a warning (e.g. an input-only pin) + * - Tip: use int8_t to store the pin value in the Usermod, so a -1 value (pin not set) can be used + * + * See usermod_v2_auto_save.h for an example that saves Flash space by reusing ArduinoJson key name strings + * + * If you need a dedicated settings page with custom layout for your Usermod, that takes a lot more work. + * You will have to add the setting to the HTML, xml.cpp and set.cpp manually. + * See the WLED Soundreactive fork (code and wiki) for reference. https://github.com/atuline/WLED + * + * I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings! + */ + void addToConfig(JsonObject& root) + { + JsonObject top = root.createNestedObject(F("WordClockUsermod1616NL")); + top[F("active")] = usermodActive; + top[F("displayItIs")] = displayItIs; + top[F("ledOffset")] = ledOffset; + } + + void appendConfigData() + { + oappend(SET_F("addInfo('WordClockUsermod1616NL:ledOffset', 1, 'Number of LEDs before the letters');")); + } + + /* + * readFromConfig() can be used to read back the custom settings you added with addToConfig(). + * This is called by WLED when settings are loaded (currently this only happens immediately after boot, or after saving on the Usermod Settings page) + * + * readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes), + * but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup. + * If you don't know what that is, don't fret. It most likely doesn't affect your use case :) + * + * Return true in case the config values returned from Usermod Settings were complete, or false if you'd like WLED to save your defaults to disk (so any missing values are editable in Usermod Settings) + * + * getJsonValue() returns false if the value is missing, or copies the value into the variable provided and returns true if the value is present + * The configComplete variable is true only if the "exampleUsermod" object and all values are present. If any values are missing, WLED will know to call addToConfig() to save them + * + * This function is guaranteed to be called on boot, but could also be called every time settings are updated + */ + bool readFromConfig(JsonObject& root) + { + // default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor + // setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed) + + JsonObject top = root[F("WordClockUsermod1616NL")]; + + bool configComplete = !top.isNull(); + + configComplete &= getJsonValue(top[F("active")], usermodActive); + configComplete &= getJsonValue(top[F("displayItIs")], displayItIs); + configComplete &= getJsonValue(top[F("ledOffset")], ledOffset); + + return configComplete; + } + + /* + * handleOverlayDraw() is called just before every show() (LED strip update frame) after effects have set the colors. + * Use this to blank out some LEDs or set them to a different color regardless of the set effect mode. + * Commonly used for custom clocks (Cronixie, 7 segment) + */ + void handleOverlayDraw() + { + // check if usermod is active + if (usermodActive == true) + { + // loop over all leds + for (int x = 0; x < maskSizeLeds; x++) + { + // check mask + if (maskLedsOn[x] == 0) + { + // set pixel off + strip.setPixelColor(x + ledOffset, RGBW32(0,0,0,0)); + } + } + } + } + + /* + * 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_WORDCLOCK; + } + + //More methods can be added in the future, this example will then be extended. + //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! +}; \ No newline at end of file diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 024e2bdc9c..825c86f501 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -141,6 +141,11 @@ #include "../usermods/usermod_v2_word_clock/usermod_v2_word_clock.h" #endif +#ifdef USERMOD_WORDCLOCK_1616NL + #include "../usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h" +#endif + + #ifdef USERMOD_MY9291 #include "../usermods/MY9291/usermode_MY9291.h" #endif @@ -325,6 +330,10 @@ void registerUsermods() usermods.add(new WordClockUsermod()); #endif + #ifdef USERMOD_WORDCLOCK_1616NL + usermods.add(new WordClockUsermod1616NL()); + #endif + #ifdef USERMOD_MY9291 usermods.add(new MY9291Usermod()); #endif From b02eb48a8a54e0540144df65ecce26e409a17ab3 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Tue, 26 Dec 2023 12:32:39 +0100 Subject: [PATCH 2/9] fixed wrong part-of-day --- .../usermod_v2_word_clock_1616_nl.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index a291436674..52a30dfacc 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -69,8 +69,8 @@ class WordClockUsermod1616NL : public Usermod { 0, 1, 2, 4, 5, -1, -1, -1 }, // 21 - het is (it is) { 144, 146, 147, 148, 149, 150, 151, -1 }, // 22 - snachts { 151, 153, 154, 155, 156, 157, 158, 159 }, // 23 - smiddags - { 169, 172, 173, 174, 175, 176, 177, -1 }, // 24 - savonds - { 177, 179, 180, 181, 182, 183, 184, 185 } // 25 - smorgens + { 160, 162, 163, 164, 165, 166, 167, -1 }, // 24 - savonds + { 167, 169, 170, 171, 172, 173, 174, 175 } // 25 - smorgens }; // hour masks @@ -223,7 +223,6 @@ class WordClockUsermod1616NL : public Usermod // calc part of day partOfDayIndex = 22; - if (hours<7) partOfDayIndex = 22; if (hours>=7 && hours<13) partOfDayIndex = 25; if (hours>=13 && hours<19) partOfDayIndex = 23; if (hours>=19) partOfDayIndex = 24; From bc463550971bfebc32764448d610ea75c7b2b849 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Thu, 4 Jan 2024 12:04:41 +0100 Subject: [PATCH 3/9] fix: corrected wrong minute index for 'tien' word --- usermods/usermod_v2_word_clock_1616_nl/readme.md | 2 ++ .../usermod_v2_word_clock_1616_nl.h | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/readme.md b/usermods/usermod_v2_word_clock_1616_nl/readme.md index ac99ecea59..31d4e8e249 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/readme.md +++ b/usermods/usermod_v2_word_clock_1616_nl/readme.md @@ -44,4 +44,6 @@ F | 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9 ## Change Log 2023/12/25 cloned from usermod_v2_word_clock +2023/12/26 fixed day-part postition +2024/01/04 fixed wrong pixel index for "tien" diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index 52a30dfacc..1230f372ba 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -55,7 +55,7 @@ class WordClockUsermod1616NL : public Usermod { 7, 8, 9, 10, 11, -1, -1, -1 }, // 7 - zeven { 48, 49, 50, 51, -1, -1, -1, -1 }, // 8 - acht { 11, 12, 13, 14, 15, -1, -1, -1 }, // 9 - negen - { 52, 53, 54, 55, -1, -1, -1, -1 }, // 10 - tien + { 60, 61, 62, 63, -1, -1, -1, -1 }, // 10 - tien { 39, 40, 41, -1, -1, -1, -1, -1 }, // 11 - elf { 51, 52, 53, 54, 55, 56, -1, -1 }, // 12 - twaalf { 57, 58, 59, 60, 61, 62, 63, -1 }, // 13 - dertien From 75aa68b844aa458dcd67623249c6c971ab553b8c Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Sun, 7 Jan 2024 16:59:30 +0100 Subject: [PATCH 4/9] :bug: fixed wrong daypart name --- .../usermod_v2_word_clock_1616_nl.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index 1230f372ba..26f353effe 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -222,11 +222,11 @@ class WordClockUsermod1616NL : public Usermod int partOfDayIndex; // calc part of day - partOfDayIndex = 22; - if (hours>=7 && hours<13) partOfDayIndex = 25; - if (hours>=13 && hours<19) partOfDayIndex = 23; - if (hours>=19) partOfDayIndex = 24; - + partOfDayIndex = 22; // 22 - snachts + if (hours>=7 && hours<12) partOfDayIndex = 25; // 25 - smorgens + if (hours>=12 && hours<19) partOfDayIndex = 23; // 23 - smiddags + if (hours>=19) partOfDayIndex = 24; // 24 - savonds + // calc hours index if ( minutes>15 ) hoursIndex++; hoursIndex %= 12; From cd8e511d3c9c83c7dba9e248f095f245b87dbbaf Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Sun, 25 Feb 2024 20:43:21 +0100 Subject: [PATCH 5/9] Corrected mod explanation in header file --- .../usermod_v2_word_clock_1616_nl.h | 23 +++++++++++-------- wled00/usermods_list.cpp | 1 - 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index 26f353effe..41a5009b2a 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -6,8 +6,11 @@ * Usermods allow you to add own functionality to WLED more easily * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality * - * This usermod can be used to drive a wordclock with a 11x10 pixel matrix with WLED. There are also 4 additional dots for the minutes. - * The visualisation is described in 4 mask with LED numbers (single dots for minutes, minutes, hours and "clock/Uhr"). + * This usermod can be used to drive a wordclock with a 16x16 pixel matrix with WLED. + * The clock resolution is in minutes with an extra line creating the seconds. I also + * managed to fit in the date displayed by the day numer and month abbreviation. + * The language for the clock in Dutch, in the readme you can find the layout mask for + * the words. * There are 2 parameters to change the behaviour: * * active: enable/disable usermod @@ -31,7 +34,7 @@ class WordClockUsermod1616NL : public Usermod #define maskSizeHours 6 #define maskSizeSeconds 1 #define maskSizeMonths 3 - + // "minute" masks (and some extra words) // | 0123456789ABCDEF // --+----------------- @@ -130,7 +133,7 @@ class WordClockUsermod1616NL : public Usermod { { 194,195,196 }, // 00 jan { 197,198,199 }, // 01 feb - { 200,201,202 }, // 02 mrt + { 200,201,202 }, // 02 mrt { 203,204,205 }, // 03 apr { 210,211,212 }, // 04 mei { 213,214,215 }, // 05 jun @@ -218,9 +221,9 @@ class WordClockUsermod1616NL : public Usermod bool voor = false; // before / to bool over = false; // after / past bool half = false; // "half"-o-clock ;-) - bool minuten = false; + bool minuten = false; int partOfDayIndex; - + // calc part of day partOfDayIndex = 22; // 22 - snachts if (hours>=7 && hours<12) partOfDayIndex = 25; // 25 - smorgens @@ -230,7 +233,7 @@ class WordClockUsermod1616NL : public Usermod // calc hours index if ( minutes>15 ) hoursIndex++; hoursIndex %= 12; - + // calc minutes index if ( minutesIndex==15 ) { over = true; @@ -261,14 +264,14 @@ class WordClockUsermod1616NL : public Usermod voor = true; minuten = true; } - if( minutesIndex > 21 ) + if( minutesIndex > 21 ) minutesIndex = 0; // updateLedMask if (half) updateLedMask(maskMinutes[16], maskSizeMinutes); if (minuten) { - if (minutesIndex==1) + if (minutesIndex==1) updateLedMask(maskMinutes[17], maskSizeMinutes); else updateLedMask(maskMinutes[18], maskSizeMinutes); @@ -288,7 +291,7 @@ class WordClockUsermod1616NL : public Usermod updateLedMask(maskMonths[(months+11)%12], maskSizeMonths); updateLedMask(maskDays[(days%10)], maskSizeSeconds); updateLedMask(maskDayTens[dayTens], maskSizeSeconds); - + } public: diff --git a/wled00/usermods_list.cpp b/wled00/usermods_list.cpp index 4e87167863..57d76529ad 100644 --- a/wled00/usermods_list.cpp +++ b/wled00/usermods_list.cpp @@ -145,7 +145,6 @@ #include "../usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h" #endif - #ifdef USERMOD_MY9291 #include "../usermods/MY9291/usermode_MY9291.h" #endif From 14b18003602c8538ee24366764e006bae3dc8ff5 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Tue, 27 Feb 2024 20:51:06 +0100 Subject: [PATCH 6/9] fixed usermod id --- .../usermod_v2_word_clock_1616_nl.h | 2 +- wled00/const.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index 41a5009b2a..fc451696f8 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -480,7 +480,7 @@ class WordClockUsermod1616NL : public Usermod */ uint16_t getId() { - return USERMOD_ID_WORDCLOCK; + return USERMOD_ID_WORDCLOCK_1616_NL; } //More methods can be added in the future, this example will then be extended. diff --git a/wled00/const.h b/wled00/const.h index 388b64c820..835489c50a 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -152,6 +152,7 @@ #define USERMOD_ID_INTERNAL_TEMPERATURE 42 //Usermod "usermod_internal_temperature.h" #define USERMOD_ID_LDR_DUSK_DAWN 43 //Usermod "usermod_LDR_Dusk_Dawn_v2.h" #define USERMOD_ID_STAIRWAY_WIPE 44 //Usermod "stairway-wipe-usermod-v2.h" +#define USERMOD_ID_WORDCLOCK_1616_NL 45 //Usermod "usermod_v2_word_clock_1616_nl.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot From e10929abbb5c665e3a7b5c1f376fd6b012caeec5 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Tue, 3 Jun 2025 19:57:02 +0200 Subject: [PATCH 7/9] clock text tweaks --- .../usermod_v2_word_clock_1616_nl/readme.md | 29 +++++++------ .../usermod_v2_word_clock_1616_nl.h | 43 ++++++++++--------- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/usermods/usermod_v2_word_clock_1616_nl/readme.md b/usermods/usermod_v2_word_clock_1616_nl/readme.md index 31d4e8e249..3ef6721027 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/readme.md +++ b/usermods/usermod_v2_word_clock_1616_nl/readme.md @@ -5,7 +5,7 @@ resolution is in 1 minutes and the last line containes seconds. There is some extra space for more words so i added part of the day and date: the day and month. The index of the LEDs in the masks always starts at 0, even if the ledOffset is not 0. There are 3 parameters that control behavior: - + active: enable/disable usermod diplayItIs: enable/disable display of "Het is" on the clock ledOffset: number of LEDs before the wordclock LEDs @@ -23,27 +23,30 @@ No special requirements. ``` | 0 1 2 3 4 5 6 7 8 9 A B C D E F --+-------------------------------- -0 | H E T I S Z E V E N E G E N +0 | H E T G I S Q Z E V E N E G E N 1 | K W A R T W E E N V I E R Z E S 2 | V I J F D R I E L F M I N U U T 3 | A C H T W A A L F D E R T I E N -4 | V E E R T I E N M I N U T E N -5 | V O O R O V E R H A L F +4 | V E E R T I E N H M I N U T E N +5 | V O O R A O V E R P H A L F T P 6 | T I E N E G E N V I E R V I J F 7 | D R I E L F T W E E N Z E V E N -8 | A C H T W A A L F Z E S U U R -9 | S . N A C H T S . M I D D A G S -A | S . A V O N D S . M O R G E N S -B | . 0 1 2 3 0 1 2 3 4 5 6 7 8 9 . -C | . . J A N F E B M R T A P R . . -D | . . M E I J U N J U L A U G . . -E | . . S E P O K T N O V D E C . . +8 | A C H T W A A L F Z E S K U U R +9 | S R N A C H T S L M I D D A G S +A | S M A V O N D S D M O R G E N S +B | 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9 +C | W I J A N F E B M R T A P R O F +D | F I M E I J U N J U L A U G O N +E | I R S E P O K T N O V D E C B T F | 0 1 2 3 4 5 0 1 2 3 4 5 6 7 8 9 ``` ## Change Log 2023/12/25 cloned from usermod_v2_word_clock -2023/12/26 fixed day-part postition +2023/12/26 fixed partOfDay postition 2024/01/04 fixed wrong pixel index for "tien" - +2024/01/07 changed partOfDay naming +2025/02/25 docu and whitespace +2025/02/27 fixed usermod ID after merge from main +2025/07/03 Filled blanks and moved some words, changed partOfDay name around 18:00 diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h index fc451696f8..238b80456a 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h @@ -64,11 +64,11 @@ class WordClockUsermod1616NL : public Usermod { 57, 58, 59, 60, 61, 62, 63, -1 }, // 13 - dertien { 64, 65, 66, 67, 68, 69, 70, 71 }, // 14 - veertien { 16, 17, 18, 19, 20, -1, -1, -1 }, // 15 - kwart - { 89, 90, 91, 92, -1, -1, -1, -1 }, // 16 - half + { 90, 91, 92, 93, -1, -1, -1, -1 }, // 16 - half { 42, 43, 44, 45, 46, 47, -1, -1 }, // 17 - minuut { 73, 74, 75, 76, 77, 78, 79, -1 }, // 18 - minuten { 80, 81, 82, 83, -1, -1, -1, -1 }, // 19 - voor - { 84, 85, 86, 87, -1, -1, -1, -1 }, // 20 - over + { 85, 86, 87, 88, -1, -1, -1, -1 }, // 20 - over { 0, 1, 2, 4, 5, -1, -1, -1 }, // 21 - het is (it is) { 144, 146, 147, 148, 149, 150, 151, -1 }, // 22 - snachts { 151, 153, 154, 155, 156, 157, 158, 159 }, // 23 - smiddags @@ -147,28 +147,29 @@ class WordClockUsermod1616NL : public Usermod const int maskDays[10][maskSizeSeconds] = { - { 181 }, // 00 - { 182 }, // 01 - { 183 }, // 02 - { 184 }, // 03 - { 185 }, // 04 - { 186 }, // 05 - { 187 }, // 06 - { 188 }, // 07 - { 189 }, // 08 - { 190 } // 09 + { 182 }, // 00 + { 183 }, // 01 + { 184 }, // 02 + { 185 }, // 03 + { 186 }, // 04 + { 187 }, // 05 + { 188 }, // 06 + { 189 }, // 07 + { 190 }, // 08 + { 191 } // 09 }; - const int maskDayTens[4][maskSizeSeconds] = + const int maskDayTens[6][maskSizeSeconds] = { - { -1 }, // 00 - { 178 }, // 01 - { 179 }, // 02 - { 180 }, // 03 + { 176 }, // 00 + { 177 }, // 01 + { 178 }, // 02 + { 179 }, // 03 + { 180 }, // 04 + { 181 }, // 05 }; - // overall mask to define which LEDs are on int maskLedsOn[maskSizeLeds] = { @@ -227,8 +228,10 @@ class WordClockUsermod1616NL : public Usermod // calc part of day partOfDayIndex = 22; // 22 - snachts if (hours>=7 && hours<12) partOfDayIndex = 25; // 25 - smorgens - if (hours>=12 && hours<19) partOfDayIndex = 23; // 23 - smiddags - if (hours>=19) partOfDayIndex = 24; // 24 - savonds + if (hours>=12 && hours<18) partOfDayIndex = 23; // 23 - smiddags + if (hours==17 && minutes>15) partOfDayIndex = 24; // 24 - savonds + if (hours>=18) partOfDayIndex = 24; // 24 - savonds + // calc hours index if ( minutes>15 ) hoursIndex++; From b651cd296db0e65297cc5435b880c42a4f34b41b Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Tue, 3 Jun 2025 20:08:52 +0200 Subject: [PATCH 8/9] added library.json --- usermods/usermod_v2_word_clock_1616_nl/library.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 usermods/usermod_v2_word_clock_1616_nl/library.json diff --git a/usermods/usermod_v2_word_clock_1616_nl/library.json b/usermods/usermod_v2_word_clock_1616_nl/library.json new file mode 100644 index 0000000000..b0f4160574 --- /dev/null +++ b/usermods/usermod_v2_word_clock_1616_nl/library.json @@ -0,0 +1,4 @@ +{ + "name": "usermod_v2_word_clock_1616_nl", + "build": { "libArchive": false } +} \ No newline at end of file From 7771124b857b5fcf49f71f8df2088d4145df56b1 Mon Sep 17 00:00:00 2001 From: Henrie Cuijpers Date: Wed, 4 Jun 2025 20:48:43 +0200 Subject: [PATCH 9/9] renamed usermod file --- ...rd_clock_1616_nl.h => usermod_v2_word_clock_1616_nl.cpp} | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) rename usermods/usermod_v2_word_clock_1616_nl/{usermod_v2_word_clock_1616_nl.h => usermod_v2_word_clock_1616_nl.cpp} (99%) diff --git a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.cpp similarity index 99% rename from usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h rename to usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.cpp index 238b80456a..4718b597fd 100644 --- a/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.h +++ b/usermods/usermod_v2_word_clock_1616_nl/usermod_v2_word_clock_1616_nl.cpp @@ -488,4 +488,8 @@ class WordClockUsermod1616NL : public Usermod //More methods can be added in the future, this example will then be extended. //Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class! -}; \ No newline at end of file +}; + + +static WordClockUsermod1616NL usermod_v2_word_clock_1616_nl; +REGISTER_USERMOD(usermod_v2_word_clock_1616_nl); \ No newline at end of file