diff --git a/.gitignore b/.gitignore index bb02e36e..789de0a9 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,5 @@ node_modules wled-update.sh esp01-update.sh /wled00/LittleFS -replace_fs.py \ No newline at end of file +replace_fs.py +wled00/wled00.ino.cpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 35308115..aaf02f12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## WLED changelog +#### Build 2302180 + +- Removed Blynk support (servers shut down on 31st Dec 2022) + #### Build 2301240 - Version bump to v0.14.0-b2 "Hoshi" diff --git a/boards/esp32_16MB-poe.json b/boards/esp32_16MB-poe.json new file mode 100644 index 00000000..a15ef9a3 --- /dev/null +++ b/boards/esp32_16MB-poe.json @@ -0,0 +1,38 @@ +{ +"build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV -DARDUINO_ESP32_POE", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32-poe", + "partitions": "partitions_16M.csv" +}, +"connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" +], +"debug": { + "openocd_board": "esp-wroom-32.cfg" +}, +"frameworks": [ + "arduino", + "espidf" +], +"name": "ESP32 16MB", +"upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 2000000 +}, +"url": "https://en.wikipedia.org/wiki/ESP32", +"vendor": "Multiple" +} diff --git a/package-lock.json b/package-lock.json index 76bc09c1..97497117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "wled", - "version": "0.14.0-b1.18", + "version": "0.14.0-b15.21", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "wled", - "version": "0.14.0-b1.18", + "version": "0.14.0-b15.21", "license": "ISC", "dependencies": { "clean-css": "^4.2.3", @@ -2939,24 +2939,6 @@ } }, "dependencies": { - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" - }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -2983,39 +2965,6 @@ "repeat-string": "^1.5.2" } }, - "ansi-align": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", - "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", - "requires": { - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, "ansi-escapes": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", @@ -3032,9 +2981,9 @@ "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3082,9 +3031,9 @@ "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -3095,68 +3044,15 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=" }, - "boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3179,35 +3075,6 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==" }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" - } - } - }, "camelcase": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", @@ -3257,25 +3124,20 @@ } }, "chokidar": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", - "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", "requires": { - "anymatch": "~3.1.1", + "anymatch": "~3.1.2", "braces": "~3.0.2", - "fsevents": "~2.1.2", - "glob-parent": "~5.1.0", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", "is-binary-path": "~2.1.0", "is-glob": "~4.0.1", "normalize-path": "~3.0.0", - "readdirp": "~3.4.0" + "readdirp": "~3.6.0" } }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, "clap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", @@ -3299,11 +3161,6 @@ } } }, - "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==" - }, "cliui": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", @@ -3314,14 +3171,6 @@ "wordwrap": "0.0.2" } }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "requires": { - "mimic-response": "^1.0.0" - } - }, "coa": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/coa/-/coa-1.0.4.tgz", @@ -3330,19 +3179,6 @@ "q": "^1.1.2" } }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "colors": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", @@ -3364,7 +3200,7 @@ "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "configstore": { "version": "1.4.0", @@ -3393,11 +3229,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" - }, "css-select": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.0.0.tgz", @@ -3444,24 +3275,11 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "requires": { - "mimic-response": "^1.0.0" - } - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -3525,19 +3343,6 @@ } } }, - "dot-prop": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", - "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", - "requires": { - "is-obj": "^2.0.0" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" - }, "duplexify": { "version": "3.7.1", "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", @@ -3592,11 +3397,6 @@ "safer-buffer": "^2.1.0" } }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, "end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -3615,11 +3415,6 @@ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-2.3.0.tgz", "integrity": "sha1-lu258v2wGZWCKyY92KratnSBgbw=" }, - "escape-goat": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", - "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" - }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -3674,19 +3469,11 @@ } }, "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "optional": true }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "requires": { - "pump": "^3.0.0" - } - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -3703,14 +3490,6 @@ "is-glob": "^4.0.1" } }, - "global-dirs": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", - "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", - "requires": { - "ini": "^1.3.5" - } - }, "got": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/got/-/got-3.3.1.tgz", @@ -3765,12 +3544,7 @@ "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "has-yarn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", - "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==" }, "he": { "version": "1.2.0", @@ -3844,11 +3618,6 @@ } } }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, "http-signature": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", @@ -3870,12 +3639,7 @@ "ignore-by-default": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", - "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" - }, - "import-lazy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, "imurmurhash": { "version": "0.1.4", @@ -3936,46 +3700,24 @@ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" }, - "is-ci": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", - "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", - "requires": { - "ci-info": "^2.0.0" - } - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, "is-finite": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz", "integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==" }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "requires": { "is-extglob": "^2.1.1" } }, - "is-installed-globally": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", - "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", - "requires": { - "global-dirs": "^2.0.1", - "is-path-inside": "^3.0.1" - } - }, "is-npm": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-1.0.0.tgz", @@ -3986,16 +3728,6 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, - "is-obj": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", - "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" - }, - "is-path-inside": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", - "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==" - }, "is-redirect": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", @@ -4011,11 +3743,6 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, - "is-yarn-global": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", - "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" - }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -4045,11 +3772,6 @@ "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz", "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==" }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -4076,14 +3798,6 @@ "verror": "1.10.0" } }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "requires": { - "json-buffer": "3.0.0" - } - }, "kind-of": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", @@ -4227,21 +3941,6 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "requires": { - "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -4260,15 +3959,10 @@ "mime-db": "1.44.0" } }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" - }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "requires": { "brace-expansion": "^1.1.7" } @@ -4300,152 +3994,34 @@ } }, "nodemon": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", - "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", + "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", "requires": { - "chokidar": "^3.2.2", - "debug": "^3.2.6", + "chokidar": "^3.5.2", + "debug": "^3.2.7", "ignore-by-default": "^1.0.1", - "minimatch": "^3.0.4", - "pstree.remy": "^1.1.7", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", "semver": "^5.7.1", + "simple-update-notifier": "^1.0.7", "supports-color": "^5.5.0", "touch": "^3.1.0", - "undefsafe": "^2.0.2", - "update-notifier": "^4.0.0" + "undefsafe": "^2.0.5" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "configstore": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", - "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", - "requires": { - "dot-prop": "^5.2.0", - "graceful-fs": "^4.1.2", - "make-dir": "^3.0.0", - "unique-string": "^2.0.0", - "write-file-atomic": "^3.0.0", - "xdg-basedir": "^4.0.0" - } - }, "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "requires": { "ms": "^2.1.1" } }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "is-npm": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", - "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" - }, - "latest-version": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", - "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", - "requires": { - "package-json": "^6.3.0" - } - }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "package-json": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", - "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", - "requires": { - "got": "^9.6.0", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^6.2.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } - }, - "registry-url": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", - "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", - "requires": { - "rc": "^1.2.8" - } - }, - "semver-diff": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", - "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", - "requires": { - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } - } + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "supports-color": { "version": "5.5.0", @@ -4454,49 +4030,13 @@ "requires": { "has-flag": "^3.0.0" } - }, - "update-notifier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", - "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", - "requires": { - "boxen": "^4.2.0", - "chalk": "^3.0.0", - "configstore": "^5.0.1", - "has-yarn": "^2.1.0", - "import-lazy": "^2.1.0", - "is-ci": "^2.0.0", - "is-installed-globally": "^0.3.1", - "is-npm": "^4.0.0", - "is-yarn-global": "^0.3.0", - "latest-version": "^5.0.0", - "pupa": "^2.0.1", - "semver-diff": "^3.1.1", - "xdg-basedir": "^4.0.0" - } - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" } } }, "nopt": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", "requires": { "abbrev": "1" } @@ -4506,11 +4046,6 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, - "normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==" - }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -4556,11 +4091,6 @@ "os-tmpdir": "^1.0.0" } }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" - }, "package-json": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/package-json/-/package-json-1.2.0.tgz", @@ -4604,9 +4134,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pinkie": { "version": "2.0.4", @@ -4649,28 +4179,11 @@ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "pupa": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", - "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", - "requires": { - "escape-goat": "^2.0.0" - } - }, "q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -4747,21 +4260,13 @@ } }, "readdirp": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", - "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "requires": { "picomatch": "^2.2.1" } }, - "registry-auth-token": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", - "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", - "requires": { - "rc": "^1.2.8" - } - }, "registry-url": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", @@ -4815,14 +4320,6 @@ "uuid": "^3.3.2" } }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "requires": { - "lowercase-keys": "^1.0.0" - } - }, "right-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", @@ -4859,10 +4356,20 @@ "semver": "^5.0.3" } }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + "simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "requires": { + "semver": "~7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==" + } + } }, "slide": { "version": "1.1.6", @@ -4929,40 +4436,10 @@ "strip-ansi": "^3.0.0" } }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "requires": { - "ansi-regex": "^5.0.0" - } - } - } + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" }, "strip-ansi": { "version": "3.0.1", @@ -4996,11 +4473,6 @@ "whet.extend": "~0.9.9" } }, - "term-size": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", - "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" - }, "terser": { "version": "4.8.1", "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", @@ -5031,11 +4503,6 @@ "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz", "integrity": "sha1-84sK6B03R9YoAB9B2vxlKs5nHAo=" }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5079,19 +4546,6 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "requires": { - "is-typedarray": "^1.0.0" - } - }, "uglify-js": { "version": "2.8.29", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", @@ -5109,20 +4563,9 @@ "optional": true }, "undefsafe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", - "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", - "requires": { - "debug": "^2.2.0" - } - }, - "unique-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", - "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", - "requires": { - "crypto-random-string": "^2.0.0" - } + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==" }, "update-notifier": { "version": "0.5.0", @@ -5146,21 +4589,6 @@ "punycode": "^2.1.0" } }, - "url-parse-lax": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", - "requires": { - "prepend-http": "^2.0.0" - }, - "dependencies": { - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5186,14 +4614,6 @@ "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", "integrity": "sha1-+HfVv2SMl+WqVC+twW1qJZucEaE=" }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "requires": { - "string-width": "^4.0.0" - } - }, "window-size": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", diff --git a/package.json b/package.json index 38eff204..a3297fa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wled", - "version": "0.14.0-b1.18", + "version": "0.14.0-b15.21", "description": "Tools for WLED project", "main": "tools/cdata.js", "directories": { @@ -25,7 +25,7 @@ "clean-css": "^4.2.3", "html-minifier-terser": "^5.1.1", "inliner": "^1.13.1", - "nodemon": "^2.0.4", + "nodemon": "^2.0.20", "zlib": "^1.0.5" } } diff --git a/platformio.ini b/platformio.ini index 8a67f546..df001a91 100644 --- a/platformio.ini +++ b/platformio.ini @@ -40,27 +40,37 @@ ; =================== default_envs = - esp32_4MB_max ; recommended default - esp32_4MB_all - esp32_16MB_max - esp32_16MB_all - esp8266_4MB_min - esp8266_4MB_max - esp32_4MB_PSRAM_max - esp32S3_8MB_max - wemos_shield_esp32_4MB_max - wemos_shield_esp32_4MB_ICS4343x_max - wemos_shield_esp32_4MB_SPM1423_max - wemos_shield_esp32_4MB_LineIn_max - wemos_shield_esp32_16MB_max - wemos_shield_esp32_16MB_ICS4343x_max - wemos_shield_esp32_16MB_SPM1423_max - wemos_shield_esp32_16MB_SPM1423_all - wemos_shield_esp32_16MB_LineIn_max - esp32_pico_4MB_max - esp32s2_tinyUF2_PSRAM_max - esp8266pro_16MB_min - esp01_1MB_min + esp32_4MB_M ; recommended default + esp32_4MB_M_debug + esp32_4MB_XL + esp32_16MB_M + esp32_16MB_M_debug + esp32_16MB_XL + esp8266_4MB_S + esp8266_4MB_M + wemos_shield_esp32_4MB_M + wemos_shield_esp32_4MB_ICS4343x_M + wemos_shield_esp32_4MB_SPM1423_M + wemos_shield_esp32_4MB_LineIn_M + wemos_shield_esp32_16MB_M + wemos_shield_esp32_16MB_ICS4343x_M + wemos_shield_esp32_16MB_SPM1423_M + wemos_shield_esp32_16MB_SPM1423_XL + wemos_shield_esp32_16MB_LineIn_M + esp32_pico_4MB_M + esp32_4MB_PSRAM_S + esp32S3_8MB_M + ;; esp32s2_tinyUF2_PSRAM_S ;; experimental - only for adafruit -S2 boards with tinyUF2 bootloader !!! + esp32s2_PSRAM_M ;; experimental + esp32c3dev_4MB_M ;; experimental + esp32_4MB_V4_S ;; experimental + esp32_16MB_V4_M ;; experimental + esp32_16MB_V4_M_debug ;; experimental + esp8266pro_16MB_S + esp8266pro_16MB_M + esp01_1MB_S + esp32_16MB_M_eth + athom_music_esp32_4MB_M ; Go to MoonModules environments for environments @@ -138,6 +148,8 @@ build_flags = -D DECODE_SONY=true -D DECODE_SAMSUNG=true -D DECODE_LG=true + ;-D DECODE_RC5=true + ;-D DECODE_RC6=true ; -Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library -DWLED_USE_MY_CONFIG ; -D USERMOD_SENSORSTOMQTT @@ -183,7 +195,7 @@ upload_speed = 115200 # Please note that we don't always use the latest version of a library. # # The following libraries have been included (and some of them changd) in the source: -# ArduinoJson@5.13.5, Blynk@0.5.4(changed), E131@1.0.0(changed), Time@1.5, Timezone@1.2.1 +# ArduinoJson@5.13.5, E131@1.0.0(changed), Time@1.5, Timezone@1.2.1 # ------------------------------------------------------------------------------ lib_compat_mode = strict lib_deps = @@ -248,7 +260,8 @@ build_flags = -g -D LOROL_LITTLEFS ; -DARDUINO_USB_CDC_ON_BOOT=0 ;; this flag is mandatory for "classic ESP32" when builing with arduino-esp32 >=2.0.3 -default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv +default_partitions = tools/WLED_ESP32_4MB_1MB_FS.csv ;; WLED standard for 4MB flash: 1.4MB firmware, 1MB filesystem +;default_partitions = tools/WLED_ESP32_4MB_256KB_FS.csv ;; Alternative for 4MB flash: 1.8MB firmware, 256KB filesystem (esptool erase_flash needed before changing) lib_deps = ${env.lib_deps} @@ -280,9 +293,10 @@ lib_depsV4 = [esp32s2] build_flags = -g - -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32 -DESP32 ;; WLEDMM -DARDUINO_ARCH_ESP32S2 -DCONFIG_IDF_TARGET_ESP32S2 + -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE ;; WLEDMM -D CONFIG_ASYNC_TCP_USE_WDT=0 -DCO -DARDUINO_USB_MODE=0 ;; this flag is mandatory for ESP32-S2 ! @@ -296,9 +310,10 @@ lib_deps = [esp32c3] build_flags = -g - -DARDUINO_ARCH_ESP32 + -DARDUINO_ARCH_ESP32 -DESP32 ;; WLEDMM -DARDUINO_ARCH_ESP32C3 -DCONFIG_IDF_TARGET_ESP32C3 + -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE ;; WLEDMM -D CONFIG_ASYNC_TCP_USE_WDT=0 -DCO -DARDUINO_USB_MODE=1 ;; this flag is mandatory for ESP32-C3 @@ -317,6 +332,7 @@ build_flags = -g -DARDUINO_ARCH_ESP32 -DARDUINO_ARCH_ESP32S3 -DCONFIG_IDF_TARGET_ESP32S3 + -DCONFIG_LITTLEFS_FOR_IDF_3_2 -DLFS_THREADSAFE ;; WLEDMM -D CONFIG_ASYNC_TCP_USE_WDT=0 -DCO ;; please make sure that the following flags are properly set (to 0 or 1) by your board.json, or included in your custom platformio_override.ini entry: @@ -326,7 +342,7 @@ lib_deps = ${env.lib_deps} ;; currently we need the latest NeoPixelBus dev version, because it contains important bugfixes for -S3 ;https://github.com/Makuna/NeoPixelBus.git#master ;; NPB 2.6.9 tends to crash whith IDF V4.4.3 -> use latest NeoPixelBus dev instead - makuna/NeoPixelBus @ 2.7.1 + makuna/NeoPixelBus @ ~2.7.1 https://github.com/pbolduc/AsyncTCP.git @ 1.2.0 @@ -340,7 +356,7 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_4m1m} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D WLED_DISABLE_BLYNK #-DWLED_DISABLE_2D +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 #-DWLED_DISABLE_2D lib_deps = ${esp8266.lib_deps} monitor_filters = esp8266_exception_decoder @@ -350,17 +366,17 @@ platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_2m512k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 -D WLED_DISABLE_BLYNK +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP02 lib_deps = ${esp8266.lib_deps} -; WLEDMM see below +;WLEDMM: see below ; [env:esp01_1m_full] ; board = esp01_1m ; platform = ${common.platform_wled_default} ; platform_packages = ${common.platform_packages} ; board_build.ldscript = ${common.ldscript_1m128k} ; build_unflags = ${common.build_unflags} -; build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA -D WLED_DISABLE_BLYNK +; build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP01 -D WLED_DISABLE_OTA ; lib_deps = ${esp8266.lib_deps} [env:esp07] @@ -406,7 +422,7 @@ board = esp32dev platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 -D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32 #-D WLED_DISABLE_BROWNOUT_DET lib_deps = ${esp32.lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.default_partitions} @@ -416,7 +432,7 @@ board = esp32dev platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 -D WLED_DISABLE_BLYNK #-D WLED_DISABLE_BROWNOUT_DET +build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_qio80 #-D WLED_DISABLE_BROWNOUT_DET lib_deps = ${esp32.lib_deps} monitor_filters = esp32_exception_decoder board_build.partitions = ${esp32.default_partitions} @@ -429,7 +445,7 @@ platform = ${esp32.platform} platform_packages = ${esp32.platform_packages} upload_speed = 921600 build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 -D WLED_DISABLE_BLYNK +build_flags = ${common.build_flags_esp32} -D WLED_RELEASE_NAME=ESP32_Ethernet -D RLYPIN=-1 -D WLED_USE_ETHERNET -D BTNPIN=-1 lib_deps = ${esp32.lib_deps} board_build.partitions = ${esp32.default_partitions} @@ -460,7 +476,7 @@ build_flags = ${common.build_flags} ${esp32c3.build_flags} -D WLED_RELEASE_NAME= -D CONFIG_LITTLEFS_FOR_IDF_3_2 ; WLEDMM -D WLED_USE_MY_CONFIG ; WLEDMM ; -D USERMOD_AUDIOREACTIVE ; WLEDMM - -D USERMOD_CUSTOMEFFECTS ; WLEDMM + -D USERMOD_ARTIFX ; WLEDMM upload_speed = 460800 build_unflags = ${common.build_unflags} lib_deps = ${esp32c3.lib_deps} @@ -479,7 +495,7 @@ build_flags = ${common.build_flags} ${esp32s3.build_flags} -D CONFIG_LITTLEFS_F -D WLED_RELEASE_NAME=ESP32-S3 -D WLED_USE_MY_CONFIG -D USERMOD_AUDIOREACTIVE - -D USERMOD_CUSTOMEFFECTS + -D USERMOD_ARTIFX lib_deps = ${esp32s3.lib_deps} https://github.com/blazoncek/arduinoFFT.git board_build.partitions = tools/WLED_ESP32_8MB.csv @@ -596,7 +612,7 @@ build_flags = ${common.build_flags} ${esp32s2.build_flags} -D WLED_RELEASE_NAME ; -D STATUSLED=15 -D WLED_USE_MY_CONFIG -D USERMOD_AUDIOREACTIVE - -D USERMOD_CUSTOMEFFECTS + -D USERMOD_ARTIFX lib_deps = ${esp32s2.lib_deps} https://github.com/blazoncek/arduinoFFT.git @@ -650,20 +666,58 @@ board_build.ldscript = ${common.ldscript_2m512k} build_flags = ${common.build_flags_esp8266} -D LEDPIN=3 -D BTNPIN=2 -D IRPIN=5 -D WLED_MAX_BUTTONS=3 lib_deps = ${esp8266.lib_deps} -[env:athom7w] -board = esp_wroom_02 +[env:Athom_RGBCW] ;7w and 5w(GU10) bulbs +board = esp8285 platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_2m512k} -build_flags = ${common.build_flags_esp8266} -D WLED_MAX_CCT_BLEND=0 -D BTNPIN=-1 -D IRPIN=-1 -D WLED_DISABLE_INFRARED +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,13,5 + -D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0 lib_deps = ${esp8266.lib_deps} -[env:athom15w] -board = esp_wroom_02 + +[env:Athom_15w_RGBCW] ;15w bulb +board = esp8285 platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_2m512k} -build_flags = ${common.build_flags_esp8266} -D WLED_USE_IC_CCT -D BTNPIN=-1 -D IRPIN=-1 -D WLED_DISABLE_INFRARED +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=-1 -D RLYPIN=-1 -D DATA_PINS=4,12,14,5,13 + -D DEFAULT_LED_TYPE=TYPE_ANALOG_5CH -D WLED_DISABLE_INFRARED -D WLED_MAX_CCT_BLEND=0 -D WLED_USE_IC_CCT lib_deps = ${esp8266.lib_deps} + +[env:Athom_3Pin_Controller] ;small controller with only data +board = esp8285 +platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} +board_build.ldscript = ${common.ldscript_2m512k} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 -D LEDPIN=1 -D WLED_DISABLE_INFRARED +lib_deps = ${esp8266.lib_deps} + + +[env:Athom_4Pin_Controller] ; With clock and data interface +board = esp8285 +platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} +board_build.ldscript = ${common.ldscript_2m512k} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=12 -D LEDPIN=1 -D WLED_DISABLE_INFRARED +lib_deps = ${esp8266.lib_deps} + + +[env:Athom_5Pin_Controller] ;Analog light strip controller +board = esp8285 +platform = ${common.platform_wled_default} +platform_packages = ${common.platform_packages} +board_build.ldscript = ${common.ldscript_2m512k} +build_unflags = ${common.build_unflags} +build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D BTNPIN=0 -D RLYPIN=-1 DATA_PINS=4,12,14,13 -D WLED_DISABLE_INFRARED +lib_deps = ${esp8266.lib_deps} + + [env:MY9291] board = esp01_1m platform = ${common.platform_wled_default} @@ -709,7 +763,6 @@ build_flags = ${common.build_flags_esp32} -D WLED_DISABLE_BROWNOUT_DET -D WLED_D -D LEDPIN=12 -D RLYPIN=27 -D BTNPIN=34 - -D WLED_DISABLE_BLYNK -D DEFAULT_LED_COUNT=6 # Display config -D ST7789_DRIVER @@ -742,21 +795,15 @@ board_build.partitions = ${esp32.default_partitions} ; shared build flags and lib deps for minimum and maximum environment [common_mm] -build_flags_min = +build_flags_S = -Wall -Wformat -Woverflow -Wuninitialized -Winit-self -Warray-bounds ; enables more warnings -Wno-attributes -Wno-unused-variable -Wno-unused-function -Wno-deprecated-declarations ;disables some stupid warnings - -D WLED_DISABLE_BLYNK ; BLYNK is only provided for backwards compatibility (no new users accepted) ;-D WLED_DISABLE_BROWNOUT_DET ; enable if you get "brownout detected" errors at startup -D WLED_USE_MY_CONFIG ; -D WLED_USE_CIE_BRIGHTNESS_TABLE ;; experimental: use different color / brightness lookup table -D USERMOD_AUDIOREACTIVE -D UM_AUDIOREACTIVE_USE_NEW_FFT ; use latest (upstream) FFTLib, instead of older library modified by blazoncek. Slightly faster, more accurate, needs 2KB RAM extra - -D USERMOD_CUSTOMEFFECTS ; WLEDMM usermod - ; -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' ;; to send debug messages over network to host 192.168.x.y - FQDN is also possible - ; -D WLED_DEBUG_NET_PORT=1768 ;; port for network debugging. default = 7868 - ; -D WLED_DEBUG ; lots of generic debug messages - ; -D SR_DEBUG ; some extra debug messages from audioreactive - ; -D MIC_LOGGER ; for sound input monitoring & debugging (use arduino serial plotter) + -D USERMOD_ARTIFX ; WLEDMM usermod ; -D WLED_DISABLE_LOXONE ; -D WLED_DISABLE_ALEXA ; -D WLED_DISABLE_HUESYNC @@ -764,13 +811,13 @@ build_flags_min = ; -D WLED_DISABLE_INFRARED ; -D WLED_ENABLE_DMX -lib_deps_min = +lib_deps_S = https://github.com/kosme/arduinoFFT#develop @ 1.9.2 ; used for USERMOD_AUDIOREACTIVE -build_flags_max = - -D WLED_MAX_USERMODS=25 ; default only 4-6, also for _all configs takes 25 pointers in memory - ;; -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4 ewowi to softhack: move to build_flags_min? - We need a different solution - -D WLED_USE_MY_CONFIG ; include custom my_config.h ewowi to softhack: redundant as also in build_flags_min? +build_flags_M = + -D WLED_MAX_USERMODS=25 ; default only 4-6, also for _XL configs takes 25 pointers in memory + ;; -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4 ewowi to softhack: move to build_flags_S? - We need a different solution + -D WLED_USE_MY_CONFIG ; include custom my_config.h ewowi to softhack: redundant as also in build_flags_S? -D USERMOD_DALLASTEMPERATURE -D USE_ALT_DISPLAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI -D USERMOD_FOUR_LINE_DISPLAY @@ -779,19 +826,24 @@ build_flags_max = -D USERMOD_WEATHER ; WLEDMM usermod -D USERMOD_MPU6050_IMU ; gyro/accelero for USERMOD_GAMES (ONLY WORKS IF USERMOD_FOUR_LINE_DISPLAY NOT INCLUDED - I2C SHARING BUG) -D USERMOD_GAMES ; WLEDMM usermod + ;WLEDMM: only setting WLED_DEBUG_HOST is enough, ip and port can be defined in sync settings as well + -D WLED_DEBUG_HOST='"192.168.x.x"' ;; to send debug messages over network to host 192.168.x.y - FQDN is also possible + -D WLED_DEBUG_PORT=1768 ;; port for network debugging. default = 7868 -lib_deps_max = +lib_deps_M = + ;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings OneWire@~2.3.5 ; used for USERMOD_FOUR_LINE_DISPLAY and USERMOD_DALLASTEMPERATURE olikraus/U8g2 @ ^2.28.8 ; used for USERMOD_FOUR_LINE_DISPLAY ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU -lib_deps_V4_max = +lib_deps_V4_M = + ;https://github.com/blazoncek/OneWire.git ; includes bugfixes for inconsistent readings paulstoffregen/OneWire@ ^2.3.7 ; used for USERMOD_DALLASTEMPERATURE -> need newer release with bugfixes for -S3; still requires TEMPERATURE_PIN < 46 olikraus/U8g2@ ^2.34.5 ; used for USERMOD_FOUR_LINE_DISPLAY -> need newer version with bugfixes for arduino-esp32 v2.0.4 (Wire inititialization) ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU claws/BH1750 @^1.2.0 ; used for USERMOD_BH1750 -build_flags_all = +build_flags_XL = -D USERMOD_BATTERY ;; enable Battery usermod -D USERMOD_BATTERY_USE_LIPO ;; use new "decharging curve" for LiPo cells -D USERMOD_BH1750 @@ -810,7 +862,7 @@ build_flags_all = -D USERMOD_VL53L0X_GESTURES -D WLED_ENABLE_PIXART -lib_deps_all = +lib_deps_XL = claws/BH1750 @^1.2.0 ; used for USERMOD_BH1750 ; adafruit/Adafruit BMP280 Library @ 2.1.0 ;; experimental for usermod USERMOD_SENSORSTOMQTT ; adafruit/Adafruit CCS811 Library @ 1.0.4 ;; experimental for usermod USERMOD_SENSORSTOMQTT @@ -824,54 +876,52 @@ lib_deps_all = ; base entries (without WLED_RELEASE_NAME) ; common defaults for all MM environments -[esp32_4MB_min_base] +[esp32_4MB_S_base] board = esp32dev platform = ${esp32.platform} upload_speed = 460800 ; or 921600 platform_packages = ${esp32.platform_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp32} ${common_mm.build_flags_min} -lib_deps = ${esp32.lib_deps} ${common_mm.lib_deps_min} +build_flags = ${common.build_flags_esp32} ${common_mm.build_flags_S} +lib_deps = ${esp32.lib_deps} ${common_mm.lib_deps_S} board_build.partitions = ${esp32.default_partitions} board_build.f_flash = 80000000L ; use full 80MHz speed for flash (default = 40Mhz) board_build.flash_mode = dio ; (dio = dual i/o; more compatible than qio = quad i/o) -; monitor_filters = esp32_exception_decoder ; used to show crash details ;common default for all max environments -[esp32_4MB_max_base] -extends = esp32_4MB_min_base -build_flags = ${esp32_4MB_min_base.build_flags} ${common_mm.build_flags_max} -lib_deps = ${esp32_4MB_min_base.lib_deps} ${common_mm.lib_deps_max} -board_build.partitions = ${esp32_4MB_min_base.board_build.partitions} +[esp32_4MB_M_base] +extends = esp32_4MB_S_base +build_flags = ${esp32_4MB_S_base.build_flags} ${common_mm.build_flags_M} +lib_deps = ${esp32_4MB_S_base.lib_deps} ${common_mm.lib_deps_M} ; board_build.partitions = tools/WLED_ESP32-wrover_4MB.csv -[esp32_4MB_all_base] -extends = esp32_4MB_max_base -build_flags = ${esp32_4MB_max_base.build_flags} ${common_mm.build_flags_all} -lib_deps = ${esp32_4MB_max_base.lib_deps} ${common_mm.lib_deps_all} +[esp32_4MB_XL_base] +extends = esp32_4MB_M_base +build_flags = ${esp32_4MB_M_base.build_flags} ${common_mm.build_flags_XL} +lib_deps = ${esp32_4MB_M_base.lib_deps} ${common_mm.lib_deps_XL} ; board_build.partitions = tools/WLED_ESP32-wrover_4MB.csv ;common default for all V4 min environments -[esp32_4MB_V4_min_base] +[esp32_4MB_V4_S_base] board = esp32dev upload_speed = 460800 ; or 921600 platform = ${esp32.platformV4} platform_packages = ${esp32.platformV4_packages} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${common_mm.build_flags_min} +build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${common_mm.build_flags_S} -Wno-misleading-indentation -Wno-format-truncation -lib_deps = ${esp32.lib_depsV4} ${common_mm.lib_deps_min} +lib_deps = ${esp32.lib_depsV4} ${common_mm.lib_deps_S} board_build.partitions = ${esp32.default_partitions} board_build.f_flash = 80000000L ; use full 80MHz speed for flash (default = 40Mhz) board_build.flash_mode = dio ; (dio = dual i/o; more compatible than qio = quad i/o) ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ; monitor_filters = esp32_exception_decoder ; used to show crash details -[esp32_4MB_V4_max_base] -extends = esp32_4MB_V4_min_base -build_flags = ${esp32_4MB_V4_min_base.build_flags} ${common_mm.build_flags_max} -lib_deps = ${esp32_4MB_V4_min_base.lib_deps} ${common_mm.lib_deps_max} -board_build.partitions = ${esp32_4MB_V4_min_base.board_build.partitions} +[esp32_4MB_V4_M_base] +extends = esp32_4MB_V4_S_base +build_flags = ${esp32_4MB_V4_S_base.build_flags} ${common_mm.build_flags_M} +lib_deps = ${esp32_4MB_V4_S_base.lib_deps} ${common_mm.lib_deps_V4_M} +board_build.partitions = ${esp32_4MB_V4_S_base.board_build.partitions} ;board_build.flash_mode = qio ; (dio = dual i/o; more compatible than qio = quad i/o) [Shield_ICS4343x] @@ -884,14 +934,29 @@ build_flags = -D SR_DMTYPE=5 -D I2S_SDPIN=32 -D I2S_WSPIN=15 -D I2S_CKPIN=-1 ; for I2S PDM microphone -D SR_SQUELCH=3 -D SR_GAIN=75 -D SR_FREQ_PROF=7 ; SPM1423 specific -[Shield_LineIn] +[Athom_PDMmic] build_flags = - -D SR_DMTYPE=4 -D MCLK_PIN=0 -D I2S_SDPIN=25 -D I2S_WSPIN=15 -D I2S_CKPIN=14 ; for audio Line-In shield - -D SR_SQUELCH=2 -D SR_GAIN=40 -D SR_FREQ_PROF=1 ; CS5343 Line-In specific + -D SR_DMTYPE=51 -D I2S_SDPIN=32 -D I2S_WSPIN=15 -D I2S_CKPIN=-1 ; for I2S PDM microphone Legacy mode! + -D SR_SQUELCH=10 -D SR_GAIN=40 -D SR_FREQ_PROF=7 ; SPM1423 specific -[Board_ESP32_16MB] ; ESP32 with 16MB Flash -board = esp32_16MB -board_build.partitions = tools/WLED_ESP32_16MB.csv +[Shield_LineIn] +build_unflags = + -D BTNPIN=17 ;; remove - its in conflict with on-shield rotary + -D ENCODER_SW_PIN=5 ;; remove - its in conflict with on-shield rotary + -D BTNPIN=0 ;; remove - its in conflict with MCLK pin +build_flags = + -D BTNPIN=-1 + -D SR_DMTYPE=4 -D MCLK_PIN=0 -D I2S_SDPIN=26 -D I2S_WSPIN=25 -D I2S_CKPIN=27 ; for audio Line-In shield, final version + -D SR_LINE_DETECT=34 ; line-in plug insert detection sensor (future support) + -D SR_SQUELCH=8 -D SR_GAIN=40 -D SR_FREQ_PROF=1 ; CS5343 Line-In specific + -D ENCODER_DT_PIN=35 -D ENCODER_CLK_PIN=39 -D ENCODER_SW_PIN=17 ; on-shield rotary encoder + +[Debug_Flags] +build_flags = + -D WLED_DEBUG ; lots of generic debug messages + -D SR_DEBUG ; some extra debug messages from audioreactive + ; -D MIC_LOGGER ; for sound input monitoring & debugging (use arduino serial plotter) + ; NetDebug moved to build_flags_M ; end of base entries @@ -899,55 +964,94 @@ board_build.partitions = tools/WLED_ESP32_16MB.csv ; bin entries (with WLED_RELEASE_NAME) -[env:esp32_4MB_min] -extends = esp32_4MB_min_base -build_flags = ${esp32_4MB_min_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_min - ; RAM: [== ] 24.1% (used 78900 bytes from 327680 bytes) - ; Flash: [======== ] 83.7% (used 1315729 bytes from 1572864 bytes) +[env:esp32_4MB_S] +extends = esp32_4MB_S_base +build_flags = ${esp32_4MB_S_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_S +; RAM: [== ] 24.1% (used 78988 bytes from 327680 bytes) +; Flash: [========= ] 85.7% (used 1348593 bytes from 1572864 bytes) WLEDMM: Earlier 83.7 -[env:esp32_4MB_max] -extends = esp32_4MB_max_base -build_flags = ${esp32_4MB_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_max - ; RAM: [== ] 24.4% (used 79804 bytes from 327680 bytes) - ; Flash: [========= ] 88.7% (used 1394813 bytes from 1572864 bytes) +[env:esp32_4MB_M] +extends = esp32_4MB_M_base +build_flags = ${esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_M +; RAM: [== ] 24.4% (used 79956 bytes from 327680 bytes) +; Flash: [========= ] 91.1% (used 1432245 bytes from 1572864 bytes) WLEDMM: earlier 88.7 -[env:esp32_4MB_all] -extends = esp32_4MB_all_base -build_flags = ${esp32_4MB_all_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_all - ; RAM: [== ] 24.4% (used 79804 bytes from 327680 bytes) - ; Flash: [========= ] 88.7% (used 1394813 bytes from 1572864 bytes) +[env:esp32_4MB_XL] +extends = esp32_4MB_XL_base +build_flags = ${esp32_4MB_XL_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_XL +; RAM: [== ] 24.4% (used 80060 bytes from 327680 bytes) +; Flash: [==========] 95.3% (used 1499037 bytes from 1572864 bytes) -[env:esp32_16MB_max] -extends = esp32_4MB_max_base -build_flags = ${esp32_4MB_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_16MB_max -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:esp32_16MB_M] +extends = esp32_4MB_M_base +build_flags = ${esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_16MB_M +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.4% (used 79916 bytes from 327680 bytes) ; Flash: [======= ] 67.0% (used 1405701 bytes from 2097152 bytes) ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation -[env:esp32_16MB_all] -extends = esp32_4MB_all_base -build_flags = ${esp32_4MB_all_base.build_flags} - -D WLED_RELEASE_NAME=esp32_16MB_all -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:esp32_4MB_M_debug] +extends = esp32_4MB_M_base +build_unflags = ${common.build_unflags} + -D CORE_DEBUG_LEVEL=0 +build_flags = ${esp32_4MB_M_base.build_flags} + ${Debug_Flags.build_flags} + -D CORE_DEBUG_LEVEL=2 ;; 2=warning + -D WLED_RELEASE_NAME=esp32_4MB_M_debug +monitor_filters = esp32_exception_decoder +; RAM: [== ] 24.5% (used 80292 bytes from 327680 bytes) +; Flash: [========= ] 94.5% (used 1487113 bytes from 1572864 bytes) + +[env:esp32_16MB_M_debug] +extends = esp32_4MB_M_base +build_unflags = ${common.build_unflags} + -D CORE_DEBUG_LEVEL=0 +build_flags = ${esp32_4MB_M_base.build_flags} + ${Debug_Flags.build_flags} + -D CORE_DEBUG_LEVEL=2 ;; 2=warning + -D WLED_RELEASE_NAME=esp32_16MB_M_debug +monitor_filters = esp32_exception_decoder +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem +; RAM: [== ] 24.5% (used 80292 bytes from 327680 bytes) +; Flash: [======= ] 70.9% (used 1487129 bytes from 2097152 bytes) + +[env:esp32_16MB_XL] +extends = esp32_4MB_XL_base +build_flags = ${esp32_4MB_XL_base.build_flags} + -D WLED_RELEASE_NAME=esp32_16MB_XL +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.4% (used 79916 bytes from 327680 bytes) ; Flash: [======= ] 67.0% (used 1405701 bytes from 2097152 bytes) ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation -[env:esp8266_4MB_min] +[env:esp32_16MB_M_eth] +extends = esp32_4MB_M_base +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem +board = esp32_16MB-poe ;; needed for ethernet boards (selects "esp32-poe" as variant) +build_flags = ${esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_16MB_M_eth ; This will be included in the firmware.bin filename + -D WLED_USE_ETHERNET +; RAM: [== ] 24.5% (used 80348 bytes from 327680 bytes) +; Flash: [======= ] 69.4% (used 1455233 bytes from 2097152 bytes) + +[env:esp8266_4MB_S] extends = env:d1_mini upload_speed = 460800 ;115200 board_build.f_cpu = 160000000L ;; we want 160Mhz (default = 80Mhz) build_flags = ${common.build_flags_esp8266} - -D WLED_RELEASE_NAME=esp8266_4MB_min + -D WLED_RELEASE_NAME=esp8266_4MB_S -D WLED_DISABLE_ALEXA - -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC ; -D WLED_DISABLE_2D ; -UWLED_USE_MY_CONFIG @@ -956,19 +1060,18 @@ build_flags = ${common.build_flags_esp8266} ; RAM: [====== ] 59.3% (used 48608 bytes from 81920 bytes) ; Flash: [======== ] 77.0% (used 804176 bytes from 1044464 bytes) -[env:esp8266_4MB_max] +[env:esp8266_4MB_M] extends = env:d1_mini upload_speed = 460800 ;115200 board_build.f_cpu = 160000000L ;; we want 160Mhz (default = 80Mhz) build_flags = ${common.build_flags_esp8266} - -D WLED_RELEASE_NAME=esp8266_4MB_max + -D WLED_RELEASE_NAME=esp8266_4MB_M -D WLED_MAX_USERMODS=5 ; default only 4-6 -D WLED_DISABLE_ALEXA - -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_LOXONE ; -D USERMOD_AUDIOREACTIVE - ; -D USERMOD_CUSTOMEFFECTS ; to be done + ; -D USERMOD_ARTIFX ; to be done ; -UWLED_USE_MY_CONFIG -D USERMOD_PIRSWITCH -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) @@ -992,7 +1095,6 @@ extends = env:d1_mini board_build.filesystem = littlefs build_flags = ${common.build_flags_esp8266} -D WLED_RELEASE_NAME=ESP8266 -D WLED_DISABLE_ALEXA - -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC -D WLED_DISABLE_LOXONE -D WLED_DISABLE_AUDIO ;WLEDMM not used anywhere @@ -1016,7 +1118,7 @@ lib_deps = ${esp8266.lib_deps} olikraus/U8g2 # @~2.33.15 Wire ; WLEDMM needed? -[env:esp8266pro_16MB_min] +[env:esp8266pro_16MB_S] extends = env:d1_mini board = d1_mini_pro ;; "D1 mini pro": ESP8266EX, 160MHz, 80KB RAM, 16MB Flash board_build.f_cpu = 160000000L ;; we want 160Mhz (default = 80Mhz) @@ -1027,31 +1129,66 @@ board_build.ldscript = ${common.ldscript_16m14m} ;; 16MB flash, use 14MB for Lit upload_speed = 460800 ;115200 build_flags = ${common.build_flags_esp8266} - -D WLED_RELEASE_NAME=esp8266pro_16MB_min + -D WLED_RELEASE_NAME=esp8266pro_16MB_S -D WLED_WATCHDOG_TIMEOUT=0 -D WLED_DISABLE_ALEXA - -D WLED_DISABLE_BLYNK -D WLED_DISABLE_HUESYNC ; -D WLED_DEBUG ; -D WLED_DISABLE_2D ; -D USERMOD_AUDIOREACTIVE - ; -D USERMOD_CUSTOMEFFECTS ; to be done + ; -D USERMOD_ARTIFX ; to be done ; -UWLED_USE_MY_CONFIG monitor_filters = esp8266_exception_decoder ; RAM: [====== ] 59.3% (used 48616 bytes from 81920 bytes) ; Flash: [======== ] 77.0% (used 804236 bytes from 1044464 bytes) -[env:esp01_1MB_min] +[env:esp8266pro_16MB_M] +extends = env:d1_mini +board = d1_mini_pro ;; "D1 mini pro": ESP8266EX, 160MHz, 80KB RAM, 16MB Flash +board_build.f_cpu = 160000000L ;; we want 160Mhz (default = 80Mhz) +;board_build.f_flash = 80000000L ;; for 80Mhz flash speed, in case your chip can handle it (default = 40Mhz) +board_build.flash_mode = qio ;; quad IO - fastest speed, in case your chip can handle it. +;;board_build.flash_mode = dout ;; use if your esp8266 becomes unstable with "qio" +board_build.ldscript = ${common.ldscript_16m14m} ;; 16MB flash, use 14MB for LittleFS + +upload_speed = 460800 ;115200 +build_flags = ${common.build_flags_esp8266} + -D WLED_RELEASE_NAME=esp8266pro_16MB_M + -D WLED_MAX_USERMODS=5 ; default only 4-6 + -D WLED_DISABLE_ALEXA + -D WLED_DISABLE_HUESYNC + -D WLED_DISABLE_LOXONE + ; -D USERMOD_AUDIOREACTIVE + ; -D USERMOD_ARTIFX ; to be done + -D USERMOD_PIRSWITCH + -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) + -D USERMOD_MULTI_RELAY + -D USE_ALT_DISPLAY ; new versions of USERMOD_FOUR_LINE_DISPLAY and USERMOD_ROTARY_ENCODER_UI + -D USERMOD_FOUR_LINE_DISPLAY + -D USERMOD_MPU6050_IMU ; gyro/accelero for USERMOD_GAMES (ONLY WORKS IF USERMOD_FOUR_LINE_DISPLAY NOT INCLUDED - I2C SHARING BUG) + -D USERMOD_GAMES ; WLEDMM usermod + ; -D WLED_DEBUG +monitor_filters = esp8266_exception_decoder +lib_deps = ${esp8266.lib_deps} + OneWire@~2.3.5 ; used for USERMOD_FOUR_LINE_DISPLAY and USERMOD_DALLASTEMPERATURE + olikraus/U8g2 @ ^2.28.8 ; used for USERMOD_FOUR_LINE_DISPLAY + ElectronicCats/MPU6050 @ 0.6.0 ; used for USERMOD_MPU6050_IMU +; RAM: [====== ] 62.4% (used 51092 bytes from 81920 bytes) +; Flash: [========= ] 85.5% (used 893056 bytes from 1044464 bytes) + +[env:esp01_1MB_S] board = esp01_1m platform = ${common.platform_wled_default} platform_packages = ${common.platform_packages} board_build.ldscript = ${common.ldscript_1m128k} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA -D WLED_DISABLE_BLYNK - -D WLED_RELEASE_NAME=esp01_1MB_min +build_flags = ${common.build_flags_esp8266} -D WLED_DISABLE_OTA + -D WLED_RELEASE_NAME=esp01_1MB_S -D WLED_DISABLE_ALEXA -D WLED_DISABLE_HUESYNC lib_deps = ${esp8266.lib_deps} +; RAM: [====== ] 59.5% (used 48748 bytes from 81920 bytes) +; Flash: [========= ] 90.7% (used 809992 bytes from 892912 bytes) # ------------------------------------------------------------------------------ @@ -1061,10 +1198,10 @@ lib_deps = ${esp8266.lib_deps} ;; When upgrading to the new framework, it might be necessary to first do a chip erase (make sure you have a backup of cfg.json and presets.json) ; compiled with ESP-IDF 4.4.1 -[env:esp32_4MB_V4_min] -extends = esp32_4MB_V4_min_base -build_flags = ${esp32_4MB_V4_min_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_V4_min +[env:esp32_4MB_V4_S] +extends = esp32_4MB_V4_S_base +build_flags = ${esp32_4MB_V4_S_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_V4_S -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup -D WLED_DISABLE_LOXONE @@ -1080,10 +1217,10 @@ build_flags = ${esp32_4MB_V4_min_base.build_flags} ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ; compiled with ESP-IDF 4.4.1 -[env:esp32_4MB_V4_max] -extends = esp32_4MB_V4_max_base -build_flags = ${esp32_4MB_V4_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_V4_max +[env:esp32_4MB_V4_M] +extends = esp32_4MB_V4_M_base +build_flags = ${esp32_4MB_V4_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_V4_M -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup ; RAM: [== ] 24.8% (used 81316 bytes from 327680 bytes) @@ -1098,44 +1235,85 @@ build_flags = ${esp32_4MB_V4_max_base.build_flags} ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ; compiled with ESP-IDF 4.4.1 -[env:esp32_16MB_V4_max] -extends = esp32_4MB_V4_max_base -build_flags = ${esp32_4MB_V4_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_16MB_V4_max +[env:esp32_16MB_V4_M] +extends = esp32_4MB_V4_M_base +build_flags = ${esp32_4MB_V4_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_16MB_V4_M -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.8% (used 81316 bytes from 327680 bytes) ; Flash: [======= ] 72.9% (used 1528253 bytes from 2097152 bytes) -;; experimental environment for boards with PSRAM (needs ESP-IDF 4.4.1). -[env:esp32_4MB_PSRAM_max] -extends = esp32_4MB_V4_max_base -board = lolin_d32_pro -;board = esp32cam -build_flags = ${esp32_4MB_V4_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_4MB_PSRAM_max +[env:esp32_16MB_V4_M_debug] +extends = esp32_4MB_V4_M_base +build_unflags = ${common.build_unflags} + -D CORE_DEBUG_LEVEL=0 +build_flags = ${esp32_4MB_V4_M_base.build_flags} + ${Debug_Flags.build_flags} + -D CORE_DEBUG_LEVEL=4 ;; 0=none, 1=error, 2=warning, 3=info, 4=debug, 5=verbose + -D WLED_RELEASE_NAME=esp32_16MB_V4_M_debug -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup - -D WLED_USE_PSRAM - ; RAM: [== ] 24.8% (used 81424 bytes from 327680 bytes) - ; Flash: [==========] 99.8% (used 1570457 bytes from 1572864 bytes) - ; 99.8% !!!! - -D WLED_DISABLE_LOXONE ; FLASH 1272 bytes - -D WLED_DISABLE_ALEXA ; RAM 116 bytes; FLASH 13524 bytes - -D WLED_DISABLE_MQTT ; RAM 216 bytes; FLASH 16496 bytes - -D WLED_DISABLE_HUESYNC ;RAM 122 bytes; FLASH 6308 bytes - ; RAM: [== ] 24.7% (used 80948 bytes from 327680 bytes) - ; Flash: [==========] 97.4% (used 1532485 bytes from 1572864 bytes) - ;-D WLED_DISABLE_INFRARED ;RAM 136 bytes; FLASH 24492 bytes +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem +monitor_filters = esp32_exception_decoder +; RAM: [=== ] 25.0% (used 82008 bytes from 327680 bytes) +; Flash: [======== ] 78.1% (used 1638193 bytes from 2097152 bytes) WLEDMM: Earlier 76.9 + +;; experimental environment for boards with PSRAM (needs ESP-IDF 4.4.1). +[env:esp32_4MB_PSRAM_S] +extends = esp32_4MB_V4_S_base +board = lolin_d32_pro +;board = esp32cam +build_flags = ${esp32_4MB_V4_S_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_PSRAM_S + -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET + -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup + -D WLED_USE_PSRAM + -D WLED_DISABLE_LOXONE ; FLASH 1272 bytes + -D WLED_DISABLE_HUESYNC ; RAM 122 bytes; FLASH 6308 bytes + -D WLED_DISABLE_ALEXA ; RAM 116 bytes; FLASH 13524 bytes + -D WLED_DISABLE_MQTT ; RAM 216 bytes; FLASH 16496 bytes + -D WLED_DISABLE_INFRARED ;RAM 136 bytes; FLASH 24492 bytes ewowi: disabled to stay below 100% ; -D WLED_ENABLE_DMX ; -D WLED_DEBUG ; -D SR_DEBUG ; -D MIC_LOGGER +lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation +;; RAM: [== ] 24.3% (used 79524 bytes from 327680 bytes) +;; Flash: [========= ] 93.2% (used 1466389 bytes from 1572864 bytes) -[env:esp32S3_8MB_max] -extends = esp32_4MB_V4_max_base +;; PSRAM build env that only leaves 300Kb for filesystem (instead of 1MB), but adds 300kB for program space +[env:esp32_4MB_PSRAM_M] +extends = esp32_4MB_V4_M_base +board = lolin_d32_pro +;board = esp32cam +board_build.partitions = tools/WLED_ESP32_4MB_256KB_FS.csv ;; 1.8MB firmware, 256KB filesystem (esptool erase_flash needed when changing from "standard WLED" partitions) +build_flags = ${esp32_4MB_V4_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_4MB_PSRAM_M + -D WLED_WATCHDOG_TIMEOUT=0 #-D WLED_DISABLE_BROWNOUT_DET + -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup + -D WLED_USE_PSRAM + -D WLED_DISABLE_LOXONE ;; FLASH 1272 bytes + -D WLED_DISABLE_HUESYNC ;; RAM 122 bytes; FLASH 6308 bytes + -D WLED_DISABLE_ALEXA ;; RAM 116 bytes; FLASH 13524 bytes + ; -D WLED_DISABLE_MQTT ;; RAM 216 bytes; FLASH 16496 bytes + ; -D WLED_DISABLE_INFRARED ;;RAM 136 bytes; FLASH 24492 bytes + ; -D WLED_ENABLE_DMX + ; -D WLED_DEBUG + ; -D SR_DEBUG + ; -D MIC_LOGGER +;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation +;monitor_filters = esp32_exception_decoder +;; RAM: [== ] 24.9% (used 81484 bytes from 327680 bytes) +;; Flash: [======== ] 84.6% (used 1607857 bytes from 1900544 bytes) + +[env:esp32S3_8MB_M] +extends = esp32_4MB_V4_M_base board = esp32-s3-devkitc-1 build_unflags = -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) @@ -1144,12 +1322,14 @@ build_unflags = -D USERMOD_ROTARY_ENCODER_UI ;; see above -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) -build_flags = ${esp32_4MB_V4_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32S3_8MB_max - -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=0 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_USB_DFU_ON_BOOT=0 - -D WLED_WATCHDOG_TIMEOUT=0 +build_flags = ${common.build_flags} ${esp32s3.build_flags} -Wno-misleading-indentation -Wno-format-truncation + ${common_mm.build_flags_S} ${common_mm.build_flags_M} + -D WLED_RELEASE_NAME=esp32S3_8MB_M + -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=0 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_USB_DFU_ON_BOOT=0 ;; for Serial-to-USB chip + ;; -D ARDUINO_USB_MODE=1 -D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MSC_ON_BOOT=0 -D ARDUINO_USB_DFU_ON_BOOT=0 ;; for Hardware-CDC USB mode + ;; -D WLED_DISABLE_ADALIGHT ;; disables serial protocols when using CDC USB (Serial RX will receive junk commands when RX pin is unconnected, unless its pulled down by resistor) + -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 ; -D U8X8_HAVE_2ND_HW_I2C ;; experimental - tells U8g2 lib that a second HW I2C unit exists - -D WLED_DISABLE_BLYNK ;; seems that BLYNK does not work on -S3 -D WLED_DISABLE_LOXONE ; FLASH 1272 bytes -D WLED_DISABLE_ALEXA ; RAM 116 bytes; FLASH 13524 bytes ; -D WLED_DISABLE_MQTT ; RAM 216 bytes; FLASH 16496 bytes @@ -1173,43 +1353,45 @@ build_flags = ${esp32_4MB_V4_max_base.build_flags} ; -D WLED_DEBUG ; -D SR_DEBUG ; -D MIC_LOGGER -lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_min} ${common_mm.lib_deps_V4_max} +lib_deps = ${esp32s3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation board_build.partitions = tools/WLED_ESP32_8MB.csv board_build.flash_mode = qio ; RAM: [== ] 24.7% (used 80856 bytes from 327680 bytes) ; Flash: [======= ] 66.9% (used 1403489 bytes from 2097152 bytes) -;; MM max for Adafruit QT Py ESP32-S2 -> 4MB flash, PSRAM, and tinyUF2 bootloader +;; MM for Adafruit QT Py ESP32-S2 -> 4MB flash, PSRAM, and tinyUF2 bootloader ;; to ewowi - i'll optimize this entry later, as a few things can be inherited for sure. To softhack: sure ;-) -[env:esp32s2_tinyUF2_PSRAM_max] -extends = esp32_4MB_V4_min_base +[env:esp32s2_tinyUF2_PSRAM_S] +extends = esp32_4MB_V4_S_base platform = ${esp32.platformV4} platform_packages = ${esp32.platformV4_packages} board = adafruit_qtpy_esp32s2 -board_build.partitions = tools/partitions-4MB-tinyuf2_spiffs.csv ;; this is needed for tinyUF2 bootloader! +board_build.partitions = tools/partitions-4MB_spiffs-tinyuf2.csv ;; this is needed for tinyUF2 bootloader! Filename has to end in "tinyuf2.csv" board_build.f_flash = 80000000L board_build.flash_mode = qio upload_speed = 256000 ;; 921600 build_unflags = ${common.build_unflags} - -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S2 (autodetect broken?) - -D USE_ALT_DISPLAY ;; four line display seems to have problems with I2C - it hangs during usermod setup - -D USERMOD_FOUR_LINE_DISPLAY ;; see above - -D USERMOD_ROTARY_ENCODER_UI ;; see above + -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) -build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${esp32s2.build_flags} +build_flags = ${common.build_flags} ${esp32s2.build_flags} + ; ${Debug_Flags.build_flags} ;ewowi: enabling debug causes Error: The program size (1463330 bytes) is greater than maximum allowed (1441792 bytes) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 - ${common_mm.build_flags_min} ${common_mm.build_flags_max} + ${common_mm.build_flags_S} -Wno-misleading-indentation -Wno-format-truncation - -D WLED_RELEASE_NAME=esp32S2_4MB_UF2_max + -D WLED_RELEASE_NAME=esp32S2_4MB_UF2_S -DARDUINO_USB_CDC_ON_BOOT=1 ;; mandatory, otherwise USB does not work!! + -D WLED_DISABLE_ADALIGHT ;; disables serial protocols when using CDC USB (Serial RX will receive junk commands, unless its pulled down by resistor) -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -D SERVERNAME='"WLED-S2"' -D WLED_USE_PSRAM - -D WLED_DISABLE_INFRARED ;; save flash space - -D WLED_DISABLE_ALEXA ;; save flash space + -D WLED_DISABLE_LOXONE ;; FLASH 1272 bytes + -D WLED_DISABLE_HUESYNC ;; RAM 122 bytes; FLASH 6308 bytes + -D WLED_DISABLE_ALEXA ;; RAM 116 bytes; FLASH 13524 bytes + ; -D WLED_DISABLE_MQTT ;; RAM 216 bytes; FLASH 16496 bytes + -D WLED_DISABLE_INFRARED ;; RAM 136 bytes; FLASH 24492 bytes -D LEDPIN=39 ;; onboard neopixel LED. Attach your own LEDs to GPIO 7 or GPIO 6 -D BTNPIN=0 ;-D RLYPIN=6 @@ -1219,33 +1401,72 @@ build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${esp32s2.build_flags -D HW_PIN_CLOCKSPI=36 -D HW_PIN_MISOSPI=37 -D AUDIOPIN=-1 - -D SR_DMTYPE=1 - -D I2S_SDPIN=9 - -D I2S_WSPIN=8 - -D I2S_CKPIN=17 - -D MCLK_PIN=18 + -D SR_DMTYPE=1 -D I2S_SDPIN=9 -D I2S_WSPIN=8 -D I2S_CKPIN=17 -D MCLK_PIN=18 ;-D STATUSLED=-1 -D WLED_USE_MY_CONFIG - ; -D WLED_DEBUG_HOST='"192.168.xxx.xxx"' ;; to send debug messages over network to host 192.168.x.y - FQDN is also possible - ; -D WLED_DEBUG_NET_PORT=1768 ;; port for network debugging. default = 7868 - ; -D WLED_DEBUG - ; -D SR_DEBUG - ; -D MIC_LOGGER -lib_deps = ${env.lib_deps} ${esp32s2.lib_deps} ${common_mm.lib_deps_min} ${common_mm.lib_deps_V4_max} -lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation +lib_deps = ${env.lib_deps} ${esp32s2.lib_deps} ${common_mm.lib_deps_S} +lib_ignore = + IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + OneWire ; not needed as we don't include USERMOD_DALLASTEMPERATURE monitor_filters = esp32_exception_decoder -; RAM: [=== ] 25.6% (used 83796 bytes from 327680 bytes) -; Flash: [==========] 97.7% (used 1408626 bytes from 1441792 bytes) +; RAM: [=== ] 25.1% (used 82348 bytes from 327680 bytes) +; Flash: [==========] 95.8% (used 1381742 bytes from 1441792 bytes) -;; MM max environment for ESP32-C3 -> 4MB flash, no PSRAM -;; to ewowi - i'll optimize this entry later ;-) really, I mean -[env:esp32c3dev_4MB_max] -extends = esp32_4MB_V4_min_base +;; MM environment for generic ESP32-S2, with PSRAM, 4MB flash (300kB filesystem to have more program space) +[env:esp32s2_PSRAM_M] +extends = esp32_4MB_V4_M_base +platform = espressif32@~5.2.0 ;; more stable on -S2 than 5.1.1 +platform_packages = + +board = lolin_s2_mini +board_build.partitions = tools/WLED_ESP32_4MB_256KB_FS.csv ;; 1.8MB firmware, 256KB filesystem (esptool erase_flash needed when changing from "standard WLED" partitions) +board_build.flash_mode = dio +upload_speed = 256000 ;; 921600 +build_unflags = ${common.build_unflags} + -DARDUINO_USB_CDC_ON_BOOT=1 + -D USERMOD_DALLASTEMPERATURE ;; disabled because it hangs during usermod setup on -S3 (autodetect broken?) + -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) +build_flags = ${common.build_flags} ${esp32s2.build_flags} + ${Debug_Flags.build_flags} + -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 + ${common_mm.build_flags_S} ${common_mm.build_flags_M} + -Wno-misleading-indentation -Wno-format-truncation + -D WLED_RELEASE_NAME=esp32S2_4MB_M + -DARDUINO_USB_CDC_ON_BOOT=0 + -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 + -D WLED_DISABLE_ADALIGHT ;; disables serial protocols, as the board onl has CDC USB + -D WLED_USE_PSRAM -DBOARD_HAS_PSRAM + -D WLED_DISABLE_INFRARED ;; save flash space + -D WLED_DISABLE_ALEXA ;; save flash space + -D WLED_DISABLE_HUESYNC ;; save flash space + -D WLED_DISABLE_LOXONE ;; save flash space + -D LEDPIN=16 + -D BTNPIN=-1 -D RLYPIN=-1 -D IRPIN=-1 + -D HW_PIN_SCL=40 -D HW_PIN_SDA=41 + -D HW_PIN_MOSISPI=35 ;WLEDMM renamed from HW_PIN_DATASPI + -D HW_PIN_CLOCKSPI=36 + -D HW_PIN_MISOSPI=37 + -D AUDIOPIN=-1 + -D SR_DMTYPE=1 -D I2S_SDPIN=9 -D I2S_WSPIN=8 -D I2S_CKPIN=17 -D MCLK_PIN=18 + -D WLED_USE_MY_CONFIG +lib_deps = ${env.lib_deps} ${esp32s2.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} +lib_ignore = + IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + OneWire ; not needed as we don't include USERMOD_DALLASTEMPERATURE +monitor_filters = esp32_exception_decoder +; RAM: [== ] 22.9% (used 75068 bytes from 327680 bytes) +; Flash: [======== ] 78.3% (used 1487802 bytes from 1900544 bytes) + +;; MM environment for ESP32-C3 -> 4MB flash, no PSRAM +[env:esp32c3dev_4MB_M] +extends = esp32_4MB_V4_S_base ;platform = ${esp32.platformV4} ;platform_packages = ${esp32.platformV4_packages} platform = espressif32@~5.2.0 ;; alternative platform, might help in case you experience bootloops due to corrupted flash filesystem platform_packages = board = esp32-c3-devkitm-1 +;board_build.partitions = tools/WLED_ESP32_4MB_256KB_FS.csv ;; 1.8MB firmware, 256KB filesystem (esptool erase_flash needed when changing from "standard WLED" partitions) +;board_build.partitions = tools/WLED_ESP32_2MB_noOTA.csv ;; use this for boards with 2MB flash (like some Ai-Thinker ESP32-C3-12F models) upload_speed = 256000 ;; 921600 build_unflags = ${common.build_unflags} @@ -1255,12 +1476,14 @@ build_unflags = ${common.build_unflags} -D USERMOD_ROTARY_ENCODER_UI ;; see above -D WLED_ENABLE_DMX ;; disabled because it does not work with ESP-IDF 4.4.x (buggy driver in SparkFunDMX) -build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${esp32c3.build_flags} +build_flags = ${common.build_flags} ${esp32c3.build_flags} + ; -D WLED_DISABLE_OTA ;; OTA is not possible for boards with 2MB flash only (like some Ai-Thinker ESP32-C3-12F models) -D WLED_WATCHDOG_TIMEOUT=0 -D CONFIG_ASYNC_TCP_USE_WDT=0 - ${common_mm.build_flags_min} ${common_mm.build_flags_max} + ${common_mm.build_flags_S} ${common_mm.build_flags_M} -Wno-misleading-indentation -Wno-format-truncation - -D WLED_RELEASE_NAME=esp32c3dev_4MB_max + -D WLED_RELEASE_NAME=esp32c3dev_4MB_M ; -DARDUINO_USB_CDC_ON_BOOT=1 ;; enable CDC USB -> needed for debugging over serial USB + ; -D WLED_DISABLE_ADALIGHT ;; to disable serial protocols when using CDC USB (Serial RX will receive junk commands, unless its pulled down by resistor) -DARDUINO_USB_CDC_ON_BOOT=0 ;; disable CDC USB -D SERVERNAME='"WLED-C3"' ;-D WLEDMM_WIFI_POWERON_HACK ;; use this _only_ if your device is not able to make a WiFI connection! @@ -1275,17 +1498,19 @@ build_flags = ${common.build_flags} ${esp32.build_flagsV4} ${esp32c3.build_flags -D SR_DMTYPE=1 -D I2S_SDPIN=5 -D I2S_WSPIN=6 -D I2S_CKPIN=4 -D MCLK_PIN=7 -D WLED_USE_MY_CONFIG -lib_deps = ${env.lib_deps} ${esp32c3.lib_deps} ${common_mm.lib_deps_min} ${common_mm.lib_deps_V4_max} +lib_deps = ${env.lib_deps} ${esp32c3.lib_deps} ${common_mm.lib_deps_S} ${common_mm.lib_deps_V4_M} ;lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ;monitor_filters = esp32_exception_decoder +; RAM: [== ] 23.1% (used 75620 bytes from 327680 bytes) +; Flash: [==========] 95.8% (used 1506216 bytes from 1572864 bytes) # ------------------------------------------------------------------------------ # custom board environments # ------------------------------------------------------------------------------ -[wemos_shield_esp32_4MB_max_base] -extends = esp32_4MB_max_base -build_flags = ${esp32_4MB_max_base.build_flags} +[wemos_shield_esp32_4MB_M_base] +extends = esp32_4MB_M_base +build_flags = ${esp32_4MB_M_base.build_flags} -D ABL_MILLIAMPS_DEFAULT=9500 ; Wemos max 10A -D LEDPIN=16 -D RLYPIN=19 @@ -1296,115 +1521,141 @@ build_flags = ${esp32_4MB_max_base.build_flags} -D FLD_PIN_SCL=-1 -D FLD_PIN_SDA=-1 ; use global! -D HW_PIN_SCL=22 -D HW_PIN_SDA=21 -D HW_PIN_CLOCKSPI=-1 -D HW_PIN_MOSISPI=-1 -D HW_PIN_MISOSPI=-1 ; WLEDMM: is now also default but just to show we didn't agree on wemos pins for spi yet - -D ENCODER_DT_PIN=35 -D ENCODER_CLK_PIN=5 -D ENCODER_SW_PIN=39 ;WLEDMM spec by @SERG74: use 35 and 39 instead of 18 and 19 (conflicts) + -D ENCODER_DT_PIN=35 -D ENCODER_CLK_PIN=39 -D ENCODER_SW_PIN=5 ; WLEDMM spec by @SERG74: use 35 and 39 instead of 18 and 19 (conflicts) -D PIR_SENSOR_PIN=-1 -D PWM_PIN=-1 ; -D WLED_USE_MY_CONFIG -[wemos_shield_esp32_4MB_all_base] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${common_mm.build_flags_all} -lib_deps = ${wemos_shield_esp32_4MB_max_base.lib_deps} ${common_mm.lib_deps_all} +[wemos_shield_esp32_4MB_XL_base] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${common_mm.build_flags_XL} +lib_deps = ${wemos_shield_esp32_4MB_M_base.lib_deps} ${common_mm.lib_deps_XL} -[env:wemos_shield_esp32_4MB_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_max +[env:wemos_shield_esp32_4MB_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_M ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -[env:wemos_shield_esp32_4MB_ICS4343x_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_ICS4343x.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_ICS4343x_max +[env:wemos_shield_esp32_4MB_ICS4343x_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_ICS4343x.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_ICS4343x_M ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -[env:wemos_shield_esp32_4MB_SPM1423_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_SPM1423.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_SPM1423_max +[env:wemos_shield_esp32_4MB_SPM1423_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_SPM1423.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_SPM1423_M ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -[env:wemos_shield_esp32_4MB_LineIn_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_LineIn.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_LineIn_max +[env:wemos_shield_esp32_4MB_LineIn_M] +extends = wemos_shield_esp32_4MB_M_base +build_unflags = ${common.build_unflags} ${Shield_LineIn.build_unflags} +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_LineIn.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_4MB_LineIn_M -[env:wemos_shield_esp32_16MB_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_max -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_M +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem +;board_build.flash_mode = qio ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [======= ] 66.4% (used 1393421 bytes from 2097152 bytes) -[env:wemos_shield_esp32_16MB_ICS4343x_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_ICS4343x.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_ICS4343x_max -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_ICS4343x_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_ICS4343x.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_ICS4343x_M +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -[env:wemos_shield_esp32_16MB_ICS4343x_all] -extends = wemos_shield_esp32_4MB_all_base -build_flags = ${wemos_shield_esp32_4MB_all_base.build_flags} ${Shield_ICS4343x.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_ICS4343x_all -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_ICS4343x_XL] +extends = wemos_shield_esp32_4MB_XL_base +build_flags = ${wemos_shield_esp32_4MB_XL_base.build_flags} ${Shield_ICS4343x.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_ICS4343x_XL +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.4% (used 80044 bytes from 327680 bytes) ; Flash: [======= ] 67.9% (used 1424185 bytes from 2097152 bytes) -monitor_filters = esp32_exception_decoder ; used to show crash details -[env:wemos_shield_esp32_16MB_SPM1423_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_SPM1423.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_SPM1423_max -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_SPM1423_M] +extends = wemos_shield_esp32_4MB_M_base +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_SPM1423.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_SPM1423_M +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -monitor_filters = esp32_exception_decoder ; used to show crash details -[env:wemos_shield_esp32_16MB_SPM1423_all] -extends = wemos_shield_esp32_4MB_all_base -build_flags = ${wemos_shield_esp32_4MB_all_base.build_flags} ${Shield_SPM1423.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_SPM1423_all -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_SPM1423_XL] +extends = wemos_shield_esp32_4MB_XL_base +build_flags = ${wemos_shield_esp32_4MB_XL_base.build_flags} ${Shield_SPM1423.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_SPM1423_XL +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem ; RAM: [== ] 24.4% (used 79820 bytes from 327680 bytes) ; Flash: [========= ] 88.6% (used 1393421 bytes from 1572864 bytes) -monitor_filters = esp32_exception_decoder ; used to show crash details -[env:wemos_shield_esp32_16MB_LineIn_max] -extends = wemos_shield_esp32_4MB_max_base -build_flags = ${wemos_shield_esp32_4MB_max_base.build_flags} ${Shield_LineIn.build_flags} - -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_LineIn_max -board = ${Board_ESP32_16MB.board} -board_build.partitions = ${Board_ESP32_16MB.board_build.partitions} +[env:wemos_shield_esp32_16MB_LineIn_M] +extends = wemos_shield_esp32_4MB_M_base +build_unflags = ${common.build_unflags} ${Shield_LineIn.build_unflags} +build_flags = ${wemos_shield_esp32_4MB_M_base.build_flags} ${Shield_LineIn.build_flags} + -D WLED_RELEASE_NAME=wemos_shield_esp32_16MB_LineIn_M +board = esp32_16MB +board_build.partitions = tools/WLED_ESP32_16MB.csv ;; WLED standard for 16MB flash: 2MB firmware, 12 MB filesystem +;board_build.partitions = tools/WLED_ESP32_16MB_9MB_FS.csv ;; WLED extended for 16MB flash: 3.2MB firmware, 9 MB filesystem + +[env:athom_music_esp32_4MB_M] +extends = esp32_4MB_M_base +build_flags = ${esp32_4MB_M_base.build_flags} ${Athom_PDMmic.build_flags} + -D WLED_AP_SSID_UNIQUE + -D WLED_RELEASE_NAME=athom_music_esp32_4MB_M + -D ABL_MILLIAMPS_DEFAULT=14500 ; max 15A + -D WLED_DISABLE_MQTT -D WLED_DISABLE_LOXONE + -D WLED_DISABLE_ADALIGHT ;to get 4ld working + -D BTNPIN=0 -D RLYPIN=2 -D IRPIN=25 -D IRTYPE=9 -D LEDPIN=18 -D + -D AUDIOPIN=-1 + ; -D TEMPERATURE_PIN=23 + -D FLD_PIN_SCL=-1 -D FLD_PIN_SDA=-1 ; use global! + -D HW_PIN_SCL=3 -D HW_PIN_SDA=1 ;4ld uses rx and tx + -D HW_PIN_CLOCKSPI=-1 -D HW_PIN_MOSISPI=-1 -D HW_PIN_MISOSPI=-1 ; WLEDMM: is now also default but just to show we didn't agree on wemos pins for spi yet + ; -D ENCODER_DT_PIN=35 -D ENCODER_CLK_PIN=39 -D ENCODER_SW_PIN=5 ; WLEDMM spec by @SERG74: use 35 and 39 instead of 18 and 19 (conflicts) + ; -D PIR_SENSOR_PIN=-1 + ; -D PWM_PIN=-1 + ; -D WLED_USE_MY_CONFIG ; ESP32 WLED pico board with builtin ICS-43432 microphpone -[env:esp32_pico_4MB_max] -extends = esp32_4MB_max_base +[env:esp32_pico_4MB_M] +extends = esp32_4MB_M_base board = pico32 -build_flags = ${esp32_4MB_max_base.build_flags} - -D WLED_RELEASE_NAME=esp32_pico_4MB_max +board_build.flash_mode = dout ;; (dout = dual out; more compatible than qio = quad i/o) +upload_speed = 256000 ;; or 115200 ;; or 460800 ; or 921600 (slower speeds are better when flashing without a soldered connection) + +build_flags = ${esp32_4MB_M_base.build_flags} + -D WLED_RELEASE_NAME=esp32_pico_4MB_M -D WLED_DISABLE_BROWNOUT_DET -D SERVERNAME='"WLED-pico32"' ; -D WLED_WATCHDOG_TIMEOUT=60 + -D WLED_DISABLE_ADALIGHT ;; WLEDMM this board does not have a serial-to-USB chip. Better to disable serial protocols, to avoid crashes (see upstream #3128) ; -D WLED_DEBUG ; -D SR_DEBUG -D LEDPIN=2 - -D RLYPIN=-1 - -D BTNPIN=-1 - -D IRPIN=-1 + -D RLYPIN=-1 -D BTNPIN=-1 -D IRPIN=-1 -D HW_PIN_SCL=22 -D HW_PIN_SDA=21 -D SR_DMTYPE=1 -D I2S_SDPIN=25 -D I2S_WSPIN=15 -D I2S_CKPIN=14 - -D SR_SQUELCH=5 -D SR_GAIN=30 -D SR_FREQ_PROF=5 ; ICS-43434 specific + -D SR_SQUELCH=5 -D SR_GAIN=30 -D SR_FREQ_PROF=5 ; ICS-4343x specific ; -D MCLK_PIN=0 -D SR_ENABLE_DEFAULT ;; enable at first start - no need to manually set "enable", then reboot ; -D WLED_USE_MY_CONFIG @@ -1414,5 +1665,36 @@ build_flags = ${esp32_4MB_max_base.build_flags} ; -D WLED_DISABLE_MQTT ; -D WLED_DISABLE_INFRARED ; -D WLED_ENABLE_DMX -; RAM: [== ] 24.4% (used 79804 bytes from 327680 bytes) -; Flash: [========= ] 88.6% (used 1394241 bytes from 1572864 bytes) +; RAM: [== ] 24.4% (used 79812 bytes from 327680 bytes) +; Flash: [========= ] 90.4% (used 1422581 bytes from 1572864 bytes) + + +;; experimental +;; PICO environment with ESP-IDF v4.4.1 / arduino-esp32 v2.0.4 +[env:esp32_pico_4MB_V4_S] +extends = esp32_4MB_V4_S_base +board = pico32 +;platform = espressif32@~5.2.0 ;; alternative platform, might help in case you experience bootloops due to corrupted flash filesystem +;platform_packages = +upload_speed = 256000 ;; or 115200 ;; or 460800 ; or 921600 (slower speeds are better when flashing without a soldered connection) + +build_flags = ${esp32_4MB_V4_S_base.build_flags} + -D ARDUINO_USB_CDC_ON_BOOT=0 ; needed for arduino-esp32 >=2.0.4; avoids errors on startup + -D WLED_RELEASE_NAME=esp32_pico_4MB_V4_S + -D WLED_DISABLE_BROWNOUT_DET + -D SERVERNAME='"WLED-pico32-V4"' + -D WLED_WATCHDOG_TIMEOUT=0 + -D WLED_DISABLE_ADALIGHT ;; WLEDMM this board does not have a serial-to-USB chip. Better to disable serial protocols, to avoid crashes (see upstream #3128) + ; -D WLED_WATCHDOG_TIMEOUT=60 + ; -D WLED_DEBUG + ; -D SR_DEBUG + -D LEDPIN=2 + -D RLYPIN=-1 -D BTNPIN=-1 -D IRPIN=-1 + -D HW_PIN_SCL=22 -D HW_PIN_SDA=21 + -D SR_DMTYPE=1 -D I2S_SDPIN=25 -D I2S_WSPIN=15 -D I2S_CKPIN=14 + -D SR_SQUELCH=5 -D SR_GAIN=30 -D SR_FREQ_PROF=5 ; ICS-4343x specific + ; -D MCLK_PIN=0 + -D SR_ENABLE_DEFAULT ;; enable audioreactive at first start - no need to manually set "enable", then reboot + ; -D WLED_USE_MY_CONFIG +; RAM: [== ] 24.5% (used 80436 bytes from 327680 bytes) +; Flash: [========= ] 93.9% (used 1476341 bytes from 1572864 bytes) diff --git a/platformio_override.ini.sample b/platformio_override.ini.sample index cd81c517..d6ea5d96 100644 --- a/platformio_override.ini.sample +++ b/platformio_override.ini.sample @@ -26,7 +26,6 @@ build_flags = ${common.build_flags_esp8266} ; disable specific features ; -D WLED_DISABLE_OTA ; -D WLED_DISABLE_ALEXA -; -D WLED_DISABLE_BLYNK ; -D WLED_DISABLE_HUESYNC ; -D WLED_DISABLE_INFRARED ; -D WLED_DISABLE_WEBSOCKETS diff --git a/readme.md b/readme.md index 15aaf885..fc5660c4 100644 --- a/readme.md +++ b/readme.md @@ -34,8 +34,7 @@ A fast and feature-rich implementation of an ESP8266/ESP32 webserver to control ## 💡 Supported light control interfaces - WLED app for [Android](https://play.google.com/store/apps/details?id=com.aircoookie.WLED) and [iOS](https://apps.apple.com/us/app/wled/id1475695033) - JSON and HTTP request APIs -- MQTT -- Blynk IoT +- MQTT - E1.31, Art-Net, DDP and TPM2.net - [diyHue](https://github.com/diyhue/diyHue) (Wled is supported by diyHue, including Hue Sync Entertainment under udp. Thanks to [Gregory Mallios](https://github.com/gmallios)) - [Hyperion](https://github.com/hyperion-project/hyperion.ng) diff --git a/tools/SoundReactive_ESP32_16MB.csv b/tools/SoundReactive_ESP32_16MB.csv deleted file mode 100644 index e547a824..00000000 --- a/tools/SoundReactive_ESP32_16MB.csv +++ /dev/null @@ -1,6 +0,0 @@ -# Name, Type, SubType, Offsaet, Size, Flags -nvs, data, nvs, 0x9000, 0x5000, -otadata, data, ota, 0xe000, 0x2000, -app0, app, ota_0, 0x10000, 0x200000, -app1, app, ota_1, 0x210000, 0x200000, -spiffs, data, spiffs, 0x410000, 0x7f0000, diff --git a/tools/WLED_ESP32_16MB_9MB_FS.csv b/tools/WLED_ESP32_16MB_9MB_FS.csv new file mode 100644 index 00000000..9ecac04e --- /dev/null +++ b/tools/WLED_ESP32_16MB_9MB_FS.csv @@ -0,0 +1,8 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x300000, +app1, app, ota_1, 0x310000,0x300000, +spiffs, data, spiffs, 0x610000,0x9E0000, +coredump, data, coredump,0xFF0000,0x10000, +# to create/use ffat, see https://github.com/marcmerlin/esp32_fatfsimage \ No newline at end of file diff --git a/tools/WLED_ESP32_2MB_noOTA.csv b/tools/WLED_ESP32_2MB_noOTA.csv new file mode 100644 index 00000000..7a1cf15f --- /dev/null +++ b/tools/WLED_ESP32_2MB_noOTA.csv @@ -0,0 +1,5 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 20K, +otadata, data, ota, 0xe000, 8K, +app0, app, ota_0, 0x10000, 1536K, +spiffs, data, spiffs, 0x190000, 384K, diff --git a/tools/WLED_ESP32_4MB_256KB_FS.csv b/tools/WLED_ESP32_4MB_256KB_FS.csv new file mode 100644 index 00000000..f9e1be26 --- /dev/null +++ b/tools/WLED_ESP32_4MB_256KB_FS.csv @@ -0,0 +1,7 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x5000, +otadata, data, ota, 0xe000, 0x2000, +app0, app, ota_0, 0x10000, 0x1D0000, +app1, app, ota_1, 0x1E0000,0x1D0000, +spiffs, data, spiffs, 0x3B0000,0x40000, +coredump, data, coredump,0x3F0000,0x10000, \ No newline at end of file diff --git a/tools/partitions-4MB-tinyuf2_spiffs.csv b/tools/partitions-4MB_spiffs-tinyuf2.csv similarity index 100% rename from tools/partitions-4MB-tinyuf2_spiffs.csv rename to tools/partitions-4MB_spiffs-tinyuf2.csv diff --git a/usermods/BH1750_v2/usermod_bh1750.h b/usermods/BH1750_v2/usermod_bh1750.h index 360c28db..77a57efb 100644 --- a/usermods/BH1750_v2/usermod_bh1750.h +++ b/usermods/BH1750_v2/usermod_bh1750.h @@ -2,13 +2,12 @@ // #warning **** Included USERMOD_BH1750 **** #ifndef WLED_ENABLE_MQTT -#error "This user mod requires MQTT to be enabled." +#warning "This user mod expects MQTT to be enabled." #endif #pragma once #include // WLEDMM: make sure that I2C drivers have the "right" Wire Object -#include #include "wled.h" #include @@ -20,7 +19,8 @@ // the min frequency to check photoresistor, 500 ms #ifndef USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL -#define USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL 500 +//#define USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL 500 +#define USERMOD_BH1750_MIN_MEASUREMENT_INTERVAL 2500 // WLEDMM this makes more sense #endif // how many seconds after boot to take first measurement, 10 seconds @@ -30,7 +30,7 @@ // only report if differance grater than offset value #ifndef USERMOD_BH1750_OFFSET_VALUE -#define USERMOD_BH1750_OFFSET_VALUE 1 +#define USERMOD_BH1750_OFFSET_VALUE 2 // WLEDMM this makes more sense #endif class Usermod_BH1750 : public Usermod @@ -91,14 +91,17 @@ private: // set up Home Assistant discovery entries void _mqttInitialize() { +#ifdef WLED_ENABLED_MQTT mqttLuminanceTopic = String(mqttDeviceTopic) + F("/brightness"); if (HomeAssistantDiscovery) _createMqttSensor(F("Brightness"), mqttLuminanceTopic, F("Illuminance"), F(" lx")); +#endif } // Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop. void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement) { +#ifdef WLED_ENABLED_MQTT String t = String(F("homeassistant/sensor/")) + mqttClientID + F("/") + name + F("/config"); StaticJsonDocument<600> doc; @@ -125,11 +128,13 @@ private: DEBUG_PRINTLN(temp); mqtt->publish(t.c_str(), 0, true, temp.c_str()); +#endif } public: void setup() { +#if 0 bool HW_Pins_Used = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda); // note whether architecture-based hardware SCL/SDA pins used PinOwner po = PinOwner::UM_BH1750; // defaults to being pinowner for SCL/SDA pins if (HW_Pins_Used) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins @@ -147,13 +152,18 @@ public: #else //Wire.begin(); // WLEDMM - i2c pins on 8266 are fixed. #endif +#endif + if (!enabled) return; if (!pinManager.joinWire()) { // WLEDMM - this allocates global I2C pins, then starts Wire - if not started previously sensorFound = false; - enabled = false; + //enabled = false; + USER_PRINTLN(F("BH1750: failed to join I2C bus.")); return; } sensorFound = lightMeter.begin(); + if (sensorFound) { USER_PRINTLN(F("BH1750 sensor found.")); } + else{ USER_PRINTLN(F("BH1750 sensor not found.")); } initDone = true; } @@ -226,7 +236,7 @@ public: lux_json.add(F(" sec until read")); return; } else { - lux_json.add(lastLux); + lux_json.add(round(lastLux)); // WLEDMM lux_json.add(F(" lx")); } } @@ -295,6 +305,7 @@ public: } else { DEBUG_PRINTLN(F(" config (re)loaded.")); // changing parameters from settings page +#if 0 bool pinsChanged = false; for (byte i=0; i<2; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; } // check if any pins changed if (pinsChanged) { //if pins changed, deallocate old pins and allocate new ones @@ -305,6 +316,9 @@ public: for (byte i=0; i<2; i++) ioPin[i] = newPin[i]; setup(); } +#else + if (enabled && !sensorFound) setup(); +#endif // use "return !top["newestParameter"].isNull();" when updating Usermod with new features return !top[F("pin")].isNull(); } diff --git a/usermods/EXAMPLE_v2/usermod_v2_example.h b/usermods/EXAMPLE_v2/usermod_v2_example.h index 43648b58..ba2ffc4e 100644 --- a/usermods/EXAMPLE_v2/usermod_v2_example.h +++ b/usermods/EXAMPLE_v2/usermod_v2_example.h @@ -20,15 +20,32 @@ * 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp */ +/* WLEDMM: move usermod variables to class. + +As of March 2023 this is work in progress, more variables will be moved in the future. +See Example v2, Temperature, MPU6050 and weather and fastled (rest to be done) as examples which has been converted using the steps below: + +Part 1 +- remove bool enabled = false/true (now default false) +- remove static const char _name[] and _enabled[] +- add constructor which calls superclass (temp?): XXXUsermod(const char *name, bool enabled):Usermod(name, enabled) {} +- replace _enabled with "enabled" +- remove const char PROGMEM init for _name[] and _enabled[] +Part 2 +- Remove bool initDone = false; +- addToConfig: replace createNestedObject with Usermod::addToConfig(root); JsonObject top = root[FPSTR(_name)]; +- readFromConfig: replace !top.isNull and enabled with bool configComplete = Usermod::readFromConfig(root);JsonObject top = root[FPSTR(_name)]; +Part 3 +- remove unsigned long lastTime = 0; //WLEDMM + +*/ + //class name. Use something descriptive and leave the ": public Usermod" part :) class MyExampleUsermod : public Usermod { private: // Private class members. You can declare variables and functions only accessible to your usermod here - bool enabled = false; - bool initDone = false; - unsigned long lastTime = 0; // set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer) bool testBool = false; @@ -41,28 +58,25 @@ class MyExampleUsermod : public Usermod { long testLong; int8_t testPins[2]; - // string that are used multiple time (this will save some flash memory) - static const char _name[]; - static const char _enabled[]; - - // any private methods should go here (non-inline methosd should be defined out of class) void publishMqtt(const char* state, bool retain = false); // example for publishing MQTT message public: + MyExampleUsermod(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM + // non WLED related methods, may be used for data exchange between usermods (non-inline methods should be defined out of class) /** * Enable/Disable the usermod */ - inline void enable(bool enable) { enabled = enable; } + // inline void enable(bool enable) { enabled = enable; } /** * Get usermod enabled/disabled state */ - inline bool isEnabled() { return enabled; } + // inline bool isEnabled() { return enabled; } // in such case add the following to another usermod: // in private vars: @@ -222,8 +236,8 @@ class MyExampleUsermod : public Usermod { */ void addToConfig(JsonObject& root) { - JsonObject top = root.createNestedObject(FPSTR(_name)); - top[FPSTR(_enabled)] = enabled; + Usermod::addToConfig(root); JsonObject top = root[FPSTR(_name)]; //WLEDMM + //save these vars persistently whenever settings are saved top["great"] = userVar0; top["testBool"] = testBool; @@ -258,9 +272,7 @@ class MyExampleUsermod : public Usermod { // 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[FPSTR(_name)]; - - bool configComplete = !top.isNull(); + bool configComplete = Usermod::readFromConfig(root);JsonObject top = root[FPSTR(_name)]; //WLEDMM configComplete &= getJsonValue(top["great"], userVar0); configComplete &= getJsonValue(top["testBool"], testBool); @@ -386,8 +398,6 @@ class MyExampleUsermod : public Usermod { // add more strings here to reduce flash memory usage -const char MyExampleUsermod::_name[] PROGMEM = "ExampleUsermod"; -const char MyExampleUsermod::_enabled[] PROGMEM = "enabled"; // implementation of non-inline member methods diff --git a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h index 099c59da..288edb32 100644 --- a/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h +++ b/usermods/PIR_sensor_switch/usermod_PIR_sensor_switch.h @@ -371,6 +371,7 @@ public: * onStateChanged() is used to detect WLED state change */ void onStateChange(uint8_t mode) { + if (!initDone) return; DEBUG_PRINT(F("PIR: offTimerStart=")); DEBUG_PRINTLN(offTimerStart); if (PIRtriggered && offTimerStart) { // checking PIRtriggered and offTimerStart will prevent cancellation upon On trigger diff --git a/usermods/RTC/usermod_rtc.h b/usermods/RTC/usermod_rtc.h index f25e16e3..08b92ef1 100644 --- a/usermods/RTC/usermod_rtc.h +++ b/usermods/RTC/usermod_rtc.h @@ -6,6 +6,8 @@ #include "src/dependencies/time/DS1307RTC.h" #include "wled.h" +#define RTC_DELTA 2 // only modify RTC time if delta exceeds this number of seconds + //Connect DS1307 to standard I2C pins (ESP32: GPIO 21 (SDA)/GPIO 22 (SCL)) class RTCUsermod : public Usermod { @@ -36,6 +38,7 @@ class RTCUsermod : public Usermod { if (rtcTime) { toki.setTime(rtcTime,TOKI_NO_MS_ACCURACY,TOKI_TS_RTC); updateLocalTime(); + USER_PRINTLN(F("Localtime updated from RTC.")); } else { if (!RTC.chipPresent()) disabled = true; //don't waste time if H/W error } @@ -45,7 +48,24 @@ class RTCUsermod : public Usermod { if (strip.isUpdating()) return; if (!disabled && toki.isTick()) { time_t t = toki.second(); - if (abs(t - RTC.get())> 2) RTC.set(t); //set RTC to NTP/UI-provided value - WLEDMM allow up to 3 sec deviation + + if (abs(t - RTC.get())> RTC_DELTA) { // WLEDMM only consider time diffs > 2 seconds + if ( (toki.getTimeSource() == TOKI_TS_NTP) + ||( (toki.getTimeSource() != TOKI_TS_NONE) && (toki.getTimeSource() != TOKI_TS_RTC) + && (toki.getTimeSource() != TOKI_TS_BAD) && (toki.getTimeSource() != TOKI_TS_UDP_SEC) && (toki.getTimeSource() != TOKI_TS_UDP))) + { // WLEMM update RTC if we have a reliable time source + RTC.set(t); //set RTC to NTP/UI-provided value - WLEDMM allow up to 3 sec deviation + USER_PRINTLN(F("RTC updated using localtime.")); + } else { + // WLEDMM if no reliable time -> update from RTC + time_t rtcTime = RTC.get(); + if (rtcTime) { + toki.setTime(rtcTime,TOKI_NO_MS_ACCURACY,TOKI_TS_RTC); + updateLocalTime(); + USER_PRINTLN(F("Localtime updated from RTC.")); + } + } + } } } diff --git a/usermods/Temperature/usermod_temperature.h b/usermods/Temperature/usermod_temperature.h index 153a502f..885f445e 100644 --- a/usermods/Temperature/usermod_temperature.h +++ b/usermods/Temperature/usermod_temperature.h @@ -21,7 +21,6 @@ class UsermodTemperature : public Usermod { private: - bool initDone = false; OneWire *oneWire; // GPIO pin used for sensor (with a default compile-time fallback) int8_t temperaturePin = TEMPERATURE_PIN; @@ -45,13 +44,9 @@ class UsermodTemperature : public Usermod { // temperature if flashed to a board without a sensor attached byte sensorFound; - bool enabled = true; - bool HApublished = false; // strings to reduce flash memory usage (used more than twice) - static const char _name[]; - static const char _enabled[]; static const char _readInterval[]; static const char _parasite[]; static const char _parasitePin[]; @@ -163,6 +158,7 @@ class UsermodTemperature : public Usermod { #endif public: + UsermodTemperature(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM: this shouldn't be necessary (passthrough of constructor), maybe because Usermod is an abstract class void setup() { int retries = 10; @@ -325,9 +321,10 @@ class UsermodTemperature : public Usermod { * addToConfig() (called from set.cpp) stores persistent properties to cfg.json */ void addToConfig(JsonObject &root) { + Usermod::addToConfig(root); + JsonObject top = root[FPSTR(_name)]; + // we add JSON object: {"Temperature": {"pin": 0, "degC": true}} - JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname - top[FPSTR(_enabled)] = enabled; top["pin"] = temperaturePin; // usermodparam top["degC"] = degC; // usermodparam top[FPSTR(_readInterval)] = readingInterval / 1000; @@ -342,17 +339,18 @@ class UsermodTemperature : public Usermod { * The function should return true if configuration was successfully loaded or false if there was no configuration. */ bool readFromConfig(JsonObject &root) { + bool configComplete = Usermod::readFromConfig(root); + JsonObject top = root[FPSTR(_name)]; + // we look for JSON object: {"Temperature": {"pin": 0, "degC": true}} int8_t newTemperaturePin = temperaturePin; DEBUG_PRINT(FPSTR(_name)); - JsonObject top = root[FPSTR(_name)]; if (top.isNull()) { DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); return false; } - enabled = top[FPSTR(_enabled)] | enabled; newTemperaturePin = top["pin"] | newTemperaturePin; degC = top["degC"] | degC; readingInterval = top[FPSTR(_readInterval)] | readingInterval/1000; @@ -398,8 +396,6 @@ class UsermodTemperature : public Usermod { }; // strings to reduce flash memory usage (used more than twice) -const char UsermodTemperature::_name[] PROGMEM = "Temperature"; -const char UsermodTemperature::_enabled[] PROGMEM = "enabled"; const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s"; const char UsermodTemperature::_parasite[] PROGMEM = "parasite-pwr"; const char UsermodTemperature::_parasitePin[] PROGMEM = "parasite-pwr-pin"; diff --git a/usermods/customeffects/arti.h b/usermods/artifx/arti.h similarity index 100% rename from usermods/customeffects/arti.h rename to usermods/artifx/arti.h diff --git a/usermods/customeffects/arti_wled.h b/usermods/artifx/arti_wled.h similarity index 100% rename from usermods/customeffects/arti_wled.h rename to usermods/artifx/arti_wled.h diff --git a/usermods/customeffects/customeffects.css b/usermods/artifx/artifx.css similarity index 100% rename from usermods/customeffects/customeffects.css rename to usermods/artifx/artifx.css diff --git a/usermods/customeffects/customeffects.js b/usermods/artifx/artifx.js similarity index 78% rename from usermods/customeffects/customeffects.js rename to usermods/artifx/artifx.js index 1011ebe0..a56c84e2 100644 --- a/usermods/customeffects/customeffects.js +++ b/usermods/artifx/artifx.js @@ -93,22 +93,23 @@ function populateCEEditor(name, segID) { fetchAndExecute((loc?`http://${locip}`:'.') + "/", name + ".wled", function(text) { - var cn=`Custom Effects Editor
+ var cn=`ARTI-FX Editor
${name}.wled


- +
- -
- -
+ +
+ +

Compile and Run Log

Run log > 3 seconds is send to Serial Ouput.
- 🥚 - 🥚`; + 🥚 + 🥚 + 🥚`; d.getElementById('kceEditor').innerHTML = cn; @@ -122,14 +123,15 @@ function populateCEEditor(name, segID) }); } -function downloadCEFile(url, name) { - if (url == "CE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/CustomEffects/wled/"; +function downloadGHFile(url, name, save=false, warn=false) { //Githubfile + if (url == "CE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/ARTIFX/wled/"; if (url == "HBB") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Base%20pack/"; if (url == "HBE") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Presets/HB_PresetPack210808_32x32_16seg/Effects%20pack/"; + if (url == "LM") url = "https://raw.githubusercontent.com/MoonModules/WLED-Effects/master/Ledmaps/"; fetchAndExecute(url, name, function(text) { - if (name == "wledv033.json" || name == "presets.json") { - if (!confirm('Are you sure to download/overwrite ' + name + '?')) + if (save) { + if (warn && !confirm('Are you sure to download/overwrite ' + name + '?')) return; uploadFileWithText("/" + name, text); } @@ -140,7 +142,7 @@ function downloadCEFile(url, name) { } }, function(error){ showToast(error); - console.log(error); + console.log(url + name,error); }); return; @@ -165,7 +167,7 @@ function downloadCEFile(url, name) { function loadCETemplate(name) { var ceProgramArea = d.getElementById("ceProgramArea"); ceProgramArea.value = `/* - Custom Effects Template + ARTIFX Template */ program ${name} { diff --git a/usermods/customeffects/usermod_v2_customeffects.h b/usermods/artifx/usermod_v2_artifx.h similarity index 91% rename from usermods/customeffects/usermod_v2_customeffects.h rename to usermods/artifx/usermod_v2_artifx.h index a4317808..eb919073 100644 --- a/usermods/customeffects/usermod_v2_customeffects.h +++ b/usermods/artifx/usermod_v2_artifx.h @@ -1,6 +1,6 @@ /* - @title Usermod Custom Effects (CE) - @file usermod_v2_customeffects.h + @title Usermod ARTIFX (AF) + @file usermod_v2_artifx.h @date 20220818 @author Ewoud Wijma @Copyright (c) 2023 Ewoud Wijma @@ -17,7 +17,7 @@ ARTI * arti; //effect function -uint16_t mode_customEffect(void) { +uint16_t mode_ARTIFX(void) { //tbd: move statics to SEGMENT.data static bool succesful; static bool notEnoughHeap; @@ -99,9 +99,9 @@ uint16_t mode_customEffect(void) { return FRAMETIME; } -static const char _data_FX_MODE_CUSTOMEFFECT[] PROGMEM = "⚙️ Custom Effect ☾@Speed,Intensity,Custom 1, Custom 2, Custom 3;!;!;1;mp12=0"; +static const char _data_FX_MODE_ARTIFX[] PROGMEM = "⚙️ ARTI-FX ☾@Speed,Intensity,Custom 1, Custom 2, Custom 3;!;!;1;mp12=0"; -class CustomEffectsUserMod : public Usermod { +class ARTIFXUserMod : public Usermod { private: // strings to reduce flash memory usage (used more than twice) static const char _name[]; //usermod name @@ -115,7 +115,7 @@ class CustomEffectsUserMod : public Usermod { void setup() { if (!initDone) - strip.addEffect(FX_MODE_CUSTOMEFFECT, &mode_customEffect, _data_FX_MODE_CUSTOMEFFECT); + strip.addEffect(FX_MODE_ARTIFX, &mode_ARTIFX, _data_FX_MODE_ARTIFX); initDone = true; enabled = true; } @@ -200,9 +200,9 @@ class CustomEffectsUserMod : public Usermod { */ uint16_t getId() { - return USERMOD_ID_CUSTOMEFFECTS; + return USERMOD_ID_ARTIFX; } }; // strings to reduce flash memory usage (used more than twice) -const char CustomEffectsUserMod::_name[] PROGMEM = "CustomEffects"; +const char ARTIFXUserMod::_name[] PROGMEM = "ARTIFX"; diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index 3e22aa81..4fbb6b63 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -29,9 +29,9 @@ // #define SR_DEBUG // generic SR DEBUG messages #ifdef SR_DEBUG - #define DEBUGSR_PRINT(x) DEBUGOUT.print(x) - #define DEBUGSR_PRINTLN(x) DEBUGOUT.println(x) - #define DEBUGSR_PRINTF(x...) DEBUGOUT.printf(x) + #define DEBUGSR_PRINT(x) DEBUGOUT(x) + #define DEBUGSR_PRINTLN(x) DEBUGOUTLN(x) + #define DEBUGSR_PRINTF(x...) DEBUGOUTF(x) #else #define DEBUGSR_PRINT(x) #define DEBUGSR_PRINTLN(x) @@ -55,10 +55,10 @@ #endif #if defined(MIC_LOGGER) || defined(FFT_SAMPLING_LOG) - #define PLOT_PRINT(x) DEBUGOUT.print(x) - #define PLOT_PRINTLN(x) DEBUGOUT.println(x) - #define PLOT_PRINTF(x...) DEBUGOUT.printf(x) - #define PLOT_FLUSH() DEBUGOUT.flush() + #define PLOT_PRINT(x) DEBUGOUT(x) + #define PLOT_PRINTLN(x) DEBUGOUTLN(x) + #define PLOT_PRINTF(x...) DEBUGOUTF(x) + #define PLOT_FLUSH() DEBUGOUTFlush() #else #define PLOT_PRINT(x) #define PLOT_PRINTLN(x) @@ -123,6 +123,15 @@ static AudioSource *audioSource = nullptr; static volatile bool disableSoundProcessing = false; // if true, sound processing (FFT, filters, AGC) will be suspended. "volatile" as its shared between tasks. static bool useBandPassFilter = false; // if true, enables a bandpass filter 80Hz-16Khz to remove noise. Applies before FFT. +//WLEDMM add experimental settings +static uint8_t micLevelMethod = 0; // 0=old "floating" miclev, 1=new "freeze" mode, 2=fast freeze mode (mode 2 may not work for you) +#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) +static uint8_t averageByRMS = false; // false: use mean value, true: use RMS (root mean squared). use simpler method on slower MCUs. +#else +static uint8_t averageByRMS = true; // false: use mean value, true: use RMS (root mean squared). use better method on fast MCUs. +#endif +static uint8_t freqDist = 0; // 0=old 1=rightshift mode + // audioreactive variables shared with FFT task static float micDataReal = 0.0f; // MicIn data with full 24bit resolution - lowest 8bit after decimal point static float multAgc = 1.0f; // sample * multAgc = sampleAgc. Our AGC multiplier @@ -136,7 +145,7 @@ static float volumeSmth = 0.0f; // either sampleAvg or sampleAgc depending // peak detection static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay() -static uint8_t maxVol = 10; // Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated) +static uint8_t maxVol = 31; // (was 10) Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated) static uint8_t binNum = 8; // Used to select the bin for FFT based beat detection (deprecated) static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData static unsigned long timeOfPeak = 0; // time of last sample peak detection. @@ -182,7 +191,7 @@ static const float fftResultPink[MAX_PINK+1][NUM_GEQ_CHANNELS] = { { 12.0f, 6.60f, 2.60f, 1.15f, 1.35f, 2.05f, 2.85f, 2.50f, 2.85f, 3.30f, 2.25f, 4.35f, 3.80f, 3.75f, 6.50f, 9.00f}, // 4 IMNP441 - voice, or small speaker { 2.75f, 1.60f, 1.40f, 1.46f, 1.52f, 1.57f, 1.68f, 1.80f, 1.89f, 2.00f, 2.11f, 2.21f, 2.30f, 1.75f, 2.55f, 3.60f }, // 5 ICS-43434 datasheet response * pink noise - { 2.25f, 1.20f, 1.00f, 1.20f, 1.80f, 3.20f, 5.10f, 5.50f, 4.00f, 4.80f, 6.70f, 6.40f, 5.80f, 3.90f, 6.00f, 5.10f }, // 6 ICS-43434 - big speaker, strong bass + { 2.90f, 1.25f, 0.75f, 1.08f, 2.35f, 3.55f, 3.60f, 3.40f, 2.75f, 3.45f, 4.40f, 6.35f, 6.80f, 6.80f, 8.50f,10.64f }, // 6 ICS-43434 - big speaker, strong bass { 1.65f, 1.00f, 1.05f, 1.30f, 1.48f, 1.30f, 1.80f, 3.00f, 1.50f, 1.65f, 2.56f, 3.00f, 2.60f, 2.30f, 5.00f, 3.00f }, // 7 SPM1423 { 2.25f, 1.60f, 1.30f, 1.60f, 2.20f, 3.20f, 3.06f, 2.60f, 2.85f, 3.50f, 4.10f, 4.80f, 5.70f, 6.05f,10.50f,14.85f }, // 8 userdef #1 for ewowi (enhance median/high freqs) @@ -264,7 +273,8 @@ constexpr uint16_t samplesFFT = 512; // Samples in an FFT batch - Thi constexpr uint16_t samplesFFT_2 = 256; // meaningfull part of FFT results - only the "lower half" contains useful information. // the following are observed values, supported by a bit of "educated guessing" //#define FFT_DOWNSCALE 0.65f // 20kHz - downscaling factor for FFT results - "Flat-Top" window @20Khz, old freq channels -#define FFT_DOWNSCALE 0.46f // downscaling factor for FFT results - for "Flat-Top" window @22Khz, new freq channels +//#define FFT_DOWNSCALE 0.46f // downscaling factor for FFT results - for "Flat-Top" window @22Khz, new freq channels +#define FFT_DOWNSCALE 0.40f // downscaling factor for FFT results, RMS averaging #define LOG_256 5.54517744f // log(256) // These are the input and output vectors. Input vectors receive computed results from FFT. @@ -303,23 +313,28 @@ static float mapf(float x, float in_min, float in_max, float out_min, float out_ } // compute average of several FFT resut bins -#if 1 // linear average -static float fftAddAvg(int from, int to) { +// linear average +static float fftAddAvgLin(int from, int to) { float result = 0.0f; for (int i = from; i <= to; i++) { result += vReal[i]; } return result / float(to - from + 1); } -#else // RMS average -static float fftAddAvg(int from, int to) { +// RMS average +static float fftAddAvgRMS(int from, int to) { double result = 0.0; for (int i = from; i <= to; i++) { result += vReal[i] * vReal[i]; } return sqrtf(result / float(to - from + 1)); } -#endif + +static float fftAddAvg(int from, int to) { + if (from == to) return vReal[from]; // small optimization + if (averageByRMS) return fftAddAvgRMS(from, to); // use SMS + else return fftAddAvgLin(from, to); // use linear average +} #if defined(CONFIG_IDF_TARGET_ESP32C3) constexpr bool skipSecondFFT = true; @@ -512,35 +527,67 @@ void FFTcode(void * parameter) fftCalc[14] = fftAddAvg(147,194); // 2940 - 3900 fftCalc[15] = fftAddAvg(194,250); // 3880 - 5000 // avoid the last 5 bins, which are usually inaccurate #else - /* new mapping, optimized for 22050 Hz by softhack007 */ + //WLEDMM: different distributions + if (freqDist == 0) { + /* new mapping, optimized for 22050 Hz by softhack007 --- update: removed overlap */ // bins frequency range if (useBandPassFilter) { // skip frequencies below 100hz - fftCalc[ 0] = 0.8f * fftAddAvg(3,4); - fftCalc[ 1] = 0.9f * fftAddAvg(4,5); - fftCalc[ 2] = fftAddAvg(5,6); - fftCalc[ 3] = fftAddAvg(6,7); + fftCalc[ 0] = 0.8f * fftAddAvg(3,3); + fftCalc[ 1] = 0.9f * fftAddAvg(4,4); + fftCalc[ 2] = fftAddAvg(5,5); + fftCalc[ 3] = fftAddAvg(6,6); // don't use the last bins from 206 to 255. fftCalc[15] = fftAddAvg(165,205) * 0.75f; // 40 7106 - 8828 high -- with some damping } else { - fftCalc[ 0] = fftAddAvg(1,2); // 1 43 - 86 sub-bass - fftCalc[ 1] = fftAddAvg(2,3); // 1 86 - 129 bass - fftCalc[ 2] = fftAddAvg(3,5); // 2 129 - 216 bass - fftCalc[ 3] = fftAddAvg(5,7); // 2 216 - 301 bass + midrange + fftCalc[ 0] = fftAddAvg(1,1); // 1 43 - 86 sub-bass + fftCalc[ 1] = fftAddAvg(2,2); // 1 86 - 129 bass + fftCalc[ 2] = fftAddAvg(3,4); // 2 129 - 216 bass + fftCalc[ 3] = fftAddAvg(5,6); // 2 216 - 301 bass + midrange // don't use the last bins from 216 to 255. They are usually contaminated by aliasing (aka noise) fftCalc[15] = fftAddAvg(165,215) * 0.70f; // 50 7106 - 9259 high -- with some damping } - fftCalc[ 4] = fftAddAvg(7,10); // 3 301 - 430 midrange - fftCalc[ 5] = fftAddAvg(10,13); // 3 430 - 560 midrange - fftCalc[ 6] = fftAddAvg(13,19); // 5 560 - 818 midrange - fftCalc[ 7] = fftAddAvg(19,26); // 7 818 - 1120 midrange -- 1Khz should always be the center ! - fftCalc[ 8] = fftAddAvg(26,33); // 7 1120 - 1421 midrange - fftCalc[ 9] = fftAddAvg(33,44); // 9 1421 - 1895 midrange - fftCalc[10] = fftAddAvg(44,56); // 12 1895 - 2412 midrange + high mid - fftCalc[11] = fftAddAvg(56,70); // 14 2412 - 3015 high mid - fftCalc[12] = fftAddAvg(70,86); // 16 3015 - 3704 high mid - fftCalc[13] = fftAddAvg(86,104); // 18 3704 - 4479 high mid - fftCalc[14] = fftAddAvg(104,165) * 0.88f; // 61 4479 - 7106 high mid + high -- with slight damping + fftCalc[ 4] = fftAddAvg(7,9); // 3 301 - 430 midrange + fftCalc[ 5] = fftAddAvg(10,12); // 3 430 - 560 midrange + fftCalc[ 6] = fftAddAvg(13,18); // 5 560 - 818 midrange + fftCalc[ 7] = fftAddAvg(19,25); // 7 818 - 1120 midrange -- 1Khz should always be the center ! + fftCalc[ 8] = fftAddAvg(26,32); // 7 1120 - 1421 midrange + fftCalc[ 9] = fftAddAvg(33,43); // 9 1421 - 1895 midrange + fftCalc[10] = fftAddAvg(44,55); // 12 1895 - 2412 midrange + high mid + fftCalc[11] = fftAddAvg(56,69); // 14 2412 - 3015 high mid + fftCalc[12] = fftAddAvg(70,85); // 16 3015 - 3704 high mid + fftCalc[13] = fftAddAvg(86,103); // 18 3704 - 4479 high mid + fftCalc[14] = fftAddAvg(104,164) * 0.88f; // 61 4479 - 7106 high mid + high -- with slight damping + } + else if (freqDist == 1) { //WLEDMM: Rightshft: note ewowi: frequencies in comments are not correct + if (useBandPassFilter) { + // skip frequencies below 100hz + fftCalc[ 0] = 0.8f * fftAddAvg(1,1); + fftCalc[ 1] = 0.9f * fftAddAvg(2,2); + fftCalc[ 2] = fftAddAvg(3,3); + fftCalc[ 3] = fftAddAvg(4,4); + // don't use the last bins from 206 to 255. + fftCalc[15] = fftAddAvg(165,205) * 0.75f; // 40 7106 - 8828 high -- with some damping + } else { + fftCalc[ 0] = fftAddAvg(1,1); // 1 43 - 86 sub-bass + fftCalc[ 1] = fftAddAvg(2,2); // 1 86 - 129 bass + fftCalc[ 2] = fftAddAvg(3,3); // 2 129 - 216 bass + fftCalc[ 3] = fftAddAvg(4,4); // 2 216 - 301 bass + midrange + // don't use the last bins from 216 to 255. They are usually contaminated by aliasing (aka noise) + fftCalc[15] = fftAddAvg(165,215) * 0.70f; // 50 7106 - 9259 high -- with some damping + } + fftCalc[ 4] = fftAddAvg(5,6); // 3 301 - 430 midrange + fftCalc[ 5] = fftAddAvg(7,8); // 3 430 - 560 midrange + fftCalc[ 6] = fftAddAvg(9,10); // 5 560 - 818 midrange + fftCalc[ 7] = fftAddAvg(11,13); // 7 818 - 1120 midrange -- 1Khz should always be the center ! + fftCalc[ 8] = fftAddAvg(14,18); // 7 1120 - 1421 midrange + fftCalc[ 9] = fftAddAvg(19,25); // 9 1421 - 1895 midrange + fftCalc[10] = fftAddAvg(26,36); // 12 1895 - 2412 midrange + high mid + fftCalc[11] = fftAddAvg(37,45); // 14 2412 - 3015 high mid + fftCalc[12] = fftAddAvg(46,66); // 16 3015 - 3704 high mid + fftCalc[13] = fftAddAvg(67,97); // 18 3704 - 4479 high mid + fftCalc[14] = fftAddAvg(98,164) * 0.88f; // 61 4479 - 7106 high mid + high -- with slight damping + } #endif } else { // noise gate closed - just decay old values isFirstRun = false; @@ -861,7 +908,9 @@ class AudioReactive : public Usermod { static const char _name[]; static const char _enabled[]; static const char _inputLvl[]; +#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) static const char _analogmic[]; +#endif static const char _digitalmic[]; static const char UDP_SYNC_HEADER[]; static const char UDP_SYNC_HEADER_v1[]; @@ -1057,6 +1106,10 @@ class AudioReactive : public Usermod { const float weighting = 0.2f; // Exponential filter weighting. Will be adjustable in a future release. const float weighting2 = 0.073f; // Exponential filter weighting, for rising signal (a bit more robust against spikes) const int AGC_preset = (soundAgc > 0)? (soundAgc-1): 0; // make sure the _compiler_ knows this value will not change while we are inside the function + static bool isFrozen = false; + static bool haveSilence = true; + static unsigned long lastSoundTime = 0; // for delaying un-freeze + static unsigned long startuptime = 0; // "fast freeze" mode: do not interfere during first 12 seconds (filter startup time) #ifdef WLED_DISABLE_SOUND micIn = inoise8(millis(), millis()); // Simulated analog read @@ -1079,8 +1132,15 @@ class AudioReactive : public Usermod { #endif #endif - micLev += (micDataReal-micLev) / 12288.0f; - if(micIn < micLev) micLev = ((micLev * 31.0f) + micDataReal) / 32.0f; // align MicLev to lowest input signal + if (startuptime == 0) startuptime = millis(); // fast freeze mode - remember filter startup time + if ((micLevelMethod < 1) || !isFrozen) { // following the input level, UNLESS mic Level was frozen + micLev += (micDataReal-micLev) / 12288.0f; + } + + if(micDataReal < (micLev-0.24)) { // MicLev above input signal: + micLev = ((micLev * 31.0f) + micDataReal) / 32.0f; // always align MicLev to lowest input signal + if (!haveSilence) isFrozen = true; // freeze mode: freeze micLevel so it cannot rise again + } micIn -= micLev; // Let's center it to 0 now // Using an exponential filter to smooth out the signal. We'll add controls for this in a future release. @@ -1093,10 +1153,26 @@ class AudioReactive : public Usermod { expAdjF = fabsf(expAdjF); // Now (!) take the absolute value + if ((micLevelMethod == 2) && !haveSilence && (expAdjF >= (1.5f * float(soundSquelch)))) + isFrozen = true; // fast freeze mode: freeze micLevel once the volume rises 50% above squelch + //expAdjF = (micInNoDC <= soundSquelch) ? 0: expAdjF; // simple noise gate - experimental expAdjF = (expAdjF <= soundSquelch) ? 0: expAdjF; // simple noise gate if ((soundSquelch == 0) && (expAdjF < 0.25f)) expAdjF = 0; // do something meaningfull when "squelch = 0" + if (expAdjF <= 0.5f) + haveSilence = true; + else { + lastSoundTime = millis(); + haveSilence = false; + } + + // un-freeze micLev + if (micLevelMethod == 0) isFrozen = false; + if ((micLevelMethod == 1) && isFrozen && haveSilence && ((millis() - lastSoundTime) > 4000)) isFrozen = false; // normal freeze: 4 seconds silence needed + if ((micLevelMethod == 2) && isFrozen && haveSilence && ((millis() - lastSoundTime) > 6000)) isFrozen = false; // fast freeze: 6 seconds silence needed + if ((micLevelMethod == 2) && (millis() - startuptime < 12000)) isFrozen = false; // fast freeze: no freeze in first 12 seconds (filter startup phase) + tmpSample = expAdjF; micIn = abs(micIn); // And get the absolute value of each sample @@ -1360,6 +1436,7 @@ class AudioReactive : public Usermod { case 0: //ADC analog #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) case 5: //PDM Microphone + case 51: //legacy PDM Microphone #endif #endif case 1: @@ -1397,6 +1474,13 @@ class AudioReactive : public Usermod { delay(100); if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin); break; + case 51: + DEBUGSR_PRINT(F("AR: Legacy PDM Microphone - ")); DEBUGSR_PRINTLN(F(I2S_PDM_MIC_CHANNEL_TEXT)); + audioSource = new I2SSource(SAMPLE_RATE, BLOCK_SIZE, 1.0f); + useBandPassFilter = true; + delay(100); + if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin); + break; #endif case 6: DEBUGSR_PRINTLN(F("AR: ES8388 Source")); @@ -1537,7 +1621,7 @@ class AudioReactive : public Usermod { #if defined(WLED_DEBUG) || defined(SR_DEBUG) || defined(SR_STATS) // complain when audio userloop has been delayed for long time. Currently we need userloop running between 500 and 1500 times per second. - if ((userloopDelay > /*23*/ 30) && !disableSoundProcessing && (audioSyncEnabled == 0)) { + if ((userloopDelay > /*23*/ 65) && !disableSoundProcessing && (audioSyncEnabled == 0)) { USER_PRINTF("[AR userLoop] hickup detected -> was inactive for last %d millis!\n", userloopDelay); } #endif @@ -1673,14 +1757,15 @@ class AudioReactive : public Usermod { connected(); // resume UDP } else // xTaskCreatePinnedToCore( - xTaskCreate( // no need to "pin" this task to core #0 +// xTaskCreate( // no need to "pin" this task to core #0 + xTaskCreateUniversal( FFTcode, // Function to implement the task "FFT", // Name of the task 5000, // Stack size in words NULL, // Task input parameter 1, // Priority of the task &FFT_Task // Task handle -// , 0 // Core where the task should run + , 0 // Core where the task should run ); } micDataReal = 0.0f; // just to be sure @@ -1780,7 +1865,10 @@ class AudioReactive : public Usermod { if (audioSource->getType() == AudioSource::Type_I2SAdc) { infoArr.add(F("ADC analog")); } else { - infoArr.add(F("I2S digital")); + if (dmType != 51) + infoArr.add(F("I2S digital")); + else + infoArr.add(F("legacy I2S PDM")); } // input level or "silence" if (maxSample5sec > 1.0) { @@ -1793,7 +1881,7 @@ class AudioReactive : public Usermod { } else { // error during audio source setup infoArr.add(F("not initialized")); - infoArr.add(F(" - check GPIO config")); + infoArr.add(F(" - check pin settings")); } } @@ -1957,6 +2045,12 @@ class AudioReactive : public Usermod { cfg[F("gain")] = sampleGain; cfg[F("AGC")] = soundAgc; + //WLEDMM: experimental settings + JsonObject poweruser = top.createNestedObject("experiments"); + poweruser[F("micLev")] = micLevelMethod; + poweruser[F("freqDist")] = freqDist; + poweruser[F("freqRMS")] = averageByRMS; + JsonObject dynLim = top.createNestedObject("dynamics"); dynLim[F("limiter")] = limiterOn; dynLim[F("rise")] = attackTime; @@ -2005,7 +2099,11 @@ class AudioReactive : public Usermod { if (dmType == 0) dmType = SR_DMTYPE; // MCU does not support analog #if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32C3) if (dmType == 5) dmType = SR_DMTYPE; // MCU does not support PDM + if (dmType == 51) dmType = SR_DMTYPE; // MCU does not support legacy PDM #endif + #else + if (dmType == 5) useBandPassFilter = true; // enable filter for PDM + if (dmType == 51) useBandPassFilter = true /*false*/; // switch on filter for legacy PDM #endif configComplete &= getJsonValue(top[FPSTR(_digitalmic)]["pin"][0], i2ssdPin); @@ -2019,6 +2117,11 @@ class AudioReactive : public Usermod { configComplete &= getJsonValue(top["config"][F("gain")], sampleGain); configComplete &= getJsonValue(top["config"][F("AGC")], soundAgc); + //WLEDMM: experimental settings + configComplete &= getJsonValue(top["experiments"][F("micLev")], micLevelMethod); + configComplete &= getJsonValue(top["experiments"][F("freqDist")], freqDist); + configComplete &= getJsonValue(top["experiments"][F("freqRMS")], averageByRMS); + configComplete &= getJsonValue(top["dynamics"][F("limiter")], limiterOn); configComplete &= getJsonValue(top["dynamics"][F("rise")], attackTime); configComplete &= getJsonValue(top["dynamics"][F("fall")], decayTime); @@ -2038,10 +2141,12 @@ class AudioReactive : public Usermod { oappend(SET_F("addInfo('AudioReactive:help',0,'');")); //WLEDMM: add defaults + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) // -S3/-S2/-C3 don't support analog audio #ifdef AUDIOPIN oappend(SET_F("xOpt('AudioReactive:analogmic:pin',1,' ⎌',")); oappendi(AUDIOPIN); oappend(");"); #endif oappend(SET_F("aOpt('AudioReactive:analogmic:pin',1);")); //only analog options + #endif oappend(SET_F("dd=addDropdown('AudioReactive','digitalmic:type');")); #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) @@ -2071,12 +2176,17 @@ class AudioReactive : public Usermod { #else oappend(SET_F("addOption(dd,'Generic I2S with Mclk',4);")); #endif - #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) + #if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) #if SR_DMTYPE==5 oappend(SET_F("addOption(dd,'Generic I2S PDM (⎌)',5);")); #else oappend(SET_F("addOption(dd,'Generic I2S PDM',5);")); #endif + #if SR_DMTYPE==51 + oappend(SET_F("addOption(dd,'.Legacy I2S PDM ☾ (⎌)',51);")); + #else + oappend(SET_F("addOption(dd,'.Legacy I2S PDM ☾',51);")); + #endif #endif oappend(SET_F("addOption(dd,'ES8388',6);")); @@ -2093,6 +2203,23 @@ class AudioReactive : public Usermod { oappend(SET_F("addOption(dd,'Vivid',2);")); oappend(SET_F("addOption(dd,'Lazy',3);")); + //WLEDMM: experimental settings + oappend(SET_F("dd=addDropdown('AudioReactive','experiments:micLev');")); + oappend(SET_F("addOption(dd,'Floating (⎌)',0);")); + oappend(SET_F("addOption(dd,'Freeze',1);")); + oappend(SET_F("addOption(dd,'Fast Freeze',2);")); + oappend(SET_F("addInfo('AudioReactive:experiments:micLev',1,'☾');")); + + oappend(SET_F("dd=addDropdown('AudioReactive','experiments:freqDist');")); + oappend(SET_F("addOption(dd,'Normal (⎌)',0);")); + oappend(SET_F("addOption(dd,'RightShift',1);")); + oappend(SET_F("addInfo('AudioReactive:experiments:freqDist',1,'☾');")); + + oappend(SET_F("dd=addDropdown('AudioReactive','experiments:freqRMS');")); + oappend(SET_F("addOption(dd,'Off (⎌)',0);")); + oappend(SET_F("addOption(dd,'On',1);")); + oappend(SET_F("addInfo('AudioReactive:experiments:freqRMS',1,'☾');")); + oappend(SET_F("dd=addDropdown('AudioReactive','dynamics:limiter');")); oappend(SET_F("addOption(dd,'Off',0);")); oappend(SET_F("addOption(dd,'On',1);")); @@ -2163,6 +2290,7 @@ class AudioReactive : public Usermod { #else oappend(SET_F("addOption(dd,'userdefined #2',9);")); #endif + oappend(SET_F("addInfo('AudioReactive:frequency:profile',1,'☾');")); oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');")); oappend(SET_F("addOption(dd,'Off',0);")); @@ -2237,7 +2365,9 @@ class AudioReactive : public Usermod { const char AudioReactive::_name[] PROGMEM = "AudioReactive"; const char AudioReactive::_enabled[] PROGMEM = "enabled"; const char AudioReactive::_inputLvl[] PROGMEM = "inputLevel"; +#if !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) && !defined(CONFIG_IDF_TARGET_ESP32S3) const char AudioReactive::_analogmic[] PROGMEM = "analogmic"; +#endif const char AudioReactive::_digitalmic[] PROGMEM = "digitalmic"; const char AudioReactive::UDP_SYNC_HEADER[] PROGMEM = "00002"; // new sync header version, as format no longer compatible with previous structure const char AudioReactive::UDP_SYNC_HEADER_v1[] PROGMEM = "00001"; // old sync header version - need to add backwards-compatibility feature diff --git a/usermods/blynk_relay_control/README.md b/usermods/blynk_relay_control/README.md deleted file mode 100644 index f4832c08..00000000 --- a/usermods/blynk_relay_control/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Blynk controllable relay -Enables controlling a relay state via user variables. Allows the user variables to be set via Blynk. - -Optionally, the servo can have a reset timer to return to its default state after a user definable interval. The interval is set via userVar1. - -## Instalation - -Replace the WLED06_usermod.ino file in Aircoookies WLED folder, with the one here. - -## Customizations - -Update the following parameters in WLED06_usermod.ino to configure the mod's behavior: - -```cpp -//Which pin is the relay connected to -#define RELAY_PIN 5 -//Which pin state should the relay default to -#define RELAY_PIN_DEFAULT LOW -//If >0 The controller returns to RELAY_PIN_DEFAULT after this time, in milliseconds -#define RELAY_PIN_TIMER_DEFAULT 3000 - -//Blynk virtual pin for controlling relay -#define BLYNK_USER_VAR0_PIN V9 -//Blynk virtual pin for controlling relay timer -#define BLYNK_USER_VAR1_PIN V10 -//Number of milliseconds between Blynk updates -#define BLYNK_RELAY_UPDATE_INTERVAL 5000 -``` diff --git a/usermods/blynk_relay_control/wled06_usermod.ino b/usermods/blynk_relay_control/wled06_usermod.ino deleted file mode 100644 index d4028ea5..00000000 --- a/usermods/blynk_relay_control/wled06_usermod.ino +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file allows you to add own functionality to WLED more easily - * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality - * EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in wled_eeprom.h) - * bytes 2400+ are currently ununsed, but might be used for future wled features - */ - -//Use userVar0 (API calls &U0=, uint16_t) to set relay state -#define relayPinState userVar0 -//Use userVar1 (API calls &U1=, uint16_t) to set relay timer duration -//Ignored if 0, otherwise number of milliseconds to allow relay to stay in -//non default state. -#define relayTimerInterval userVar1 - -//Which pin is the relay connected to -#define RELAY_PIN 5 -//Which pin state should the relay default to -#define RELAY_PIN_DEFAULT LOW -//If >0 The controller returns to RELAY_PIN_DEFAULT after this time in milliseconds -#define RELAY_PIN_TIMER_DEFAULT 3000 - -//Blynk virtual pin for controlling relay -#define BLYNK_USER_VAR0_PIN V9 -//Blynk virtual pin for controlling relay timer -#define BLYNK_USER_VAR1_PIN V10 -//Number of milliseconds between updating blynk -#define BLYNK_RELAY_UPDATE_INTERVAL 5000 - -//Is the timer for resetting the relay active -bool relayTimerStarted = false; -//millis() time after which relay will be reset -unsigned long relayTimeToDefault = 0; -//millis() time after which relay vars in Blynk will be sent -unsigned long relayBlynkUpdateTime = 0; - -//gets called once at boot. Do all initialization that doesn't depend on network here -void userSetup() -{ - relayPinState = RELAY_PIN_DEFAULT; - relayTimerInterval = RELAY_PIN_TIMER_DEFAULT; - pinMode(RELAY_PIN, OUTPUT); - digitalWrite(RELAY_PIN, relayPinState); -} - -//gets called every time WiFi is (re-)connected. Initialize own network interfaces here -void userConnected() -{ -} - -//loop. You can use "if (WLED_CONNECTED)" to check for successful connection -void userLoop() -{ - //Normalize relayPinState to an accepted value - if (relayPinState != HIGH && relayPinState != LOW) { - relayPinState = RELAY_PIN_DEFAULT; - } - //If relay changes and relayTimerInterval is set, start a timer to change back - if (relayTimerInterval != 0 && - relayPinState != RELAY_PIN_DEFAULT && - !relayTimerStarted ) { - relayTimerStarted = true; - relayTimeToDefault = millis() + relayTimerInterval; - } - //If manually changed back to default, cancel timer - if (relayTimerStarted && relayPinState == RELAY_PIN_DEFAULT ) { - relayTimerStarted = false; - } - //If timer completes, set relay back to default - if (relayTimerStarted && millis() > relayTimeToDefault) { - relayPinState = RELAY_PIN_DEFAULT; - relayTimerStarted = false; - } - digitalWrite(RELAY_PIN, relayPinState); - updateRelayBlynk(); -} - -//Update Blynk with state of userVars at BLYNK_RELAY_UPDATE_INTERVAL -void updateRelayBlynk() -{ - if (!WLED_CONNECTED) return; - if (relayBlynkUpdateTime > millis()) return; - Blynk.virtualWrite(BLYNK_USER_VAR0_PIN, userVar0); - Blynk.virtualWrite(BLYNK_USER_VAR1_PIN, userVar1); - relayBlynkUpdateTime = millis() + BLYNK_RELAY_UPDATE_INTERVAL; -} - -//Add Blynk callback for setting userVar0 -BLYNK_WRITE(BLYNK_USER_VAR0_PIN) -{ - userVar0 = param.asInt(); -} -//Add Blynk callback for setting userVar1 -BLYNK_WRITE(BLYNK_USER_VAR1_PIN) -{ - userVar1 = param.asInt(); -} diff --git a/usermods/mpu6050_imu/usermod_mpu6050_imu.h b/usermods/mpu6050_imu/usermod_mpu6050_imu.h index d839c0df..e923e1f9 100644 --- a/usermods/mpu6050_imu/usermod_mpu6050_imu.h +++ b/usermods/mpu6050_imu/usermod_mpu6050_imu.h @@ -65,9 +65,9 @@ #undef DEBUG_PRINTF #ifdef WLED_DEBUG - #define DEBUG_PRINT(x) DEBUGOUT.print(x) - #define DEBUG_PRINTLN(x) DEBUGOUT.println(x) - #define DEBUG_PRINTF(x...) DEBUGOUT.printf(x) + #define DEBUG_PRINT(x) DEBUGOUT(x) + #define DEBUG_PRINTLN(x) DEBUGOUTLN(x) + #define DEBUG_PRINTF(x...) DEBUGOUTF(x) #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) @@ -93,18 +93,22 @@ void IRAM_ATTR dmpDataReady() { class MPU6050Driver : public Usermod { private: MPU6050 mpu; - bool enabled = true; unsigned long lastUMRun = millis(); // MPU control/status vars - bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer + // strings to reduce flash memory usage (used more than twice) + static const char _INT_pin[]; + public: + MPU6050Driver(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM: this shouldn't be necessary (passthrough of constructor), maybe because Usermod is an abstract class + + bool dmpReady = false; // set true if DMP init was successful // WLEDMM expose this info in public interface // orientation/motion vars Quaternion qat; // [w, x, y, z] quaternion container VectorInt16 aa; // [x, y, z] accel sensor measurements @@ -122,7 +126,11 @@ class MPU6050Driver : public Usermod { #endif void setup() { - // WLEDMM begin + // WLEDMM begin + if (!enabled) { + dmpReady = false; + return; + } USER_PRINTLN(F("mpu setup")); PinManagerPinType pins[2] = { { i2c_scl, true }, { i2c_sda, true } }; if ((i2c_scl < 0) || (i2c_sda < 0)) { @@ -171,16 +179,26 @@ class MPU6050Driver : public Usermod { // initialize device DEBUG_PRINT_IMULN(F("Initializing I2C devices...")); // WLEDMM begin - if (!pinManager.allocatePin(INTERRUPT_PIN, false, PinOwner::UM_Unspecified)) + if ((INTERRUPT_PIN < 0) || (!pinManager.isPinINT(INTERRUPT_PIN))) { + //enabled = false; + USER_PRINTF("mpu6050: warning - interrupt GPIO %d does not support interrupts.\n", INTERRUPT_PIN); + //INTERRUPT_PIN = -1; + //return; + } + if ((INTERRUPT_PIN >= 0) && (pinManager.getPinOwner(INTERRUPT_PIN) != PinOwner::UM_IMU) // only allocate pin if we don't ownn it already + && !pinManager.allocatePin(INTERRUPT_PIN, false, PinOwner::UM_IMU)) { //enabled = false; USER_PRINTF("mpu6050: warning - failed to allocate interrupt GPIO %d\n", INTERRUPT_PIN); + //INTERRUPT_PIN = -1; //return; } // WLEDMM end mpu.initialize(); - pinMode(INTERRUPT_PIN, INPUT); + if (INTERRUPT_PIN >= 0) { // WLEDMM only if pin is valid + pinMode(INTERRUPT_PIN, INPUT); + } // verify connection DEBUG_PRINT_IMULN(F("Testing device connections...")); @@ -214,11 +232,13 @@ class MPU6050Driver : public Usermod { DEBUG_PRINT_IMULN(F("Enabling DMP...")); mpu.setDMPEnabled(true); - // enable Arduino interrupt detection - DEBUG_PRINT_IMU(F("Enabling interrupt detection (Arduino external interrupt ")); - DEBUG_PRINT_IMU(digitalPinToInterrupt(INTERRUPT_PIN)); - DEBUG_PRINT_IMULN(F(")...")); - attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + if (INTERRUPT_PIN >= 0) { + // enable Arduino interrupt detection + DEBUG_PRINT_IMU(F("Enabling interrupt detection (Arduino external interrupt ")); + DEBUG_PRINT_IMU(digitalPinToInterrupt(INTERRUPT_PIN)); + DEBUG_PRINT_IMULN(F(")...")); + attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), dmpDataReady, RISING); + } mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it @@ -235,7 +255,9 @@ class MPU6050Driver : public Usermod { DEBUG_PRINT(F("DMP Initialization failed (code ")); DEBUG_PRINT(devStatus); DEBUG_PRINTLN(")"); + dmpReady = false; } + initDone = true; } void connected() { @@ -244,6 +266,7 @@ class MPU6050Driver : public Usermod { void loop() { // if programming failed, don't try to do anything + if (!initDone) return; if (!enabled || (strip.isUpdating() && (millis() - lastUMRun < 2))) return; // be nice, but not too nice lastUMRun = millis(); // update time keeping @@ -265,12 +288,15 @@ class MPU6050Driver : public Usermod { void addToJsonInfo(JsonObject& root) { + if (!initDone) return; + if (!enabled && !dmpReady) return; // WLEDMM no info when usermod disabled JsonObject user = root["u"]; if (user.isNull()) user = root.createNestedObject("u"); StaticJsonDocument<800> doc; //measured 528 // WLEDMM added some margin (was 600) JsonObject imu_meas = doc.createNestedObject("IMU"); + //JsonObject imu_meas = user.createNestedObject("IMU"); #ifdef WLED_DEBUG JsonArray quat_json = imu_meas.createNestedArray("Quat"); quat_json.add(qat.w); @@ -328,29 +354,64 @@ class MPU6050Driver : public Usermod { //{ //} - // void addToConfig(JsonObject& root) - // { - // JsonObject top = root.createNestedObject("MPU6050"); - // top[FPSTR("enabled")] = enabled; + // void addToConfig(JsonObject& root) + // { + // Usermod::addToConfig(root); + // JsonObject top = root[FPSTR(_name)]; + // // //JsonObject interruptPin = top.createNestedObject(FPSTR(_INT_pin)); + // // //interruptPin["pin"] = INTERRUPT_PIN; + // // DEBUG_PRINTLN(F("MPU6050 IMU config saved.")); + // } - // JsonObject interruptPin = top.createNestedObject(FPSTR("interruptPin")); - // interruptPin["pin"] = interruptPin; - // } + //WLEDMM: add appendConfigData + void appendConfigData() + { + oappend(SET_F("addHB('mpu6050-IMU');")); + /* + #ifdef MPU6050_INT_GPIO + oappend(SET_F("xOpt('mpu6050-IMU:interrupt_pin',0,' ⎌',")); oappendi(MPU6050_INT_GPIO); oappend(");"); + #endif + //WLEDMM add errorMessage to um settings + if (strcmp(errorMessage, "") != 0) { + oappend(SET_F("addInfo('errorMessage', 0, 'error: ")); oappend(errorMessage); oappend("! Correct and reboot');"); + } + */ + } - // bool readFromConfig(JsonObject& root) - // { - // JsonObject top = root[FPSTR("MPU6050")]; - // bool configComplete = !top.isNull(); + bool readFromConfig(JsonObject& root) + { + bool configComplete = Usermod::readFromConfig(root); + JsonObject top = root[FPSTR(_name)]; - // configComplete &= getJsonValue(top[FPSTR("enabled")], enabled); - // configComplete &= getJsonValue(top[FPSTR("interruptPin")]["pin"], interruptPin); + if (top.isNull()) { + DEBUG_PRINT(FPSTR(_name)); + DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); + return false; + } - // return configComplete; - // } + //configComplete &= getJsonValue(top[FPSTR(_INT_pin)]["pin"], INTERRUPT_PIN); + + DEBUG_PRINT(FPSTR(_name)); + if (!initDone) { + // first run: reading from cfg.json + DEBUG_PRINTLN(F(" config loaded.")); + } else { + DEBUG_PRINTLN(F(" config (re)loaded.")); + if (enabled || dmpReady) setup(); // re-run setup if user has checked "enabled" + if (!enabled) dmpReady = false; // not enabled inplies "no DMP data ready" + } + + return configComplete; + // use "return !top["newestParameter"].isNull();" when updating Usermod with new features + //return !top[FPSTR(_INT_pin)].isNull(); + } uint16_t getId() { return USERMOD_ID_IMU; } -}; \ No newline at end of file +}; + +// strings to reduce flash memory usage (used more than twice) +const char MPU6050Driver::_INT_pin[] PROGMEM = "interrupt_pin"; diff --git a/usermods/multi_relay/usermod_multi_relay.h b/usermods/multi_relay/usermod_multi_relay.h index 6528687d..749b9c75 100644 --- a/usermods/multi_relay/usermod_multi_relay.h +++ b/usermods/multi_relay/usermod_multi_relay.h @@ -202,11 +202,11 @@ class MultiRelay : public Usermod { /** * Enable/Disable the usermod */ - inline void enable(bool enable) { enabled = enable; } + // inline void enable(bool enable) { enabled = enable; } /** * Get usermod enabled/disabled state */ - inline bool isEnabled() { return enabled; } + // inline bool isEnabled() { return enabled; } /** * switch relay on/off diff --git a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h index e8806609..e2b65910 100644 --- a/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h +++ b/usermods/usermod_v2_auto_save/usermod_v2_auto_save.h @@ -79,6 +79,10 @@ class AutoSaveUsermod : public Usermod { month(localTime), day(localTime), hour(localTime), minute(localTime), second(localTime)); cacheInvalidate++; // force reload of presets + DEBUG_PRINT(F("UM autosave: saving preset ")); + DEBUG_PRINT(autoSavePreset); + DEBUG_PRINT(F(" => ")); + DEBUG_PRINTLN(presetNameBuffer); savePreset(autoSavePreset, presetNameBuffer); } @@ -86,7 +90,7 @@ class AutoSaveUsermod : public Usermod { #ifdef USERMOD_FOUR_LINE_DISPLAY if (display != nullptr) { display->wakeDisplay(); - display->overlay("Settings", "Auto Saved", 1500); + if (display->canDraw()) display->overlay("Settings", "Auto Saved", 1500); // WLEDMM bugfix } #endif } diff --git a/usermods/usermod_v2_fastled/readme.md b/usermods/usermod_v2_fastled/readme.md new file mode 100644 index 00000000..93707655 --- /dev/null +++ b/usermods/usermod_v2_fastled/readme.md @@ -0,0 +1,10 @@ +# Usermods API v2 example usermod + +In this usermod file you can find the documentation on how to take advantage of the new version 2 usermods! + +## Installation + +Copy `usermod_v2_fastled.h` to the wled00 directory. +Uncomment the corresponding lines in `usermods_list.cpp` and compile! +_(You shouldn't need to actually install this, it does nothing useful)_ + diff --git a/usermods/usermod_v2_fastled/usermod_v2_fastled.h b/usermods/usermod_v2_fastled/usermod_v2_fastled.h new file mode 100644 index 00000000..ae073445 --- /dev/null +++ b/usermods/usermod_v2_fastled/usermod_v2_fastled.h @@ -0,0 +1,358 @@ +#pragma once + +#include "wled.h" + +//WLEDMM + + +// Polar basics demo for the +// FastLED Podcast #2 +// https://www.youtube.com/watch?v=KKjFRZFBUrQ +// +// VO.1 preview version +// by Stefan Petrick 2023 +// This code is licenced under a +// Creative Commons Attribution +// License CC BY-NC 3.0 + +class PolarBasics { + private: + + public: + float runtime; // elapse ms since startup + float newdist, newangle; // parameters for image reconstruction + float z; // 3rd dimension for the 3d noise function + float offset_x, offset_y; // wanna shift the cartesians during runtime? + float scale_x, scale_y; // cartesian scaling in 2 dimensions + float dist, angle; // the actual polar coordinates + + int x, y; // the cartesian coordiantes + int num_x;// = WIDTH; // horizontal pixel count + int num_y;// = HEIGHT; // vertical pixel count + + // Background for setting the following 2 numbers: the FastLED inoise16() function returns + // raw values ranging from 0-65535. In order to improve contrast we filter this output and + // stretch the remains. In histogram (photography) terms this means setting a blackpoint and + // a whitepoint. low_limit MUST be smaller than high_limit. + + uint16_t low_limit;// = 30000; // everything lower drawns in black + // higher numer = more black & more contrast present + uint16_t high_limit;// = 50000; // everything higher gets maximum brightness & bleeds out + // lower number = the result will be more bright & shiny + + float center_x;// = (num_x / 2) - 0.5; // the reference point for polar coordinates + float center_y;// = (num_y / 2) - 0.5; // (can also be outside of the actual xy matrix) + //float center_x = 20; // the reference point for polar coordinates + //float center_y = 20; + + //WLEDMM: assign 32x32 fixed for the time being + float theta [32] [32]; // look-up table for all angles + float distance[32] [32]; // look-up table for all distances + float vignette[32] [32]; + float inverse_vignette[32] [32]; + + // std::vector> theta; // look-up table for all angles + // std::vector> distance; // look-up table for all distances + // std::vector> vignette; + // std::vector> inverse_vignette; + + float spd; // can be used for animation speed manipulation during runtime + + float show1, show2, show3, show4, show5; // to save the rendered values of all animation layers + float red, green, blue; // for the final RGB results after the colormapping + + float c, d, e, f; // factors for oscillators + float linear_c, linear_d, linear_e, linear_f; // linear offsets + float angle_c, angle_d, angle_e, angle_f; // angle offsets + float noise_angle_c, noise_angle_d, noise_angle_e, noise_angle_f; // angles based on linear noise travel + float dir_c, dir_d, dir_e, dir_f; // direction multiplicators + + void init () { + num_x = SEGMENT.virtualWidth(); // horizontal pixel count + num_y = SEGMENT.virtualHeight(); // vertical pixel count + low_limit = 30000; // everything lower drawns in black + // higher numer = more black & more contrast present + high_limit = 50000; // everything higher gets maximum brightness & bleeds out + // lower number = the result will be more bright & shiny + center_x = (num_x / 2) - 0.5; // the reference point for polar coordinates + center_y = (num_y / 2) - 0.5; // (can also be outside of the actual xy matrix) + + //allocate memory for the 2D arrays + // theta.resize(num_x, std::vector(num_y, 0)); + // distance.resize(num_x, std::vector(num_y, 0)); + // vignette.resize(num_x, std::vector(num_y, 0)); + // inverse_vignette.resize(num_x, std::vector(num_y, 0)); + } + + PolarBasics() { + USER_PRINTLN("constructor"); + } + ~PolarBasics() { + USER_PRINTLN("destructor"); + } + + void speedratiosAndOscillators() { + // set speedratios for the offsets & oscillators + + spd = 0.05 ; + c = 0.013 ; + d = 0.017 ; + e = 0.2 ; + f = 0.007 ; + + calculate_oscillators(); // get linear offsets and oscillators going + } + + void forLoop() { + // pick polar coordinates from look the up table + + dist = distance [x] [y]; + angle = theta [y] [x]; + + // Generation of one layer. Explore the parameters and what they do. + + scale_x = 10000; // smaller value = zoom in, bigger structures, less detail + scale_y = 10000; // higher = zoom out, more pixelated, more detail + z = 0; // must be >= 0 + newangle = angle + angle_c; + newdist = dist; + offset_x = 0; // must be >=0 + offset_y = 0; // must be >=0 + + show1 = render_pixel(); + + + // Colormapping - Assign rendered values to colors + + red = show1; + green = 0; + blue = 0; + + // Check the final results. + // Discard faulty RGB values & write the valid results into the framebuffer. + + write_pixel_to_framebuffer(); + } + + void calculate_oscillators() { + + runtime = millis(); // save elapsed ms since start up + + runtime = runtime * spd; // global anaimation speed + + linear_c = runtime * c; // some linear rising offsets 0 to max + linear_d = runtime * d; + linear_e = runtime * e; + linear_f = runtime * f; + + angle_c = fmodf(linear_c, 2 * PI); // some cyclic angle offsets 0 to 2*PI + angle_d = fmodf(linear_d, 2 * PI); + angle_e = fmodf(linear_e, 2 * PI); + angle_f = fmodf(linear_f, 2 * PI); + + dir_c = sinf(angle_c); // some direction oscillators -1 to 1 + dir_d = sinf(angle_d); + dir_e = sinf(angle_e); + dir_f = sinf(angle_f); + + uint16_t noi; + noi = inoise16(10000 + linear_c * 100000); // some noise controlled angular offsets + noise_angle_c = map_float(noi, 0, 65535 , 0, 4*PI); + noi = inoise16(20000 + linear_d * 100000); + noise_angle_d = map_float(noi, 0, 65535 , 0, 4*PI); + noi = inoise16(30000 + linear_e * 100000); + noise_angle_e = map_float(noi, 0, 65535 , 0, 4*PI); + noi = inoise16(40000 + linear_f * 100000); + noise_angle_f = map_float(noi, 0, 65535 , 0, 4*PI); + } + + + // given a static polar origin we can precalculate + // all the (expensive) polar coordinates + + void render_polar_lookup_table() { + + for (int xx = 0; xx < num_x; xx++) { + for (int yy = 0; yy < num_y; yy++) { + + float dx = xx - center_x; + float dy = yy - center_y; + + distance[xx] [yy] = hypotf(dx, dy); + theta[xx] [yy] = atan2f(dy, dx); + + } + } + } + + // convert polar coordinates back to cartesian + // & render noise value there + + float render_pixel() { + + // convert polar coordinates back to cartesian ones + + float newx = (offset_x + center_x - (cosf(newangle) * newdist)) * scale_x; + float newy = (offset_y + center_y - (sinf(newangle) * newdist)) * scale_y; + + // render noisevalue at this new cartesian point + + uint16_t raw_noise_field_value = inoise16(newx, newy, z); + + // a lot is happening here, namely + // A) enhance histogram (improve contrast) by setting the black and white point + // B) scale the result to a 0-255 range + // it's the contrast boosting & the "colormapping" (technically brightness mapping) + + if (raw_noise_field_value < low_limit) raw_noise_field_value = low_limit; + if (raw_noise_field_value > high_limit) raw_noise_field_value = high_limit; + + float scaled_noise_value = map_float(raw_noise_field_value, low_limit, high_limit, 0, 255); + + return scaled_noise_value; + + // done, we've just rendered one color value for one single pixel + } + + // float mapping maintaining 32 bit precision + // we keep values with high resolution for potential later usage + + float map_float(float x, float in_min, float in_max, float out_min, float out_max) { + + float result = (x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min; + if (result < out_min) result = out_min; + if( result > out_max) result = out_max; + + return result; + } + + // Avoid any possible color flicker by forcing the raw RGB values to be 0-255. + // This enables to play freely with random equations for the colormapping + // without causing flicker by accidentally missing the valid target range. + + void rgb_sanity_check() { + + // rescue data if possible: when negative return absolute value + if (red < 0) red = abs(red); + if (green < 0) green = abs(green); + if (blue < 0) blue = abs(blue); + + // discard everything above the valid 0-255 range + if (red > 255) red = 255; + if (green > 255) green = 255; + if (blue > 255) blue = 255; + + } + + void write_pixel_to_framebuffer() { + + // the final color values shall not exceed 255 (to avoid flickering pixels caused by >255 = black...) + // negative values * -1 + + rgb_sanity_check(); + + CRGB finalcolor = CRGB(red, green, blue); + + // write the rendered pixel into the framebutter + SEGMENT.setPixelColorXY(x,y,finalcolor); + } + + // precalculate a radial brightness mask + + void render_vignette_table(float filter_radius) { + + for (int xx = 0; xx < num_x; xx++) { + for (int yy = 0; yy < num_y; yy++) { + + vignette[xx] [yy] = (filter_radius - distance[xx] [yy]) / filter_radius; + if (vignette[xx] [yy] < 0) vignette[xx] [yy] = 0; + } + } + } + +}; + +//effect functions +uint16_t mode_PolarBasics(void) { + + PolarBasics* pb; + + + if(!SEGENV.allocateData(sizeof(PolarBasics))) {SEGMENT.fill(SEGCOLOR(0)); return 350;} //mode_static(); //allocation failed + + pb = reinterpret_cast(SEGENV.data); + + //first time init + if (SEGENV.call == 0) { + + USER_PRINTF("mode_PolarBasics %d\n", sizeof(PolarBasics)); + // if (SEGENV.call == 0) SEGMENT.setUpLeds(); + + pb->init(); + + pb->render_polar_lookup_table(); // precalculate all polar coordinates + // to improve the framerate + pb->render_vignette_table(9.5); // the number is the desired radius in pixel + // WIDTH/2 generates a circle + } + + pb->speedratiosAndOscillators(); + + // ...and now let's generate a frame + + for (pb->x = 0; pb->x < pb->num_x; pb->x++) { + for (pb->y = 0; pb->y < pb->num_y; pb->y++) { + + pb->forLoop(); + + } + } + + // FastLED.show(); + + return FRAMETIME; +} + +static const char _data_FX_mode_PolarBasics[] PROGMEM = "💡Polar Basics ☾@;;;2"; + +//class name. Use something descriptive and leave the ": public Usermod" part :) +class FastledUsermod : public Usermod { + + private: + + + public: + + FastledUsermod(const char *name, bool enabled):Usermod(name, enabled) {} //WLEDMM + + void setup() { + strip.addEffect(255, &mode_PolarBasics, _data_FX_mode_PolarBasics); + + initDone = true; + } + + + void connected() { + } + + + void loop() { + if (!enabled || strip.isUpdating()) return; + + // do your magic here + if (millis() - lastTime > 1000) { + //Serial.println("I'm alive!"); + lastTime = millis(); + } + } + + + uint16_t getId() + { + return USERMOD_ID_FASTLED; + } + +}; + + + diff --git a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h index ebe066c3..ff60a4d4 100644 --- a/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h +++ b/usermods/usermod_v2_four_line_display_ALT/usermod_v2_four_line_display_ALT.h @@ -2,35 +2,37 @@ #include // WLEDMM: make sure that I2C drivers have the "right" Wire Object #include +#include #undef U8X8_NO_HW_I2C // WLEDMM: we do want I2C hardware drivers - if possible -//#define WIRE_INTERFACES_COUNT 2 // experimental - tell U8x8Lib that there is a econd Wire unit +//#define WIRE_INTERFACES_COUNT 2 // experimental - tell U8x8Lib that there is a second Wire unit #include "wled.h" #include // from https://github.com/olikraus/u8g2/ #include "4LD_wled_fonts.c" #ifndef FLD_ESP32_NO_THREADS -#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!! +#define FLD_ESP32_USE_THREADS // comment out to use 0.13.x behaviour without parallel update task - slower, but more robust. May delay other tasks like LEDs or audioreactive!! #endif +//#define OLD_4LD_FONTS // comment out if you prefer the "classic" look with blocky fonts (saves 1K flash) + // -// Insired by the usermod_v2_four_line_display +// Inspired by the usermod_v2_four_line_display // // v2 usermod for using 128x32 or 128x64 i2c // OLED displays to provide a four line display // for WLED. // // Dependencies -// * This usermod REQURES the ModeSortUsermod -// * This Usermod works best, by far, when coupled -// with RotaryEncoderUIUsermod. +// * This usermod does not REQUIRE the ModeSortUsermod any more +// * This usermod works best, by far, when coupled +// with RotaryEncoderUI_ALT usermod. // // Make sure to enable NTP and set your time zone in WLED Config | Time. // // REQUIREMENT: You must add the following requirements to // REQUIREMENT: "lib_deps" within platformio.ini / platformio_override.ini -// REQUIREMENT: * U8g2 (the version already in platformio.ini is fine) -// REQUIREMENT: * Wire +// REQUIREMENT: olikraus/U8g2@ ^2.34.15 (the version already in platformio.ini is fine) // //The SCL and SDA pins are defined here. @@ -92,7 +94,9 @@ typedef enum { SSD1305, // U8X8_SSD1305_128X32_ADAFRUIT_HW_I2C SSD1305_64, // U8X8_SSD1305_128X64_ADAFRUIT_HW_I2C SSD1306_SPI, // U8X8_SSD1306_128X32_NONAME_HW_SPI - SSD1306_SPI64 // U8X8_SSD1306_128X64_NONAME_HW_SPI + SSD1306_SPI64=7, // U8X8_SSD1306_128X64_NONAME_HW_SPI + SSD1309_SPI64=8, // U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI + SSD1327_SPI128=9 // U8X8_SSD1327_WS_128X128_4W_SW_SPI } DisplayType; @@ -115,6 +119,23 @@ class FourLineDisplayUsermod : public Usermod { // HW interface & configuration U8X8 *u8x8 = nullptr; // pointer to U8X8 display object +#if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) + // semaphores - needed on ESP32 only, as we use a separate task to update the display + SemaphoreHandle_t drawMux = xSemaphoreCreateBinary(); // for drawstring and drawglyph functions (to prevent concurrent access to HW) + SemaphoreHandle_t drawMuxBig = xSemaphoreCreateBinary(); // for draw2x2GlyphIcons() and showCurrentEffectOrPalette() - more complex and not thread-safe + const TickType_t maxWait = 300 * portTICK_PERIOD_MS; // wait max. 300ms (drawstring semaphore) + const TickType_t maxWaitLong = 800 * portTICK_PERIOD_MS; // wait max. 800ms (big drawing semaphore) + #define FLD_SemaphoreTake(x,t) xSemaphoreTake((x),(t)) + #define FLD_SemaphoreGive(x) xSemaphoreGive(x) +#else + // 8266 or no tasks - no semaphores + #define FLD_SemaphoreTake(x,t) pdTRUE + #define FLD_SemaphoreGive(x) + #if !defined(ARDUINO_ARCH_ESP32) && !defined(pdTRUE) + #define pdTRUE true + #endif +#endif + #ifndef FLD_SPI_DEFAULT int8_t ioPin[5] = {FLD_PIN_SCL, FLD_PIN_SDA, -1, -1, -1}; // I2C pins: SCL, SDA uint32_t ioFrequency = 400000; // in Hz (minimum is 100000, baseline is 400000 and maximum should be 3400000) @@ -124,7 +145,7 @@ class FourLineDisplayUsermod : public Usermod { #endif DisplayType type = FLD_TYPE; // display type - bool typeOK = false; //WLEDMM: instead of type == NULL and type=NULL. Intially false, as display was not initialized yet + bool typeOK = false; //WLEDMM: instead of type == NULL and type=NULL. Initially false, as display was not initialized yet bool flip = false; // flip display 180° uint8_t contrast = 10; // screen contrast uint8_t lineHeight = 1; // 1 row or 2 rows @@ -143,6 +164,8 @@ class FourLineDisplayUsermod : public Usermod { bool enabled = true; #endif bool contrastFix = false; + bool driverHW = false; + bool driverSPI = false; // Next variables hold the previous known values to determine if redraw is // required. @@ -193,7 +216,7 @@ class FourLineDisplayUsermod : public Usermod { // some displays need this to properly apply contrast void setVcomh(bool highContrast) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it - if (!canDraw()) return; // don't interfere with ongoing draw + if (u8x8 == nullptr) return; u8x8_t *u8x8_struct = u8x8->getU8x8(); u8x8_cad_StartTransfer(u8x8_struct); @@ -207,33 +230,77 @@ class FourLineDisplayUsermod : public Usermod { */ void setFlipMode(uint8_t mode) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it - if (canDraw()) u8x8->setFlipMode(mode); + if (u8x8 == nullptr) return; + u8x8->setFlipMode(mode); } void setContrast(uint8_t contrast) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it - if (canDraw()) u8x8->setContrast(contrast); + if (u8x8 == nullptr) return; + u8x8->setContrast(contrast); } void drawString(uint8_t col, uint8_t row, const char *string, bool ignoreLH=false) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it - u8x8->setFont(u8x8_font_chroma48medium8_r); // crashes randomly on ESP32 - if (!ignoreLH && lineHeight==2) u8x8->draw1x2String(col, row, string); // crashes randomly on ESP32 - else u8x8->drawString(col, row, string); + if (u8x8 == nullptr) return; + if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex + +#if defined(ARDUINO_ARCH_ESP32) && !defined(OLD_4LD_FONTS) // WLEDMM use nicer 2x2 font on ESP32 + if (!ignoreLH && lineHeight>1) { + if(strlen(string) > 3) // WLEDMM little hack - less than 3 chars -> show in bold + u8x8->setFont(u8x8_font_7x14_1x2_r); // normal + else + u8x8->setFont(u8x8_font_8x13B_1x2_r); // bold + u8x8->drawString(col, row, string); + } + else { + u8x8->setFont(u8x8_font_chroma48medium8_r); + u8x8->drawString(col, row, string); + } +#else + u8x8->setFont(u8x8_font_chroma48medium8_r); + if (!ignoreLH && lineHeight>1) u8x8->draw1x2String(col, row, string); + else u8x8->drawString(col, row, string); +#endif + FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex } void draw2x2String(uint8_t col, uint8_t row, const char *string) { if (!typeOK || !enabled) return; + if (u8x8 == nullptr) return; + if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex +#if defined(ARDUINO_ARCH_ESP32) && !defined(OLD_4LD_FONTS) // WLEDMM use nicer 2x2 font on ESP32 + if (lineHeight>1) { // WLEDMM use 2x3 on 128x64 displays + //u8x8->setFont(u8x8_font_profont29_2x3_r); // sans serif 2x3 + u8x8->setFont(u8x8_font_courB18_2x3_r); // courier bold 2x3 + u8x8->drawString(col, row + (row >3? 1:0), string); + } else { + //u8x8->setFont(u8x8_font_lucasarts_scumm_subtitle_o_2x2_r); + //u8x8->setFont(u8x8_font_lucasarts_scumm_subtitle_r_2x2_r); + u8x8->setFont(u8x8_font_px437wyse700b_2x2_r); + u8x8->drawString(col, row, string); + } +#else u8x8->setFont(u8x8_font_chroma48medium8_r); - u8x8->draw2x2String(col, row, string); + if (lineHeight>1) { // WLEDMM use 2x3 on 128x64 displays + u8x8->draw2x2String(col, row + (row >3? 1:0), string); + } else { + u8x8->draw2x2String(col, row, string); + } +#endif + FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex } void drawGlyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font, bool ignoreLH=false) { if (!typeOK || !enabled) return; + if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex u8x8->setFont(font); - if (!ignoreLH && lineHeight==2) u8x8->draw1x2Glyph(col, row, glyph); + if (!ignoreLH && lineHeight>1) u8x8->draw1x2Glyph(col, row, glyph); else u8x8->drawGlyph(col, row, glyph); + FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex } void draw2x2Glyph(uint8_t col, uint8_t row, char glyph, const uint8_t *font) { if (!typeOK || !enabled) return; + if (FLD_SemaphoreTake(drawMux, maxWait) != pdTRUE) return; // WLEDMM acquire draw mutex u8x8->setFont(font); u8x8->draw2x2Glyph(col, row, glyph); + FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex } uint8_t getCols() { if (!typeOK || !enabled) return 0; @@ -242,10 +309,13 @@ class FourLineDisplayUsermod : public Usermod { void clear() { if (!typeOK || !enabled) return; if (nullptr == u8x8) return; // prevents some crashes + if (FLD_SemaphoreTake(drawMux, maxWaitLong ) != pdTRUE) return; // WLEDMM acquire draw mutex - clear() can take very long in software I2C mode u8x8->clear(); // crashes randomly on ESP32 + FLD_SemaphoreGive(drawMux); // WLEDMM release draw mutex } void setPowerSave(uint8_t save) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it + if (u8x8 == nullptr) return; u8x8->setPowerSave(save); } @@ -257,7 +327,8 @@ class FourLineDisplayUsermod : public Usermod { void draw2x2GlyphIcons() { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it - if (lineHeight == 2) { + if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex + if (lineHeight > 1) { drawGlyph( 1, 0, 1, u8x8_4LineDisplay_WLED_icons_2x2, true); //brightness icon drawGlyph( 5, 0, 2, u8x8_4LineDisplay_WLED_icons_2x2, true); //speed icon drawGlyph( 9, 0, 3, u8x8_4LineDisplay_WLED_icons_2x2, true); //intensity icon @@ -270,6 +341,7 @@ class FourLineDisplayUsermod : public Usermod { drawGlyph(15, 2, 4, u8x8_4LineDisplay_WLED_icons_1x1); //palette icon drawGlyph(15, 3, 5, u8x8_4LineDisplay_WLED_icons_1x1); //effect icon } + FLD_SemaphoreGive(drawMuxBig); // WLEDMM release BIG draw mutex } /** @@ -305,10 +377,25 @@ class FourLineDisplayUsermod : public Usermod { } snprintf_P(lineBuffer,LINE_BUFFER_SIZE, PSTR("%2d:%02d"), (useAMPM ? AmPmHour : hourCurrent), minuteCurrent); draw2x2String(2, lineHeight*2, lineBuffer); //draw hour, min. blink ":" depending on odd/even seconds - if (useAMPM) drawString(12, lineHeight*2, (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time + if (useAMPM) drawString(12, lineHeight*2 + (lineHeight-1), (isitAM ? "AM" : "PM"), true); //draw am/pm if using 12 time drawStatusIcons(); //icons power, wifi, timer, etc + if (lineHeight > 1) { // WLEDMM use extra space for useful information + #if defined(WLED_DEBUG) || defined(SR_DEBUG) || defined(SR_STATS) + snprintf_P(lineBuffer, LINE_BUFFER_SIZE, PSTR(" %-3.3s %-2.2s "), driverSPI? "SPI" : "I2C", driverHW? "hw" : "sw"); // WLEDMM driver info + #else + strncpy_P(lineBuffer, PSTR(" "), LINE_BUFFER_SIZE); + #endif + if (apActive) strncpy_P(lineBuffer, PSTR(" AP mode "), LINE_BUFFER_SIZE); + else if (!WLED_CONNECTED) strncpy_P(lineBuffer, PSTR(" NO NET "), LINE_BUFFER_SIZE); + if (WLED_MQTT_CONNECTED) lineBuffer[9] = 'M'; // "MQTT" + if (realtimeMode && !realtimeOverride) lineBuffer[10] = 'X'; // "eXternal control" + //if (transitionActive) lineBuffer[11] = 'T'; + //if (stateChanged) lineBuffer[12] = 'C'; + drawString(1, 0, lineBuffer, false); + } + knownMinute = minuteCurrent; knownHour = hourCurrent; } @@ -316,7 +403,10 @@ class FourLineDisplayUsermod : public Usermod { lastSecond = secondCurrent; draw2x2String(6, lineHeight*2, secondCurrent%2 ? " " : ":"); snprintf_P(lineBuffer, LINE_BUFFER_SIZE, PSTR("%02d"), secondCurrent); - drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line + if (useAMPM) + drawString(12, lineHeight*2+1 + (lineHeight-1), lineBuffer, true); // even with double sized rows print seconds in 1 line // WLEDMM move it a bit lower + else + drawString(12, lineHeight*2+1, lineBuffer, true); // even with double sized rows print seconds in 1 line } drawing = false; } @@ -326,16 +416,26 @@ class FourLineDisplayUsermod : public Usermod { // gets called once at boot. Do all initialization that doesn't depend on // network here void setup() { - if (!enabled) return; // typeOK = true will be set after successfull setup + if (!enabled) return; // typeOK = true will be set after successful setup - bool isHW, isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64); + bool isHW, isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type > 7); PinOwner po = PinOwner::UM_FourLineDisplay; if (isSPI) { if (ioPin[0] < 0 || ioPin[1] < 0) { ioPin[0] = spi_sclk; ioPin[1] = spi_mosi; + } else { + if ((spi_sclk < 0) && (spi_mosi < 0)) { // WLEDMM UM pins are valid, but global = -1 --> copy pins to "global" + spi_sclk = ioPin[0]; + spi_mosi = ioPin[1]; + } } + if ((ioPin[0] < 0 || ioPin[1] < 0) && (spi_sclk < 0 || spi_mosi < 0)) { // invalid pins, or "use global" and global pins not defined + typeOK=false; strcpy(errorMessage, PSTR("SPI No Pins defined")); return; } //WLEDMM bugfix - ensure that "final" GPIO are valid + isHW = (ioPin[0]==spi_sclk && ioPin[1]==spi_mosi); + if ((ioPin[0] == -1) || (ioPin[1] == -1)) isHW = true; // WLEDMM "use global" = hardware + if ((spi_sclk <0) || (spi_mosi < 0)) isHW = false; // no global pins - use software emulation PinManagerPinType cspins[3] = { { ioPin[2], true }, { ioPin[3], true }, { ioPin[4], true } }; if (!pinManager.allocateMultiplePins(cspins, 3, PinOwner::UM_FourLineDisplay)) { typeOK=false; strcpy(errorMessage, PSTR("SPI3 alloc pins failed")); return; } if (isHW) po = PinOwner::HW_SPI; // allow multiple allocations of HW I2C bus pins @@ -346,25 +446,36 @@ class FourLineDisplayUsermod : public Usermod { strcpy(errorMessage, PSTR("SPI2 alloc pins failed")); return; } + // start SPI now! +#ifdef ARDUINO_ARCH_ESP32 + if (isHW) SPI.begin(spi_sclk, spi_miso, spi_mosi); // ESP32 - will silently fail if SPI alread active. +#else + if (isHW) SPI.begin(); // ESP8266 - SPI pins are fixed +#endif + } else { - if (ioPin[0] < 0 || ioPin[1] < 0) { - ioPin[0] = i2c_scl; - ioPin[1] = i2c_sda; - } + //if (ioPin[0] < 0 || ioPin[1] < 0) { //WLEDMM do _not_ copy global pins !! + // ioPin[0] = i2c_scl; + // ioPin[1] = i2c_sda; + //} isHW = (ioPin[0]==i2c_scl && ioPin[1]==i2c_sda); + if ((ioPin[0] == -1) || (ioPin[1] == -1)) isHW = true; // WLEDMM "use global" = hardware // isHW = true; if (isHW) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins PinManagerPinType pins[2] = { {ioPin[0], true }, { ioPin[1], true } }; - if (ioPin[0] < 0 || ioPin[1] < 0) { typeOK=false; strcpy(errorMessage, PSTR("I2C No Pins defined")); return; } //WLEDMM bugfix - ensure that "final" GPIO are valid + if ((ioPin[0] < 0 || ioPin[1] < 0) && (i2c_scl < 0 || i2c_sda < 0)) { // invalid pins, or "use global" and global pins not defined + typeOK=false; strcpy(errorMessage, PSTR("I2C No Pins defined")); return; } //WLEDMM bugfix - ensure that "final" GPIO are valid if (isHW) { - if (!pinManager.joinWire(ioPin[1], ioPin[0])) { typeOK=false; strcpy(errorMessage, PSTR("I2C init failed")); return; } // WLEDMM join the HW bus + if (!pinManager.joinWire(i2c_sda, i2c_scl)) { typeOK=false; strcpy(errorMessage, PSTR("I2C HW init failed")); return; } // WLEDMM join the HW bus } else { if (!pinManager.allocateMultiplePins(pins, 2, po)) { typeOK=false; strcpy(errorMessage, PSTR("I2C Alloc pins failed")); return; } // WLEDMM use software bus } } + driverHW = isHW; + driverSPI= isSPI; DEBUG_PRINTLN(F("Allocating display.")); /* // At some point it may be good to not new/delete U8X8 object but use this instead @@ -436,19 +547,31 @@ class FourLineDisplayUsermod : public Usermod { if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); else u8x8 = (U8X8 *) new U8X8_SSD1306_128X64_NONAME_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset break; + case SSD1309_SPI64: + // u8x8 uses global SPI variable that is attached to VSPI bus on ESP32 + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); + else u8x8 = (U8X8 *) new U8X8_SSD1309_128X64_NONAME0_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset + break; + case SSD1327_SPI128: + // u8x8 uses global SPI variable that is attached to VSPI bus on ESP32 + if (!isHW) u8x8 = (U8X8 *) new U8X8_SSD1327_WS_128X128_4W_SW_SPI(ioPin[0], ioPin[1], ioPin[2], ioPin[3], ioPin[4]); + else u8x8 = (U8X8 *) new U8X8_SSD1327_WS_128X128_4W_HW_SPI(ioPin[2], ioPin[3], ioPin[4]); // Pins are cs, dc, reset + break; default: u8x8 = nullptr; } if (nullptr == u8x8) { USER_PRINTLN(F("Display init failed.")); - pinManager.deallocateMultiplePins((const uint8_t*)ioPin, isSPI ? 5 : 2, po); + if (!isHW || !isSPI) pinManager.deallocateMultiplePins((const uint8_t*)ioPin, isSPI ? 5 : 2, po); // WLEDMM do not de-alloc global pins typeOK=false; strcpy(errorMessage, PSTR("Display init failed")); return; } lineHeight = u8x8->getRows() > 4 ? 2 : 1; + if (u8x8->getRows() > 8) lineHeight =3; + //if (u8x8->getRows() > 12) lineHeight =4; if (isSPI) { USER_PRINTLN(isHW ? F("Starting display (SPI HW).") : F("Starting display (SPI Soft).")); } else { @@ -457,15 +580,24 @@ class FourLineDisplayUsermod : public Usermod { u8x8->setBusClock(ioFrequency); // can be used for SPI too u8x8->begin(); typeOK = true; - drawing = false; + reDrawing = false; + drawing = true; setFlipMode(flip); setVcomh(contrastFix); setContrast(contrast); //Contrast setup will help to preserve OLED lifetime. In case OLED need to be brighter increase number up to 255 setPowerSave(0); + drawing = false; + + // init semaphores to allow drawing + FLD_SemaphoreGive(drawMux); + FLD_SemaphoreGive(drawMuxBig); + + onUpdateBegin(false); // create Display task // WLEDMM bugfix: before drawing anything + delay(200); + //drawString(0, 0, "Loading..."); overlayLogo(3500); - onUpdateBegin(false); // create Display task initDone = true; } @@ -502,6 +634,7 @@ class FourLineDisplayUsermod : public Usermod { //function to to check if a redraw or overlay draw is active. Needed for UM Rotary, to avoid random/concurrent drawing bool canDraw(void) { + if (!typeOK || !enabled || !initDone) return(false); // WLEDMM make sure the display is initialized before we try to draw on it #if defined(ARDUINO_ARCH_ESP32) && defined(FLD_ESP32_USE_THREADS) // only necessary on ESP32 if (drawing) return(false); // overlay draws someting if (reDrawing) return(false); // redraw task draws something @@ -609,7 +742,7 @@ class FourLineDisplayUsermod : public Usermod { // and turn it back on if it changed. clear(); sleepOrClock(true); - } else if (displayTurnedOff && ntpEnabled) { + } else if (displayTurnedOff) { // WLEDMM removed "&& ntpEnabled" showTime(); } return; @@ -686,10 +819,10 @@ class FourLineDisplayUsermod : public Usermod { uint8_t col = 15; uint8_t row = 0; drawGlyph(col, row, (wificonnected ? 20 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // wifi icon - if (lineHeight==2) { col--; } else { row++; } + if (lineHeight>1) { col--; } else { row++; } drawGlyph(col, row, (bri > 0 ? 9 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // power icon - if (lineHeight==2) { col--; } else { col = row = 0; } - drawGlyph(col, row, (nightlightActive ? 6 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // moon icon for nighlight mode + if (lineHeight>1) { col--; } else { col = row = 0; } + drawGlyph(col, row, (nightlightActive ? 6 : 0), u8x8_4LineDisplay_WLED_icons_1x1, true); // moon icon for nightlight mode } /** @@ -702,7 +835,7 @@ class FourLineDisplayUsermod : public Usermod { markColNum = newMarkColNum; } - //Draw the arrow for the current setting beiong changed + //Draw the arrow for the current setting being changed void drawArrow() { if (markColNum != 255 && markLineNum !=255) drawGlyph(markColNum, markLineNum*lineHeight, 21, u8x8_4LineDisplay_WLED_icons_1x1); } @@ -712,6 +845,8 @@ class FourLineDisplayUsermod : public Usermod { void showCurrentEffectOrPalette(int inputEffPal, const char *qstring, uint8_t row) { char lineBuffer[MAX_JSON_CHARS] = { '\0' }; if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it + if (FLD_SemaphoreTake(drawMuxBig, maxWaitLong) != pdTRUE) return; // WLEDMM acquire BIG draw mutex + if (overlayUntil == 0) { // Find the mode name in JSON uint8_t printedChars = extractModeName(inputEffPal, qstring, lineBuffer, MAX_JSON_CHARS-1); @@ -725,7 +860,7 @@ class FourLineDisplayUsermod : public Usermod { for (byte i=5; i<=printedChars; i++) lineBuffer[i-5] = lineBuffer[i]; //include '\0' printedChars -= 5; } - if (lineHeight == 2) { // use this code for 8 line display + if (lineHeight > 1) { // use this code for 8 line display char smallBuffer1[MAX_MODE_LINE_SPACE+1] = { '\0' }; char smallBuffer2[MAX_MODE_LINE_SPACE+1] = { '\0' }; uint8_t smallChars1 = 0; @@ -754,11 +889,11 @@ class FourLineDisplayUsermod : public Usermod { } while (smallChars1 < (MAX_MODE_LINE_SPACE-1)) smallBuffer1[smallChars1++]=' '; smallBuffer1[smallChars1] = 0; - smallBuffer1[MAX_MODE_LINE_SPACE -1] = '\0'; // ensure the string ends where it should (while loop avove can overshoot by 1) + smallBuffer1[MAX_MODE_LINE_SPACE -1] = '\0'; // ensure the string ends where it should (while loop above can overshoot by 1) drawString(1, row*lineHeight, smallBuffer1, true); while (smallChars2 < (MAX_MODE_LINE_SPACE-1)) smallBuffer2[smallChars2++]=' '; smallBuffer2[smallChars2] = 0; - smallBuffer2[MAX_MODE_LINE_SPACE -1] = '\0'; // ensure the string ends where it should (while loop avove can overshoot by 1) + smallBuffer2[MAX_MODE_LINE_SPACE -1] = '\0'; // ensure the string ends where it should (while loop above can overshoot by 1) drawString(1, row*lineHeight+1, smallBuffer2, true); } } else { // use this code for 4 ling displays @@ -769,6 +904,8 @@ class FourLineDisplayUsermod : public Usermod { drawString(1, row*lineHeight, smallBuffer3, true); } } + + FLD_SemaphoreGive(drawMuxBig); // WLEDMM release BIG draw mutex } /** @@ -779,6 +916,7 @@ class FourLineDisplayUsermod : public Usermod { */ bool wakeDisplay() { if (!typeOK || !enabled) return false; + if (!initDone) return false; if (displayTurnedOff) { unsigned long now = millis(); while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing @@ -800,6 +938,7 @@ class FourLineDisplayUsermod : public Usermod { */ void overlay(const char* line1, long showHowLong, byte glyphType) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it + if (!initDone) return; // WLEDMM bugfix unsigned long now = millis(); while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing while ((reDrawing && overlayUntil == 0) && (millis()-now < 250)) delay(10); // wait if someone else is re-drawing @@ -808,7 +947,7 @@ class FourLineDisplayUsermod : public Usermod { if (!wakeDisplay()) clear(); // Print the overlay if (glyphType>0 && glyphType<255) { - if (lineHeight == 2) drawGlyph(5, 0, glyphType, u8x8_4LineDisplay_WLED_icons_6x6, true); // use 3x3 font with draw2x2Glyph() if flash runs short and comment out 6x6 font + if (lineHeight > 1) drawGlyph(5, 0, glyphType, u8x8_4LineDisplay_WLED_icons_6x6, true); // use 3x3 font with draw2x2Glyph() if flash runs short and comment out 6x6 font else drawGlyph(6, 0, glyphType, u8x8_4LineDisplay_WLED_icons_3x3, true); } if (line1) { @@ -832,7 +971,7 @@ class FourLineDisplayUsermod : public Usermod { // Turn the display back on if (!wakeDisplay()) clear(); // Print the overlay - if (lineHeight == 2) { + if (lineHeight > 1) { //add a bit of randomness switch (millis()%3) { case 0: @@ -888,6 +1027,7 @@ class FourLineDisplayUsermod : public Usermod { */ void overlay(const char* line1, const char* line2, long showHowLong) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it + if (!initDone) return; // WLEDMM bugfix unsigned long now = millis(); while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing while ((reDrawing && overlayUntil == 0) && (millis()-now < 250)) delay(10); // wait if someone else is re-drawing @@ -911,6 +1051,7 @@ class FourLineDisplayUsermod : public Usermod { void networkOverlay(const char* line1, long showHowLong) { if (!typeOK || !enabled) return; // WLEDMM make sure the display is initialized before we try to draw on it + if (!initDone) return; // WLEDMM bugfix unsigned long now = millis(); while (drawing && millis()-now < 250) delay(1); // wait if someone else is drawing drawing = true; @@ -952,10 +1093,11 @@ class FourLineDisplayUsermod : public Usermod { /** * Enable sleep (turn the display off) or clock mode. */ - void sleepOrClock(bool enabled) { - if (enabled) { + void sleepOrClock(bool sleepEnable) { + if (sleepEnable) { displayTurnedOff = true; - if (clockMode && ntpEnabled) { + //setContrast(contrastFix? 2+ contrast/4 : 0); // un-comment to dim display in "clock mode" + if (clockMode) { // WLEDMM removed " && ntpEnabled" knownMinute = knownHour = 99; showTime(); } else @@ -963,6 +1105,7 @@ class FourLineDisplayUsermod : public Usermod { } else { displayTurnedOff = false; setPowerSave(0); + //setContrast(contrast); // un-comment to restore display brightness on wakeup } } @@ -1059,7 +1202,7 @@ class FourLineDisplayUsermod : public Usermod { xTaskCreateUniversal( // this is guaranteed to work on any ESP32 (single or dual core) [](void * par) { // Function to implement the task // see https://www.freertos.org/vtaskdelayuntil.html - const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2; + const TickType_t xFrequency = REFRESH_RATE_MS * portTICK_PERIOD_MS / 2; TickType_t xLastWakeTime = xTaskGetTickCount(); for(;;) { delay(1); // DO NOT DELETE THIS LINE! It is needed to give the IDLE(0) task enough time and to keep the watchdog happy. @@ -1120,7 +1263,9 @@ class FourLineDisplayUsermod : public Usermod { oappend(SET_F("addOption(dd,'SSD1305 128x64',5);")); oappend(SET_F("addOption(dd,'SSD1306 SPI',6);")); oappend(SET_F("addOption(dd,'SSD1306 SPI 128x64',7);")); - bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64); + oappend(SET_F("addOption(dd,'SSD1309 SPI 128x64',8);")); + oappend(SET_F("addOption(dd,'SSD1327 SPI 128x128',9);")); + bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type > 7); // WLEDMM add defaults oappend(SET_F("addInfo('4LineDisplay:pin[]',0,'','I2C/SPI CLK');")); oappend(SET_F("dRO('4LineDisplay:pin[]',0);")); // disable read only pins @@ -1183,7 +1328,7 @@ class FourLineDisplayUsermod : public Usermod { void addToConfig(JsonObject& root) { // determine if we are using global HW pins (data & clock) int8_t hw_dta, hw_clk; - if ((type == SSD1306_SPI || type == SSD1306_SPI64)) { + if ((type == SSD1306_SPI || type == SSD1306_SPI64) || (type > 7)) { hw_clk = spi_sclk; hw_dta = spi_mosi; } else { @@ -1249,7 +1394,7 @@ class FourLineDisplayUsermod : public Usermod { clockMode = top[FPSTR(_clockMode)] | clockMode; showSeconds = top[FPSTR(_showSeconds)] | showSeconds; contrastFix = top[FPSTR(_contrastFix)] | contrastFix; - if (newType == SSD1306_SPI || newType == SSD1306_SPI64) + if (newType == SSD1306_SPI || newType == SSD1306_SPI64 || newType > 7) ioFrequency = min(20000, max(500, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency else ioFrequency = min(3400, max(100, (int)(top[FPSTR(_busClkFrequency)] | ioFrequency/1000))) * 1000; // limit frequency @@ -1279,14 +1424,17 @@ class FourLineDisplayUsermod : public Usermod { USER_PRINTLN(F("Display terminated.")); } PinOwner po = PinOwner::UM_FourLineDisplay; - bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64); + bool isSPI = (type == SSD1306_SPI || type == SSD1306_SPI64 || type > 7); if (isSPI) { pinManager.deallocateMultiplePins((const uint8_t *)(&oldPin[2]), 3, po); bool isHW = (oldPin[0]==spi_sclk && oldPin[1]==spi_mosi); + if (oldPin[0]==-1 && oldPin[1]==-1) isHW = true; // WLEDMM "use global" means hardware driver + if (spi_sclk==-1 && spi_mosi==-1) isHW = false; // WLEDMM global pins not set -> software driver if (isHW) po = PinOwner::HW_SPI; } else { - bool isHW = (oldPin[0]==i2c_scl && oldPin[1]==i2c_sda); - if (isHW) po = PinOwner::HW_I2C; + //bool isHW = (oldPin[0]==i2c_scl && oldPin[1]==i2c_sda); + //if ((ioPin[0] == -1) || (ioPin[1] == -1)) isHW = true; // WLEDMM "use global" = hardware + //if (isHW) po = PinOwner::HW_I2C; // WLEDMM don't try to de-alloc HW pins. } pinManager.deallocateMultiplePins((const uint8_t *)oldPin, 2, po); type = newType; @@ -1333,3 +1481,8 @@ const char FourLineDisplayUsermod::_contrastFix[] PROGMEM = "contrastFix"; #ifdef ARDUINO_ARCH_ESP32 FourLineDisplayUsermod *FourLineDisplayUsermod::instance = nullptr; #endif + +// WLEDMM clean up some macros, so they don't cause problems in other usermods +#undef FLD_SemaphoreTake +#undef FLD_SemaphoreGive + diff --git a/usermods/usermod_v2_games/usermod_v2_games.h b/usermods/usermod_v2_games/usermod_v2_games.h index 5256f5c5..1b1f9047 100644 --- a/usermods/usermod_v2_games/usermod_v2_games.h +++ b/usermods/usermod_v2_games/usermod_v2_games.h @@ -183,7 +183,7 @@ uint16_t mode_IMUTest(void) { uint8_t y = 0; - if (IMU != nullptr) { + if ((IMU != nullptr) && (IMU->dmpReady)) { SEGMENT.setPixelColorXY(SEGMENT.virtualWidth() * (IMU->aa.x+INT16_MAX)/(2*INT16_MAX), y+=1, BLUE); SEGMENT.setPixelColorXY(SEGMENT.virtualWidth() * (IMU->aa.y+INT16_MAX)/(2*INT16_MAX), y+=1, BLUE); SEGMENT.setPixelColorXY(SEGMENT.virtualWidth() * (IMU->aa.z+INT16_MAX)/(2*INT16_MAX), y+=1, BLUE); @@ -280,7 +280,7 @@ uint16_t mode_3DIMUCube(void) { float roll = 0; #ifdef USERMOD_MPU6050_IMU - if (IMU != nullptr) { + if ((IMU != nullptr) && (IMU->dmpReady)) { yaw = -IMU->ypr[0]; pitch = IMU->ypr[1]; roll = IMU->ypr[2]; @@ -319,7 +319,7 @@ uint16_t mode_3DIMUCube(void) { return FRAMETIME; } -static const char _data_FX_MODE_3DIMUCube[] PROGMEM = "🎮 3DIMUCube ☾@,Perspective;!;!;2;pal=1"; //random cycle +static const char _data_FX_MODE_3DIMUCube[] PROGMEM = "🎮 3DIMUCube ☾@,Perspective;!;!;2;pal=1"; //WLEDMM random smooth class GamesUsermod : public Usermod { private: @@ -330,9 +330,9 @@ class GamesUsermod : public Usermod { strip.addEffect(255, &mode_pongGame, _data_FX_MODE_PONGGAME); #ifdef USERMOD_MPU6050_IMU IMU = (MPU6050Driver *)usermods.lookup(USERMOD_ID_IMU); - // #ifdef WLED_DEBUG + #ifdef WLED_DEBUG strip.addEffect(255, &mode_IMUTest, _data_FX_MODE_IMUTest); - // #endif + #endif #endif strip.addEffect(255, &mode_3DIMUCube, _data_FX_MODE_3DIMUCube); //works also without IMU } diff --git a/usermods/usermod_v2_klipper_percentage/readme.md b/usermods/usermod_v2_klipper_percentage/readme.md new file mode 100644 index 00000000..0619bf85 --- /dev/null +++ b/usermods/usermod_v2_klipper_percentage/readme.md @@ -0,0 +1,40 @@ +# Klipper Percentage Usermod +This usermod polls the Klipper API every 10s for the progressvalue. +The leds are then filled with a solid color according to that progress percentage. +the solid color is the secondary color of the segment. + +A corresponding curl command would be: +``` +curl --location --request GET 'http://[]/printer/objects/query?virtual_sdcard=progress' +``` +## Usage +Compile the source with the buildflag `-D USERMOD_KLIPPER_PERCENTAGE` added. + +You can also use the WLBD bot in the Discord by simply extending an exsisting build enviroment: +``` +[env:esp32klipper] +extends = env:esp32dev +build_flags = ${common.build_flags_esp32} -D USERMOD_KLIPPER_PERCENTAGE +``` + +## Settings + +### Enabled: +Checkbox to enable or disable the overlay + +### Klipper IP: +IP adress of your Klipper instance you want to poll. ESP has to be restarted after change + +### Direction : +0 = normal + +1 = reversed + +2 = center + +----- +Author: + +Sören Willrodt + +Discord: Sören#5281 \ No newline at end of file diff --git a/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h b/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h new file mode 100644 index 00000000..0e19cc80 --- /dev/null +++ b/usermods/usermod_v2_klipper_percentage/usermod_v2_klipper_percentage.h @@ -0,0 +1,222 @@ +#pragma once + +#include "wled.h" + +class klipper_percentage : public Usermod +{ +private: + unsigned long lastTime = 0; + String ip = "192.168.25.207"; + WiFiClient wifiClient; + char errorMessage[100] = ""; + int printPercent = 0; + int direction = 0; // 0 for along the strip, 1 for reversed direction + + static const char _name[]; + static const char _enabled[]; + bool enabled = false; + + void httpGet(WiFiClient &client, char *errorMessage) + { + // https://arduinojson.org/v6/example/http-client/ + // is this the most compact way to do http get and put it in arduinojson object??? + // would like async response ... ??? + client.setTimeout(10000); + if (!client.connect(ip.c_str(), 80)) + { + strcat(errorMessage, PSTR("Connection failed")); + } + else + { + // Send HTTP request + client.println(F("GET /printer/objects/query?virtual_sdcard=progress HTTP/1.0")); + client.println("Host: " + ip); + client.println(F("Connection: close")); + if (client.println() == 0) + { + strcat(errorMessage, PSTR("Failed to send request")); + } + else + { + // Check HTTP status + char status[32] = {0}; + client.readBytesUntil('\r', status, sizeof(status)); + if (strcmp(status, "HTTP/1.1 200 OK") != 0) + { + strcat(errorMessage, PSTR("Unexpected response: ")); + strcat(errorMessage, status); + } + else + { + // Skip HTTP headers + char endOfHeaders[] = "\r\n\r\n"; + if (!client.find(endOfHeaders)) + { + strcat(errorMessage, PSTR("Invalid response")); + } + } + } + } + } + +public: + void setup() + { + } + + void connected() + { + } + + void loop() + { + if (enabled) + { + if (WLED_CONNECTED) + { + if (millis() - lastTime > 10000) + { + httpGet(wifiClient, errorMessage); + if (strcmp(errorMessage, "") == 0) + { + PSRAMDynamicJsonDocument klipperDoc(4096); // in practive about 2673 + DeserializationError error = deserializeJson(klipperDoc, wifiClient); + if (error) + { + strcat(errorMessage, PSTR("deserializeJson() failed: ")); + strcat(errorMessage, error.c_str()); + } + printPercent = (int)(klipperDoc["result"]["status"]["virtual_sdcard"]["progress"].as() * 100); + + DEBUG_PRINT("Percent: "); + DEBUG_PRINTLN((int)(klipperDoc["result"]["status"]["virtual_sdcard"]["progress"].as() * 100)); + DEBUG_PRINT("LEDs: "); + DEBUG_PRINTLN(direction == 2 ? (strip.getLengthTotal() / 2) * printPercent / 100 : strip.getLengthTotal() * printPercent / 100); + } + else + { + DEBUG_PRINTLN(errorMessage); + DEBUG_PRINTLN(ip); + } + lastTime = millis(); + } + } + } + } + + void addToConfig(JsonObject &root) + { + JsonObject top = root.createNestedObject("Klipper Printing Percentage"); + top["Enabled"] = enabled; + top["Klipper IP"] = ip; + top["Direction"] = direction; + } + + 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["Klipper Printing Percentage"]; + + bool configComplete = !top.isNull(); + configComplete &= getJsonValue(top["Klipper IP"], ip); + configComplete &= getJsonValue(top["Enabled"], enabled); + configComplete &= getJsonValue(top["Direction"], direction); + return configComplete; + } + + /* + * 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["u"]; + if (user.isNull()) + user = root.createNestedObject("u"); + + JsonArray infoArr = user.createNestedArray(FPSTR(_name)); + String uiDomString = F(""); + infoArr.add(uiDomString); + } + + void addToJsonState(JsonObject &root) + { + JsonObject usermod = root[FPSTR(_name)]; + if (usermod.isNull()) + { + usermod = root.createNestedObject(FPSTR(_name)); + } + usermod["on"] = enabled; + } + void readFromJsonState(JsonObject &root) + { + JsonObject usermod = root[FPSTR(_name)]; + if (!usermod.isNull()) + { + if (usermod[FPSTR(_enabled)].is()) + { + enabled = usermod[FPSTR(_enabled)].as(); + } + } + } + + /* + * 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() + { + if (enabled) + { + if (direction == 0) // normal + { + for (int i = 0; i < strip.getLengthTotal() * printPercent / 100; i++) + { + strip.setPixelColor(i, strip.getSegment(0).colors[1]); + } + } + else if (direction == 1) // reversed + { + for (int i = 0; i < strip.getLengthTotal() * printPercent / 100; i++) + { + strip.setPixelColor(strip.getLengthTotal() - i, strip.getSegment(0).colors[1]); + } + } + else if (direction == 2) // center + { + for (int i = 0; i < (strip.getLengthTotal() / 2) * printPercent / 100; i++) + { + strip.setPixelColor((strip.getLengthTotal() / 2) + i, strip.getSegment(0).colors[1]); + strip.setPixelColor((strip.getLengthTotal() / 2) - i, strip.getSegment(0).colors[1]); + } + } + else + { + direction = 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_KLIPPER; + } +}; +const char klipper_percentage::_name[] PROGMEM = "Klipper_Percentage"; +const char klipper_percentage::_enabled[] PROGMEM = "enabled"; \ No newline at end of file diff --git a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h index 526ee7a0..96539658 100644 --- a/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h +++ b/usermods/usermod_v2_rotary_encoder_ui_ALT/usermod_v2_rotary_encoder_ui_ALT.h @@ -348,8 +348,10 @@ public: findCurrentEffectAndPalette(); } - if (modes_alpha_indexes[effectCurrentIndex] != effectCurrent || palettes_alpha_indexes[effectPaletteIndex] != effectPalette) { - currentEffectAndPaletteInitialized = false; + if (modes_alpha_indexes != nullptr) { // WLEDMM bugfix + if (modes_alpha_indexes[effectCurrentIndex] != effectCurrent || palettes_alpha_indexes[effectPaletteIndex] != effectPalette) { + currentEffectAndPaletteInitialized = false; + } } if (currentTime - loopTime >= 2) // 2ms since last check of encoder = 500Hz @@ -469,11 +471,13 @@ public: void displayNetworkInfo() { #ifdef USERMOD_FOUR_LINE_DISPLAY + if (display != nullptr) display->networkOverlay(PSTR("NETWORK INFO"), 10000); #endif } void findCurrentEffectAndPalette() { + if (modes_alpha_indexes == nullptr) return; // WLEDMM bugfix currentEffectAndPaletteInitialized = true; for (uint8_t i = 0; i < strip.getModeCount(); i++) { if (modes_alpha_indexes[i] == effectCurrent) { @@ -510,7 +514,8 @@ public: // 6: fx changed 7: hue 8: preset cycle 9: blynk 10: alexa //setValuesFromFirstSelectedSeg(); //to make transition work on main segment (should no longer be required) stateUpdated(CALL_MODE_BUTTON); - updateInterfaces(CALL_MODE_BUTTON); + if ((millis() - lastInterfaceUpdate) > INTERFACE_UPDATE_COOLDOWN) // WLEDMM respect cooldown times, to avoid crash in AsyncWebSocketMessageBuffer + updateInterfaces(CALL_MODE_BUTTON); } void changeBrightness(bool increase) { @@ -522,7 +527,10 @@ public: } display->updateRedrawTime(); #endif - bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0); + byte lastBri = bri; + if (bri < 40) bri = max(min((increase ? bri+fadeAmount/2 : bri-fadeAmount/2), 255), 0); // WLEDMM slower steps when brightness < 16% + else bri = max(min((increase ? bri+fadeAmount : bri-fadeAmount), 255), 0); + if (lastBri != bri) stateChanged = true; // WLEDMM bugfix lampUdated(); #ifdef USERMOD_FOUR_LINE_DISPLAY if (display->canDraw()) // only draw if nothing else is drawing @@ -541,7 +549,7 @@ public: display->updateRedrawTime(); #endif effectCurrentIndex = max(min((increase ? effectCurrentIndex+1 : effectCurrentIndex-1), strip.getModeCount()-1), 0); - effectCurrent = modes_alpha_indexes[effectCurrentIndex]; + if (modes_alpha_indexes != nullptr) effectCurrent = modes_alpha_indexes[effectCurrentIndex]; stateChanged = true; if (applyToAll) { for (byte i=0; i?');")); - + oappend(SET_F("addHB('Weather');")); // WLEDMM + oappend(SET_F("dd=addDropdown('Weather','units');")); oappend(SET_F("addOption(dd,'Kelvin',0);")); oappend(SET_F("addOption(dd,'Celcius',1);")); @@ -349,9 +347,6 @@ class WeatherUsermod : public Usermod { } }; -// strings to reduce flash memory usage (used more than twice) -const char WeatherUsermod::_name[] PROGMEM = "Weather"; - // example openweathermap data // {"cod":"200","message":0,"cnt":40,"list":[ // {"dt":1663945200,"main":{"temp":18.05,"feels_like":17.79,"temp_min":17.64,"temp_max":18.05,"pressure":1014,"sea_level":1014,"grnd_level":1013,"humidity":72,"temp_kf":0.41},"weather":[{"id":500,"main":"Rain","description":"light rain","icon":"10d"}],"clouds":{"all":100},"wind":{"speed":4.32,"deg":238,"gust":5.6},"visibility":10000,"pop":0.48,"rain":{"3h":0.15},"sys":{"pod":"d"},"dt_txt":"2022-09-23 15:00:00"}, diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 8915e118..b2c64012 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -124,7 +124,7 @@ uint16_t blink(uint32_t color1, uint32_t color2, bool strobe, bool do_palette) { uint16_t mode_blink(void) { return blink(SEGCOLOR(0), SEGCOLOR(1), false, true); } -static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!"; +static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!;01"; /* @@ -133,7 +133,7 @@ static const char _data_FX_MODE_BLINK[] PROGMEM = "Blink@!,Duty cycle;!,!;!"; uint16_t mode_blink_rainbow(void) { return blink(SEGMENT.color_wheel(SEGENV.call & 0xFF), SEGCOLOR(1), false, false); } -static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequency,Blink duration;!,!;!"; +static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequency,Blink duration;!,!;!;01"; /* @@ -142,7 +142,7 @@ static const char _data_FX_MODE_BLINK_RAINBOW[] PROGMEM = "Blink Rainbow@Frequen uint16_t mode_strobe(void) { return blink(SEGCOLOR(0), SEGCOLOR(1), true, true); } -static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!"; +static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!;01"; /* @@ -151,7 +151,7 @@ static const char _data_FX_MODE_STROBE[] PROGMEM = "Strobe@!;!,!;!"; uint16_t mode_strobe_rainbow(void) { return blink(SEGMENT.color_wheel(SEGENV.call & 0xFF), SEGCOLOR(1), true, false); } -static const char _data_FX_MODE_STROBE_RAINBOW[] PROGMEM = "Strobe Rainbow@!;,!;!"; +static const char _data_FX_MODE_STROBE_RAINBOW[] PROGMEM = "Strobe Rainbow@!;,!;!;01"; /* @@ -350,7 +350,7 @@ uint16_t mode_breath(void) { return FRAMETIME; } -static const char _data_FX_MODE_BREATH[] PROGMEM = "Breathe@!;!,!;!"; +static const char _data_FX_MODE_BREATH[] PROGMEM = "Breathe@!;!,!;!;01"; /* @@ -366,7 +366,7 @@ uint16_t mode_fade(void) { return FRAMETIME; } -static const char _data_FX_MODE_FADE[] PROGMEM = "Fade@!;!,!;!"; +static const char _data_FX_MODE_FADE[] PROGMEM = "Fade@!;!,!;!;01"; /* @@ -754,7 +754,7 @@ uint16_t mode_multi_strobe(void) { return FRAMETIME; } -static const char _data_FX_MODE_MULTI_STROBE[] PROGMEM = "Strobe Mega@!,!;!,!;!"; +static const char _data_FX_MODE_MULTI_STROBE[] PROGMEM = "Strobe Mega@!,!;!,!;!;01"; /* @@ -976,6 +976,7 @@ static const char _data_FX_MODE_COLORFUL[] PROGMEM = "Colorful@!,Saturation;1,2, * Emulates a traffic light. */ uint16_t mode_traffic_light(void) { + if (SEGLEN == 1) return mode_static(); for (int i=0; i < SEGLEN; i++) SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(i, true, PALETTE_SOLID_WRAP, 1)); uint32_t mdelay = 500; @@ -1008,6 +1009,7 @@ static const char _data_FX_MODE_TRAFFIC_LIGHT[] PROGMEM = "Traffic Light@!,US st */ #define FLASH_COUNT 4 uint16_t mode_chase_flash(void) { + if (SEGLEN == 1) return mode_static(); uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1); for (int i = 0; i < SEGLEN; i++) { @@ -1037,6 +1039,7 @@ static const char _data_FX_MODE_CHASE_FLASH[] PROGMEM = "Chase Flash@!;Bg,Fx;!"; * Prim flashes running, followed by random color. */ uint16_t mode_chase_flash_random(void) { + if (SEGLEN == 1) return mode_static(); uint8_t flash_step = SEGENV.call % ((FLASH_COUNT * 2) + 1); for (int i = 0; i < SEGENV.aux1; i++) { @@ -1170,6 +1173,7 @@ static const char _data_FX_MODE_DUAL_LARSON_SCANNER[] PROGMEM = "Scanner Dual@!, * Firing comets from one end. "Lighthouse" */ uint16_t mode_comet(void) { + if (SEGLEN == 1) return mode_static(); uint16_t counter = strip.now * ((SEGMENT.speed >>2) +1); uint16_t index = (counter * SEGLEN) >> 16; if (SEGENV.call == 0) SEGENV.aux0 = index; @@ -1197,7 +1201,8 @@ static const char _data_FX_MODE_COMET[] PROGMEM = "Lighthouse@!,Fade rate;!,!;!" * Fireworks function. */ uint16_t mode_fireworks() { - const uint16_t width = strip.isMatrix ? SEGMENT.virtualWidth() : SEGMENT.virtualLength(); + if (SEGLEN == 1) return mode_static(); + const uint16_t width = SEGMENT.is2D() ? SEGMENT.virtualWidth() : SEGMENT.virtualLength(); const uint16_t height = SEGMENT.virtualHeight(); if (SEGENV.call == 0) { @@ -1211,18 +1216,18 @@ uint16_t mode_fireworks() { bool valid1 = (SEGENV.aux0 < width*height); bool valid2 = (SEGENV.aux1 < width*height); uint32_t sv1 = 0, sv2 = 0; - if (valid1) sv1 = strip.isMatrix ? SEGMENT.getPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width) : SEGMENT.getPixelColor(SEGENV.aux0); // get spark color - if (valid2) sv2 = strip.isMatrix ? SEGMENT.getPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width) : SEGMENT.getPixelColor(SEGENV.aux1); + if (valid1) sv1 = SEGMENT.is2D() ? SEGMENT.getPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width) : SEGMENT.getPixelColor(SEGENV.aux0); // get spark color + if (valid2) sv2 = SEGMENT.is2D() ? SEGMENT.getPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width) : SEGMENT.getPixelColor(SEGENV.aux1); if (!SEGENV.step) SEGMENT.blur(16); - if (valid1) { if (strip.isMatrix) SEGMENT.setPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width, sv1); else SEGMENT.setPixelColor(SEGENV.aux0, sv1); } // restore spark color after blur - if (valid2) { if (strip.isMatrix) SEGMENT.setPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width, sv2); else SEGMENT.setPixelColor(SEGENV.aux1, sv2); } // restore old spark color after blur + if (valid1) { if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(SEGENV.aux0%width, SEGENV.aux0/width, sv1); else SEGMENT.setPixelColor(SEGENV.aux0, sv1); } // restore spark color after blur + if (valid2) { if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(SEGENV.aux1%width, SEGENV.aux1/width, sv2); else SEGMENT.setPixelColor(SEGENV.aux1, sv2); } // restore old spark color after blur for (int i=0; i> 1)) == 0) { uint16_t index = random16(width*height); uint16_t j = index % width, k = index / width; uint32_t col = SEGMENT.color_from_palette(random8(), false, false, 0); - if (strip.isMatrix) SEGMENT.setPixelColorXY(j, k, col); + if (SEGMENT.is2D()) SEGMENT.setPixelColorXY(j, k, col); else SEGMENT.setPixelColor(index, col); SEGENV.aux1 = SEGENV.aux0; // old spark SEGENV.aux0 = index; // remember where spark occured @@ -1234,8 +1239,8 @@ static const char _data_FX_MODE_FIREWORKS[] PROGMEM = "Fireworks@,Frequency;!,!; //Twinkling LEDs running. Inspired by https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Rain.h -uint16_t mode_rain() -{ +uint16_t mode_rain() { + if (SEGLEN == 1) return mode_static(); const uint16_t width = SEGMENT.virtualWidth(); const uint16_t height = SEGMENT.virtualHeight(); SEGENV.step += FRAMETIME; @@ -1294,7 +1299,7 @@ uint16_t mode_fire_flicker(void) { SEGENV.step = it; return FRAMETIME; } -static const char _data_FX_MODE_FIRE_FLICKER[] PROGMEM = "Fire Flicker@!,!;!;!;;pal=0"; //WLEDMM pal=0 +static const char _data_FX_MODE_FIRE_FLICKER[] PROGMEM = "Fire Flicker@!,!;!;!;01;pal=0"; //WLEDMM pal=0 /* @@ -1345,8 +1350,8 @@ static const char _data_FX_MODE_LOADING[] PROGMEM = "Loading@!,Fade;!,!;!;;ix=16 //American Police Light with all LEDs Red and Blue -uint16_t police_base(uint32_t color1, uint32_t color2) -{ +uint16_t police_base(uint32_t color1, uint32_t color2) { + if (SEGLEN == 1) return mode_static(); uint16_t delay = 1 + (FRAMETIME<<3) / SEGLEN; // longer segments should change faster uint32_t it = strip.now / map(SEGMENT.speed, 0, 255, delay<<4, delay); uint16_t offset = it % SEGLEN; @@ -1794,9 +1799,9 @@ uint16_t mode_oscillate(void) { } } - for (int i=0; i < SEGLEN; i++) { + for (int i = 0; i < SEGLEN; i++) { uint32_t color = BLACK; - for (int j=0; j < numOscillators; j++) { + for (int j = 0; j < numOscillators; j++) { if(i >= oscillators[j].pos - oscillators[j].size && i <= oscillators[j].pos + oscillators[j].size) { color = (color == BLACK) ? SEGCOLOR(j) : color_blend(color, SEGCOLOR(j), 128); } @@ -1812,6 +1817,7 @@ static const char _data_FX_MODE_OSCILLATE[] PROGMEM = "Oscillate"; //TODO uint16_t mode_lightning(void) { + if (SEGLEN == 1) return mode_static(); uint16_t ledstart = random16(SEGLEN); // Determine starting location of flash uint16_t ledlen = 1 + random16(SEGLEN -ledstart); // Determine length of flash (not to go beyond NUM_LEDS-1) uint8_t bri = 255/random8(1, 3); @@ -1872,7 +1878,6 @@ uint16_t mode_pride_2015(void) { sPseudotime += duration * msmultiplier; sHue16 += duration * beatsin88( 400, 5,9); uint16_t brightnesstheta16 = sPseudotime; - CRGB fastled_col; for (int i = 0 ; i < SEGLEN; i++) { hue16 += hueinc16; @@ -1898,6 +1903,7 @@ static const char _data_FX_MODE_PRIDE_2015[] PROGMEM = "Pride 2015@!;;"; //eight colored dots, weaving in and out of sync with each other uint16_t mode_juggle(void) { + if (SEGLEN == 1) return mode_static(); if (SEGENV.call == 0) { SEGMENT.setUpLeds(); //lossless getPixelColor() SEGMENT.fill(BLACK); @@ -1967,6 +1973,7 @@ static const char _data_FX_MODE_PALETTE[] PROGMEM = "Palette@Cycle speed;;!;;c3= // feel of your fire: COOLING (used in step 1 above) (Speed = COOLING), and SPARKING (used // in step 3 above) (Effect Intensity = Sparking). uint16_t mode_fire_2012() { + if (SEGLEN == 1) return mode_static(); const uint16_t strips = SEGMENT.nrOfVStrips(); if (!SEGENV.allocateData(strips * SEGLEN)) return mode_static(); //allocation failed byte* heat = SEGENV.data; @@ -2267,6 +2274,7 @@ static const char _data_FX_MODE_LAKE[] PROGMEM = "Lake@!;Fx;!"; // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t mode_meteor() { + if (SEGLEN == 1) return mode_static(); if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed byte* trail = SEGENV.data; @@ -2304,6 +2312,7 @@ static const char _data_FX_MODE_METEOR[] PROGMEM = "Meteor@!,Trail length;!;!"; // send a meteor from begining to to the end of the strip with a trail that randomly decays. // adapted from https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain uint16_t mode_meteor_smooth() { + if (SEGLEN == 1) return mode_static(); if (!SEGENV.allocateData(SEGLEN)) return mode_static(); //allocation failed byte* trail = SEGENV.data; @@ -2341,6 +2350,7 @@ static const char _data_FX_MODE_METEOR_SMOOTH[] PROGMEM = "Meteor Smooth@!,Trail //Railway Crossing / Christmas Fairy lights uint16_t mode_railway() { + if (SEGLEN == 1) return mode_static(); uint16_t dur = (256 - SEGMENT.speed) * 40; uint16_t rampdur = (dur * SEGMENT.intensity) >> 8; if (SEGENV.step > dur) @@ -2441,6 +2451,7 @@ uint16_t ripple_base() uint16_t mode_ripple(void) { + if (SEGLEN == 1) return mode_static(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); return ripple_base(); } @@ -2448,6 +2459,7 @@ static const char _data_FX_MODE_RIPPLE[] PROGMEM = "Ripple@!,Wave #,,,,,Overlay; uint16_t mode_ripple_rainbow(void) { + if (SEGLEN == 1) return mode_static(); if (SEGENV.call ==0) { SEGENV.aux0 = random8(); SEGENV.aux1 = random8(); @@ -2612,6 +2624,7 @@ static const char _data_FX_MODE_TWINKLECAT[] PROGMEM = "Twinklecat@!,Twinkle rat //inspired by https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectBlinkingHalloweenEyes uint16_t mode_halloween_eyes() { + if (SEGLEN == 1) return mode_static(); const uint16_t maxWidth = strip.isMatrix ? SEGMENT.virtualWidth() : SEGLEN; const uint16_t HALLOWEEN_EYE_SPACE = MAX(2, strip.isMatrix ? SEGMENT.virtualWidth()>>4: SEGLEN>>5); const uint16_t HALLOWEEN_EYE_WIDTH = HALLOWEEN_EYE_SPACE/2; @@ -2721,6 +2734,7 @@ static const char _data_FX_MODE_TRI_STATIC_PATTERN[] PROGMEM = "Solid Pattern Tr uint16_t spots_base(uint16_t threshold) { + if (SEGLEN == 1) return mode_static(); if (!SEGMENT.check2) SEGMENT.fill(SEGCOLOR(1)); uint16_t maxZones = SEGLEN >> 2; @@ -2776,6 +2790,7 @@ typedef struct Ball { * Bouncing Balls Effect */ uint16_t mode_bouncing_balls(void) { + if (SEGLEN == 1) return mode_static(); //allocate segment data const uint16_t strips = SEGMENT.nrOfVStrips(); // adapt for 2D const size_t maxNumBalls = 16; @@ -2848,6 +2863,7 @@ static const char _data_FX_MODE_BOUNCINGBALLS[] PROGMEM = "Bouncing Balls@Gravit * Sinelon stolen from FASTLED examples */ uint16_t sinelon_base(bool dual, bool rainbow=false) { + if (SEGLEN == 1) return mode_static(); SEGMENT.fade_out(SEGMENT.intensity); uint16_t pos = beatsin16(SEGMENT.speed/10,0,SEGLEN-1); if (SEGENV.call == 0) SEGENV.aux0 = pos; @@ -2945,6 +2961,7 @@ typedef struct Spark { * modified from https://github.com/kitesurfer1404/WS2812FX/blob/master/src/custom/Popcorn.h */ uint16_t mode_popcorn(void) { + if (SEGLEN == 1) return mode_static(); //allocate segment data uint16_t strips = SEGMENT.nrOfVStrips(); uint16_t dataSize = sizeof(spark) * maxNumPopcorn; @@ -3087,7 +3104,7 @@ uint16_t mode_candle() { return candle(false); } -static const char _data_FX_MODE_CANDLE[] PROGMEM = "Candle@!,!;!,!;!;1;sx=96,ix=224,pal=0"; +static const char _data_FX_MODE_CANDLE[] PROGMEM = "Candle@!,!;!,!;!;01;sx=96,ix=224,pal=0"; uint16_t mode_candle_multi() @@ -3118,6 +3135,7 @@ typedef struct particle { } star; uint16_t mode_starburst(void) { + if (SEGLEN == 1) return mode_static(); uint16_t maxData = FAIR_DATA_PER_SEG; //ESP8266: 256 ESP32: 640 uint8_t segs = strip.getActiveSegmentsNum(); if (segs <= (strip.getMaxSegments() /2)) maxData *= 2; //ESP8266: 512 if <= 8 segs ESP32: 1280 if <= 16 segs @@ -3237,6 +3255,7 @@ static const char _data_FX_MODE_STARBURST[] PROGMEM = "Fireworks Starburst@Chanc */ uint16_t mode_exploding_fireworks(void) { + if (SEGLEN == 1) return mode_static(); const uint16_t cols = strip.isMatrix ? SEGMENT.virtualWidth() : 1; const uint16_t rows = strip.isMatrix ? SEGMENT.virtualHeight() : SEGMENT.virtualLength(); @@ -3371,6 +3390,7 @@ static const char _data_FX_MODE_EXPLODING_FIREWORKS[] PROGMEM = "Fireworks 1D@Gr */ uint16_t mode_drip(void) { + if (SEGLEN == 1) return mode_static(); //allocate segment data uint16_t strips = SEGMENT.nrOfVStrips(); const int maxNumDrops = 4; @@ -3468,6 +3488,7 @@ typedef struct Tetris { } tetris; uint16_t mode_tetrix(void) { + if (SEGLEN == 1) return mode_static(); uint16_t strips = SEGMENT.nrOfVStrips(); // allow running on virtual strips (columns in 2D segment) uint16_t dataSize = sizeof(tetris); if (!SEGENV.allocateData(dataSize * strips)) return mode_static(); //allocation failed @@ -3510,7 +3531,7 @@ uint16_t mode_tetrix(void) { if (drop->pos > drop->stack) { // fall until top of stack drop->pos -= drop->speed; // may add gravity as: speed += gravity if (int(drop->pos) < int(drop->stack)) drop->pos = drop->stack; - for (int i=int(drop->pos); ipos); i < SEGLEN; i++) { uint32_t col = ipos)+drop->brick ? SEGMENT.color_from_palette(drop->col, false, false, 0) : SEGCOLOR(1); SEGMENT.setPixelColor(indexToVStrip(i, stripNr), col); } @@ -3525,7 +3546,7 @@ uint16_t mode_tetrix(void) { drop->brick = 0; // reset brick size (no more growing) if (drop->step > millis()) { // allow fading of virtual strip - for (int i=0; istack = 0; // reset brick stack size drop->step = 0; // proceed with next brick @@ -3652,7 +3673,7 @@ uint16_t mode_heartbeat(void) { return FRAMETIME; } -static const char _data_FX_MODE_HEARTBEAT[] PROGMEM = "Heartbeat@!,!;!,!;!;;m12=1"; //Bar +static const char _data_FX_MODE_HEARTBEAT[] PROGMEM = "Heartbeat@!,!;!,!;!;01;m12=1"; //Bar // "Pacifica" @@ -3776,6 +3797,7 @@ static const char _data_FX_MODE_PACIFICA[] PROGMEM = "Pacifica@!,Angle;;!;;pal=5 * Mode simulates a gradual sunrise */ uint16_t mode_sunrise() { + if (SEGLEN == 1) return mode_static(); //speed 0 - static sun //speed 1 - 60: sunrise time in minutes //speed 60 - 120 : sunset time in minutes - 60; @@ -3869,7 +3891,7 @@ static const char _data_FX_MODE_PHASEDNOISE[] PROGMEM = "Phased Noise@!,!;!,!;!" uint16_t mode_twinkleup(void) { // A very short twinkle routine with fade-in and dual controls. By Andrew Tuline. random16_set_seed(535); // The randomizer needs to be re-set each time through the loop in order for the same 'random' numbers to be the same each time through. - for (int i = 0; i SEGMENT.intensity) pixBri = 0; @@ -3931,7 +3953,7 @@ uint16_t mode_sinewave(void) { // Adjustable sinewave. By Andrew Tul SEGENV.step += SEGMENT.speed/16; // Speed of animation. uint16_t freq = SEGMENT.intensity/4;//SEGMENT.fft2/8; // Frequency of the signal. - for (int i=0; i> 4)); uint16_t numBirds = 2 + (SEGLEN >> 3); // 2 + 1/8 of a segment @@ -4037,6 +4060,7 @@ typedef struct Spotlight { */ uint16_t mode_dancing_shadows(void) { + if (SEGLEN == 1) return mode_static(); uint8_t numSpotlights = map(SEGMENT.intensity, 0, 255, 2, SPOT_MAX_COUNT); // 49 on 32 segment ESP32, 17 on 16 segment ESP8266 bool initialize = SEGENV.aux0 != numSpotlights; SEGENV.aux0 = numSpotlights; @@ -4163,7 +4187,7 @@ uint16_t mode_washing_machine(void) { SEGENV.step += (speed * 128.0f); - for (int i=0; i> 7)); SEGMENT.setPixelColor(i, SEGMENT.color_from_palette(col, false, PALETTE_SOLID_WRAP, 3)); } @@ -4500,7 +4524,7 @@ static const char _data_FX_MODE_AURORA[] PROGMEM = "Aurora@!,!;1,2,3;!;;sx=24,pa // 16 bit perlinmove. Use Perlin Noise instead of sinewaves for movement. By Andrew Tuline. // Controls are speed, # of pixels, faderate. uint16_t mode_perlinmove(void) { - + if (SEGLEN == 1) return mode_static(); SEGMENT.fade_out(255-SEGMENT.custom1); for (int i = 0; i < SEGMENT.intensity/16 + 1; i++) { uint16_t locn = inoise16(millis()*128/(260-SEGMENT.speed)+i*15000, millis()*128/(260-SEGMENT.speed)); // Get a new pixel location from moving noise. @@ -5796,8 +5820,8 @@ uint16_t mode_2Dfloatingblobs(void) { } } uint32_t c = SEGMENT.color_from_palette(blob->color[i], false, false, 0); - if (blob->r[i] > 1.f) SEGMENT.fill_circle(blob->y[i], blob->x[i], roundf(blob->r[i]), c); - else SEGMENT.setPixelColorXY(blob->y[i], blob->x[i], c); + if (blob->r[i] > 1.f) SEGMENT.fill_circle(blob->x[i], blob->y[i], roundf(blob->r[i]), c); + else SEGMENT.setPixelColorXY(blob->x[i], blob->y[i], c); // move x if (blob->x[i] + blob->r[i] >= cols - 1) blob->x[i] += (blob->sX[i] * ((cols - 1 - blob->x[i]) / blob->r[i] + 0.005f)); else if (blob->x[i] - blob->r[i] <= 0) blob->x[i] += (blob->sX[i] * (blob->x[i] / blob->r[i] + 0.005f)); @@ -6013,6 +6037,8 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli SEGMENT.custom1 = *binNum; SEGMENT.custom2 = *maxVol * 2; } + if (SEGMENT.custom1 < 2) SEGMENT.custom1 = 2; // WLEDMM prevent stupid settings + if (SEGMENT.custom2 < 48) SEGMENT.custom1 = 48; // WLEDMM prevent stupid settings *binNum = SEGMENT.custom1; // Select a bin. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. @@ -6363,7 +6389,7 @@ uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. SEGENV.aux0 = secondHand; int pixBri = volumeRaw * SEGMENT.intensity / 64; - for (int i=0; ithisphase += beatsin8(6,-4,4); // You can change direction and speed individually. plasmoip->thatphase += beatsin8(7,-4,4); // Two phase values to make a complex pattern. By Andrew Tuline. - for (int i=0; ithisphase) & 0xFF)/2; thisbright += cos8(((i*(97 +(5*SEGMENT.speed/32)))+plasmoip->thatphase) & 0xFF)/2; // Let's munge the brightness a bit and animate it all with the phases. @@ -6574,6 +6600,8 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. SEGMENT.custom1 = *binNum; SEGMENT.custom2 = *maxVol * 2; } + if (SEGMENT.custom1 < 2) SEGMENT.custom1 = 2; // WLEDMM prevent stupid settings + if (SEGMENT.custom2 < 48) SEGMENT.custom1 = 48; // WLEDMM prevent stupid settings *binNum = SEGMENT.custom1; // Select a bin. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. @@ -6706,6 +6734,7 @@ uint16_t mode_DJLight(void) { // Written by ??? Adapted by Wil um_data = simulateSound(SEGMENT.soundSim); } uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; + float volumeSmth = *(float*)um_data->u_data[0]; if (SEGENV.call == 0) { SEGMENT.setUpLeds(); @@ -6716,8 +6745,41 @@ uint16_t mode_DJLight(void) { // Written by ??? Adapted by Wil if (SEGENV.aux0 != secondHand) { // Triggered millis timing. SEGENV.aux0 = secondHand; - CRGB color = CRGB(fftResult[15]/2, fftResult[5]/2, fftResult[0]/2); // 16-> 15 as 16 is out of bounds - SEGMENT.setPixelColor(mid, color.fadeToBlackBy(map(fftResult[4], 0, 255, 255, 4))); // TODO - Update + CRGB color = CRGB(0,0,0); + // color = CRGB(fftResult[15]/2, fftResult[5]/2, fftResult[0]/2); // formula from 0.13.x (10Khz): R = 3880-5120, G=240-340, B=60-100 + if (!SEGENV.check1) { + color = CRGB(fftResult[12]/2, fftResult[3]/2, fftResult[1]/2); // formula for 0.14.x (22Khz): R = 3015-3704, G=216-301, B=86-129 + } else { + // candy factory: an attempt to get more colors + color = CRGB(fftResult[11]/2 + fftResult[12]/4 + fftResult[14]/4, // red : 2412-3704 + 4479-7106 + fftResult[4]/2 + fftResult[3]/4, // green: 216-430 + fftResult[0]/4 + fftResult[1]/4 + fftResult[2]/4); // blue: 46-216 + if ((color.getLuma() < 96) && (volumeSmth >= 1.5f)) { // enhance "almost dark" pixels with yellow, based on not-yet-used channels + unsigned yello_g = (fftResult[5] + fftResult[6] + fftResult[7]) / 3; + unsigned yello_r = (fftResult[7] + fftResult[8] + fftResult[9] + fftResult[10]) / 4; + color.green += (uint8_t) yello_g / 2; + color.red += (uint8_t) yello_r / 2; + } + } + + if (volumeSmth < 1.0f) color = CRGB(0,0,0); // silence = black + + // make colors less "pastel", by turning up color saturation in HSV space + if (color.getLuma() > 32) { // don't change "dark" pixels + CHSV hsvColor = rgb2hsv_approximate(color); + hsvColor.v = min(max(hsvColor.v, (uint8_t)48), (uint8_t)204); // 48 < brightness < 204 + if (SEGENV.check1) + hsvColor.s = max(hsvColor.s, (uint8_t)204); // candy factory mode: strongly turn up color saturation (> 192) + else + hsvColor.s = max(hsvColor.s, (uint8_t)108); // normal mode: turn up color saturation to avoid pastels + color = hsvColor; + } + //if (color.getLuma() > 12) color.maximizeBrightness(); // for testing + + //SEGMENT.setPixelColor(mid, color.fadeToBlackBy(map(fftResult[4], 0, 255, 255, 4))); // 0.13.x fade -> 180hz-260hz + uint8_t fadeVal = map(fftResult[3], 0, 255, 255, 4); // 0.14.x fade -> 216hz-301hz + if (SEGENV.check1) fadeVal = constrain(fadeVal, 0, 176); // "candy factory" mode - avoid complete fade-out + SEGMENT.setPixelColor(mid, color.fadeToBlackBy(fadeVal)); for (int i = SEGLEN - 1; i > mid; i--) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i-1)); // move to the left for (int i = 0; i < mid; i++) SEGMENT.setPixelColor(i, SEGMENT.getPixelColor(i+1)); // move to the right @@ -6725,7 +6787,7 @@ uint16_t mode_DJLight(void) { // Written by ??? Adapted by Wil return FRAMETIME; } // mode_DJLight() -static const char _data_FX_MODE_DJLIGHT[] PROGMEM = "DJ Light@Speed;;;1f;m12=2,si=0"; // Arc, Beatsin +static const char _data_FX_MODE_DJLIGHT[] PROGMEM = "DJ Light@Speed,,,,,Candy Factory;;;1f;m12=2,si=0"; // Arc, Beatsin //////////////////// @@ -6755,9 +6817,17 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(MAX_FREQ_LOG10 - 1.78f); // Scale log10 of frequency values to the 255 colour index. if (FFT_MajorPeak < 61.0f) pixCol = 0; // handle underflow +#if defined(ARDUINO_ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) && !defined(CONFIG_IDF_TARGET_ESP32C3) + uint16_t bright = (int) (sqrtf(my_magnitude)*16.0f); // WLEDMM sqrt scaling, to make peaks more prominent +#else uint16_t bright = (int)my_magnitude; +#endif SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), bright)); + if (SEGMENT.speed > 228) { // WLEDMM looks nice in 2D + SEGMENT.blur(5*(SEGMENT.speed - 224)); + SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), bright)); + } return FRAMETIME; } // mode_freqmap() @@ -7071,6 +7141,9 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin SEGMENT.custom2 = *maxVol * 2; } + if (SEGMENT.custom1 < 2) SEGMENT.custom1 = 2; // WLEDMM prevent stupid settings + if (SEGMENT.custom2 < 48) SEGMENT.custom1 = 48; // WLEDMM prevent stupid settings + *binNum = SEGMENT.custom1; // Select a bin. *maxVol = SEGMENT.custom2 / 2; // Our volume comparator. @@ -7087,7 +7160,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin } else { SEGMENT.setPixelColor(SEGLEN-1, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(pixCol+SEGMENT.intensity, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude)); } - for (int i=0; i(SEGENV.data); //array of previous bar heights per frequency band @@ -7131,12 +7205,39 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. int fadeoutDelay = (256 - SEGMENT.speed) / 64; if ((fadeoutDelay <= 1 ) || ((SEGENV.call % fadeoutDelay) == 0)) SEGMENT.fadeToBlackBy(SEGMENT.speed); + uint16_t lastBandHeight = 0; // WLEDMM: for smoothing out bars + + //WLEDMM: evenly ditribut bands + float bandwidth = (float)cols / NUM_BANDS; + float remaining = bandwidth; + uint8_t band = 0; for (int x=0; x < cols; x++) { - uint8_t band = map(x, 0, cols-1, 0, NUM_BANDS - 1); - if (NUM_BANDS < 16) band = map(band, 0, NUM_BANDS - 1, 0, 15); // always use full range. comment out this line to get the previous behaviour. - band = constrain(band, 0, 15); - uint16_t colorIndex = band * 17; - uint16_t barHeight = map(fftResult[band], 0, 255, 0, rows); // do not subtract -1 from rows here + //WLEDMM if not enough remaining + if (remaining < 1) {band++; remaining+= bandwidth;} //increase remaining but keep the current remaining + remaining--; //consume remaining + + // Serial.printf("x %d b %d n %d w %f %f\n", x, band, NUM_BANDS, bandwidth, remaining); + uint8_t frBand = ((NUM_BANDS < 16) && (NUM_BANDS > 1)) ? map(band, 0, NUM_BANDS - 1, 0, 15):band; // always use full range. comment out this line to get the previous behaviour. + // frBand = constrain(frBand, 0, 15); //WLEDMM can never be out of bounds (I think...) + uint16_t colorIndex = frBand * 17; //WLEDMM 0.255 + uint16_t bandHeight = fftResult[frBand]; // WLEDMM we use the original ffResult, to preserve accuracy + + // WLEDMM begin - smooth out bars + if ((x > 0) && (x < (cols-1)) && (SEGMENT.check2)) { + // get height of next (right side) bar + uint8_t nextband = (remaining < 1)? band +1: band; + nextband = constrain(nextband, 0, 15); // just to be sure + frBand = ((NUM_BANDS < 16) && (NUM_BANDS > 1)) ? map(nextband, 0, NUM_BANDS - 1, 0, 15):nextband; // always use full range. comment out this line to get the previous behaviour. + uint16_t nextBandHeight = fftResult[frBand]; + // smooth Band height + bandHeight = (7*bandHeight + 3*lastBandHeight + 3*nextBandHeight) / 12; // yeees, its 12 not 13 (10% amplification) + bandHeight = constrain(bandHeight, 0, 255); // remove potential over/underflows + colorIndex = map(x, 0, cols-1, 0, 255); //WLEDMM + } + lastBandHeight = bandHeight; // remember BandHeight (left side) for next iteration + uint16_t barHeight = map(bandHeight, 0, 255, 0, rows); // Now we map bandHeight to barHeight. do not subtract -1 from rows here + // WLEDMM end + if (barHeight > rows) barHeight = rows; // WLEDMM map() can "overshoot" due to rounding errors if (barHeight > previousBarHeight[x]) previousBarHeight[x] = barHeight; //drive the peak up @@ -7148,7 +7249,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. ledColor = SEGMENT.color_from_palette(colorIndex, false, PALETTE_SOLID_WRAP, 0); SEGMENT.setPixelColorXY(x, rows-1 - y, ledColor); } - if ((previousBarHeight[x] > 0) && (previousBarHeight[x] < rows)) // WLEDMM avoid "overshooting" into other segments + if ((SEGMENT.intensity < 255) && (previousBarHeight[x] > 0) && (previousBarHeight[x] < rows)) // WLEDMM avoid "overshooting" into other segments SEGMENT.setPixelColorXY(x, rows - previousBarHeight[x], (SEGCOLOR(2) != BLACK) ? SEGCOLOR(2) : ledColor); if (rippleTime && previousBarHeight[x]>0) previousBarHeight[x]--; //delay/ripple effect @@ -7156,13 +7257,13 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. #ifdef SR_DEBUG // WLEDMM: abuse top left/right pixels for peak detection debugging - SEGMENT.setPixelColorXY(cols-1, rows-1, (samplePeak > 0) ? GREEN : BLACK); - if (samplePeak > 0) SEGMENT.setPixelColorXY(0, rows-1, GREEN); + SEGMENT.setPixelColorXY(cols-1, 0, (samplePeak > 0) ? GREEN : BLACK); + if (samplePeak > 0) SEGMENT.setPixelColorXY(0, 0, GREEN); // WLEDMM end #endif return FRAMETIME; } // mode_2DGEQ() -static const char _data_FX_MODE_2DGEQ[] PROGMEM = "GEQ ☾@Fade speed,Ripple decay,# of bands,,,Color bars;!,,Peaks;!;2f;c1=255,c2=64,pal=11,si=0"; // Beatsin +static const char _data_FX_MODE_2DGEQ[] PROGMEM = "GEQ ☾@Fade speed,Ripple decay,# of bands,,,Color bars,Smooth bars ☾;!,,Peaks;!;2f;c1=255,c2=64,pal=11,si=0"; // Beatsin ///////////////////////// diff --git a/wled00/FX.h b/wled00/FX.h index 86ecd39e..f62ce24a 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -72,7 +72,11 @@ #ifndef MAX_NUM_SEGMENTS #define MAX_NUM_SEGMENTS 32 #endif - #define MAX_SEGMENT_DATA 32767 + #if defined(ARDUINO_ARCH_ESP32S2) + #define MAX_SEGMENT_DATA 24576 + #else + #define MAX_SEGMENT_DATA 32767 + #endif #endif /* How much data bytes each segment should max allocate to leave enough space for other segments, @@ -312,7 +316,7 @@ #define FX_MODE_WAVESINS 184 #define FX_MODE_ROCKTAVES 185 #define FX_MODE_2DAKEMI 186 -#define FX_MODE_CUSTOMEFFECT 187 //WLEDMM Custom Effects +#define FX_MODE_ARTIFX 187 //WLEDMM ARTIFX #define MODE_COUNT 188 @@ -322,8 +326,8 @@ typedef enum mapping1D2D { M12_pArc = 2, M12_pCorner = 3, M12_jMap = 4, //WLEDMM jMap - M12_sCircle = 5, //WLEDMM jMap - M12_sBlock = 6 //WLEDMM jMap + M12_sCircle = 5, //WLEDMM Circle + M12_sBlock = 6 //WLEDMM Block } mapping1D2D_t; // segment, 72 bytes @@ -465,7 +469,7 @@ typedef struct Segment { _dataLen(0), _t(nullptr) { - refreshLightCapabilities(); + //refreshLightCapabilities(); } Segment(uint16_t sStartX, uint16_t sStopX, uint16_t sStartY, uint16_t sStopY) : Segment(sStartX, sStopX) { @@ -501,6 +505,9 @@ typedef struct Segment { inline bool isSelected(void) const { return selected; } inline bool isActive(void) const { return stop > start; } inline bool is2D(void) const { return (width()>1 && height()>1); } + inline bool hasRGB(void) const { return _isRGB; } + inline bool hasWhite(void) const { return _hasW; } + inline bool isCCT(void) const { return _isCCT; } inline uint16_t width(void) const { return stop - start; } // segment width in physical pixels (length if 1D) inline uint16_t height(void) const { return stopY - startY; } // segment height (if 2D) in physical pixels inline uint16_t length(void) const { return width() * height(); } // segment length (count) in physical pixels @@ -668,7 +675,6 @@ class WS2812FX { // 96 bytes isMatrix(false), #ifndef WLED_DISABLE_2D panels(1), - matrix{0,0,0,0}, #endif // semi-private (just obscured) used in effect functions through macros _currentPalette(CRGBPalette16(CRGB::Black)), @@ -721,7 +727,6 @@ class WS2812FX { // 96 bytes finalizeInit(), service(void), setMode(uint8_t segid, uint8_t m), - setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0), setColor(uint8_t slot, uint32_t c), setCCT(uint16_t k), setBrightness(uint8_t b, bool direct = false), @@ -737,10 +742,10 @@ class WS2812FX { // 96 bytes setPixelColor(int n, uint32_t c), show(void), setTargetFps(uint8_t fps), - deserializeMap(uint8_t n=0), enumerateLedmaps(); //WLEDMM (from fcn_declare) - void fill(uint32_t c) { for (int i = 0; i < _length; i++) setPixelColor(i, c); } // fill whole strip with color (inline) + void setColor(uint8_t slot, uint8_t r, uint8_t g, uint8_t b, uint8_t w = 0) { setColor(slot, RGBW32(r,g,b,w)); } + void fill(uint32_t c) { for (int i = 0; i < getLengthTotal(); i++) setPixelColor(i, c); } // fill whole strip with color (inline) void addEffect(uint8_t id, mode_ptr mode_fn, const char *mode_name); // add effect to the list; defined in FX.cpp void setupEffectData(void); // add default effects to the list; defined in FX.cpp @@ -758,7 +763,8 @@ class WS2812FX { // 96 bytes hasCCTBus(void), // return true if the strip is being sent pixel updates isUpdating(void), - useLedsArray = true; //WLEDMM default true as recommended for overlapping segments + deserializeMap(uint8_t n=0), + useLedsArray = false; inline bool isServicing(void) { return _isServicing; } inline bool hasWhiteChannel(void) {return _hasWhiteChannel;} @@ -787,17 +793,17 @@ class WS2812FX { // 96 bytes ablMilliampsMax, currentMilliamps, getLengthPhysical(void), + getLengthTotal(void), // will include virtual/nonexistent pixels in matrix getFps(); inline uint16_t getFrameTime(void) { return _frametime; } inline uint16_t getMinShowDelay(void) { return MIN_SHOW_DELAY; } - inline uint16_t getLengthTotal(void) { return _length; } + inline uint16_t getLength(void) { return _length; } // 2D matrix may have less pixels than W*H inline uint16_t getTransition(void) { return _transitionDur; } uint32_t now, timebase, - currentColor(uint32_t colorNew, uint8_t tNr), getPixelColor(uint16_t); inline uint32_t getLastShow(void) { return _lastShow; } @@ -825,9 +831,9 @@ class WS2812FX { // 96 bytes panelsH, //WLEDMM needs to be stored as well panelsV; //WLEDMM needs to be stored as well + //WLEDMM: keep storing basic 2d setup bool - bOrA; //WLEDMM basic or advanced - + bOrA = false; //WLEDMM basic or advanced, default basic struct { bool bottomStart : 1; bool rightStart : 1; @@ -839,7 +845,7 @@ class WS2812FX { // 96 bytes bool rightStart : 1; bool vertical : 1; bool serpentine : 1; - } panelO; //WLEDMM panelOrientation + } panelO; //panelOrientation typedef struct panel_t { uint8_t xOffset; // x offset relative to the top left of matrix in LEDs. WLEDMM 8 bits/256 is enough @@ -855,12 +861,19 @@ class WS2812FX { // 96 bytes bool serpentine : 1; // is serpentine? }; }; + panel_t() + : xOffset(0) + , yOffset(0) + , width(8) + , height(8) + , options(0) + {} } Panel; std::vector panel; #endif void - setUpMatrix(bool reset = true), //WLEDMM: add reset option to switch on/off reset of customMappingTable + setUpMatrix(), setPixelColorXY(int x, int y, uint32_t c); // outsmart the compiler :) by correctly overloading diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index a35cc6a9..84335dd8 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -34,15 +34,12 @@ // note: matrix may be comprised of multiple panels each with different orientation // but ledmap takes care of that. ledmap is constructed upon initialization // so matrix should disable regular ledmap processing -void WS2812FX::setUpMatrix(bool reset) { +void WS2812FX::setUpMatrix() { #ifndef WLED_DISABLE_2D // erase old ledmap, just in case. - if (reset) { //WLEDMM: add reset option to switch on/off reset of customMappingTable - if (customMappingTable != nullptr) delete[] customMappingTable; - customMappingTable = nullptr; - customMappingSize = 0; - loadedLedmap = 0; - } + if (customMappingTable != nullptr) delete[] customMappingTable; + customMappingTable = nullptr; + customMappingSize = 0; // isMatrix is set in cfg.cpp or set.cpp if (isMatrix) { @@ -59,30 +56,60 @@ void WS2812FX::setUpMatrix(bool reset) { } } - if (reset) { //WLEDMM: add reset option to switch on/off reset of customMappingTable - // safety check - if (Segment::maxWidth * Segment::maxHeight > MAX_LEDS || Segment::maxWidth <= 1 || Segment::maxHeight <= 1) { - DEBUG_PRINTF("2D Bounds error. %d x %d\n", Segment::maxWidth, Segment::maxHeight); - isMatrix = false; - Segment::maxWidth = _length; - Segment::maxHeight = 1; - panels = 0; - panel.clear(); // release memory allocated by panels - resetSegments(true); //WLEDMM bounds only - return; - } - - customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight]; + // safety check + if (Segment::maxWidth * Segment::maxHeight > MAX_LEDS || Segment::maxWidth <= 1 || Segment::maxHeight <= 1) { + DEBUG_PRINTF("2D Bounds error. %d x %d\n", Segment::maxWidth, Segment::maxHeight); + isMatrix = false; + Segment::maxWidth = _length; + Segment::maxHeight = 1; + panels = 0; + panel.clear(); // release memory allocated by panels + resetSegments(true); //WLEDMM bounds only + return; } + customMappingTable = new uint16_t[Segment::maxWidth * Segment::maxHeight]; + if (customMappingTable != nullptr) { - uint16_t customMappingSizeLedmap = customMappingSize; customMappingSize = Segment::maxWidth * Segment::maxHeight; - uint16_t *customMappingTableCombi = nullptr; //WLEDMM: Idea @Troy#2642 - if (customMappingSizeLedmap > 0) { //WLEDMM: @Troy#2642 : include ledmap = 0 as default ledmap - customMappingTableCombi = new uint16_t[customMappingSize]; - for (int i=0; i(); + gapSize = map.size(); + if (!map.isNull() && gapSize >= customMappingSize) { // not an empty map + gapTable = new int8_t[gapSize]; + if (gapTable) for (size_t i = 0; i < gapSize; i++) { + gapTable[i] = constrain(map[i], -1, 1); + } + } + } + DEBUG_PRINTLN(F("Gaps loaded.")); + releaseJSONBufferLock(); } uint16_t x, y, pix=0; //pixel @@ -91,30 +118,22 @@ void WS2812FX::setUpMatrix(bool reset) { uint16_t h = p.vertical ? p.height : p.width; uint16_t v = p.vertical ? p.width : p.height; for (size_t j = 0; j < v; j++){ - for(size_t i = 0; i < h; i++, pix++) { + for(size_t i = 0; i < h; i++) { y = (p.vertical?p.rightStart:p.bottomStart) ? v-j-1 : j; x = (p.vertical?p.bottomStart:p.rightStart) ? h-i-1 : i; x = p.serpentine && j%2 ? h-x-1 : x; - uint16_t index = (p.yOffset + (p.vertical?x:y)) * Segment::maxWidth + p.xOffset + (p.vertical?y:x); - if (customMappingSizeLedmap > 0) { //WLEDMM: @Troy#2642 : include ledmap = 0 as default ledmap - if (index < customMappingSizeLedmap && customMappingTable[index] < customMappingSize) - customMappingTableCombi[customMappingTable[index]] = pix; //WLEDMM: allow for 2 transitions if reset = false (ledmap and logical to physical) - } - else - customMappingTable[index] = pix; + size_t index = (p.yOffset + (p.vertical?x:y)) * Segment::maxWidth + p.xOffset + (p.vertical?y:x); + if (!gapTable || (gapTable && gapTable[index] > 0)) customMappingTable[index] = pix; // a useful pixel (otherwise -1 is retained) + if (!gapTable || (gapTable && gapTable[index] >= 0)) pix++; // not a missing pixel } } } - if (customMappingSizeLedmap > 0) { //WLEDMM: @Troy#2642 : include ledmap = 0 as default ledmap - for (size_t i = 0; i < customMappingSize; i++) { - customMappingTable[i] = customMappingTableCombi[i]; - } - delete[] customMappingTableCombi; - } + // delete gap array as we no longer need it + if (gapTable) delete[] gapTable; #ifdef WLED_DEBUG - DEBUG_PRINTF("Matrix ledmap: %d\n", loadedLedmap); + DEBUG_PRINTF("Matrix ledmap: \n"); for (uint16_t i=0; i= customMappingSize) return; #else uint16_t index = x; - if (index >= _length) return; #endif if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return; busses.setPixelColor(index, col); } @@ -155,12 +173,11 @@ void IRAM_ATTR_YN WS2812FX::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) { #ifndef WLED_DISABLE_2D uint16_t index = (y * Segment::maxWidth + x); - if (index >= customMappingSize) return 0; // customMappingSize is always W * H of matrix in 2D setup #else uint16_t index = x; - if (index >= _length) return 0; #endif if (index < customMappingSize) index = customMappingTable[index]; + if (index >= _length) return 0; return busses.getPixelColor(index); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index c666d913..58dd2624 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -81,7 +81,7 @@ uint16_t Segment::maxHeight = 1; // copy constructor Segment::Segment(const Segment &orig) { //DEBUG_PRINTLN(F("-- Copy segment constructor --")); - memcpy(this, &orig, sizeof(Segment)); + memcpy((void*)this, (void*)&orig, sizeof(Segment)); name = nullptr; data = nullptr; _dataLen = 0; @@ -97,7 +97,7 @@ Segment::Segment(const Segment &orig) { // move constructor Segment::Segment(Segment &&orig) noexcept { //DEBUG_PRINTLN(F("-- Move segment constructor --")); - memcpy(this, &orig, sizeof(Segment)); + memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -116,7 +116,7 @@ Segment& Segment::operator= (const Segment &orig) { if (leds && !Segment::_globalLeds) free(leds); deallocateData(); // copy source - memcpy(this, &orig, sizeof(Segment)); + memcpy((void*)this, (void*)&orig, sizeof(Segment)); // erase pointers to allocated data name = nullptr; data = nullptr; @@ -141,7 +141,7 @@ Segment& Segment::operator= (Segment &&orig) noexcept { deallocateData(); // free old runtime data if (_t) delete _t; if (leds && !Segment::_globalLeds) free(leds); - memcpy(this, &orig, sizeof(Segment)); + memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -188,7 +188,8 @@ void Segment::deallocateData() { void Segment::resetIfRequired() { if (reset) { if (leds && !Segment::_globalLeds) { free(leds); leds = nullptr; } - //if (_t) { delete _t; _t = nullptr; transitional = false; } + if (transitional && _t) { transitional = false; delete _t; _t = nullptr; } + deallocateData(); next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; reset = false; // setOption(SEG_OPTION_RESET, false); } @@ -230,14 +231,14 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { case FX_MODE_NOISE16_4 : pal = 26; break; // landscape 33 case FX_MODE_GLITTER : pal = 11; break; // rainbow colors case FX_MODE_SUNRISE : pal = 35; break; // heat palette - case FX_MODE_FLOW : pal = 6; break; // party + case FX_MODE_RAILWAY : pal = 3; break; // prim + sec } switch (pal) { case 0: //default palette. Exceptions for specific effects above targetPalette = PartyColors_p; break; case 1: {//periodically replace palette with a random one. Transition palette change in 500ms uint32_t timeSinceLastChange = millis() - _lastPaletteChange; - if (timeSinceLastChange > 5000 /*+ ((uint32_t)(255-intensity))*100*/) { + if (timeSinceLastChange > randomPaletteChangeTime * 1000U) { prevRandomPalette = randomPalette; randomPalette = CRGBPalette16( CHSV(random8(), random8(160, 255), random8(128, 255)), @@ -257,7 +258,7 @@ CRGBPalette16 &Segment::loadPalette(CRGBPalette16 &targetPalette, uint8_t pal) { break;} case 73: {//periodically replace palette with a random one. Transition palette change in 500ms uint32_t timeSinceLastChange = millis() - _lastPaletteChange; - if (timeSinceLastChange > 5000 /*+ ((uint32_t)(255-intensity))*100*/) { + if (timeSinceLastChange > randomPaletteChangeTime * 1000U) { prevRandomPalette = randomPalette; randomPalette = CRGBPalette16( CHSV(random8(), random8(160, 255), random8(128, 255)), @@ -442,6 +443,10 @@ void Segment::set(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, uint16_t o bool Segment::setColor(uint8_t slot, uint32_t c) { //returns true if changed if (slot >= NUM_COLORS || c == colors[slot]) return false; + if (!_isRGB && !_hasW) { + if (slot == 0 && c == BLACK) return false; // on/off segment cannot have primary color black + if (slot == 1 && c != BLACK) return false; // on/off segment cannot have secondary color non black + } if (fadeTransition) startTransition(strip.getTransition()); // start transition prior to change colors[slot] = c; stateChanged = true; // send UDP/WS broadcast @@ -575,12 +580,12 @@ class JMapC { char previousSegmentName[50] = ""; ~JMapC() { - Serial.println("~JMapC"); + USER_PRINTLN("~JMapC"); deletejVectorMap(); } void deletejVectorMap() { if (jVectorMap.size() > 0) { - Serial.println("delete jVectorMap"); + USER_PRINTLN("delete jVectorMap"); for (size_t i=0; i>16; // hack to allow running on virtual strips (2D segment columns/rows) +#endif i &= 0xFFFF; if (i >= virtualLength() || i<0) return; // if pixel would fall out of segment just exit @@ -952,7 +959,9 @@ void Segment::setPixelColor(float i, uint32_t col, bool aa) uint32_t Segment::getPixelColor(int i) { +#ifndef WLED_DISABLE_2D int vStrip = i>>16; +#endif i &= 0xFFFF; #ifndef WLED_DISABLE_2D @@ -1040,15 +1049,34 @@ uint8_t Segment::differs(Segment& b) const { void Segment::refreshLightCapabilities() { uint8_t capabilities = 0; + uint16_t segStartIdx = 0xFFFFU; + uint16_t segStopIdx = 0; + + if (start < Segment::maxWidth * Segment::maxHeight) { + // we are withing 2D matrix (includes 1D segments) + for (int y = startY; y < stopY; y++) for (int x = start; x < stop; x++) { + uint16_t index = x + Segment::maxWidth * y; + if (index < strip.customMappingSize) index = strip.customMappingTable[index]; // convert logical address to physical + if (index < 0xFFFFU) { + if (segStartIdx > index) segStartIdx = index; + if (segStopIdx < index) segStopIdx = index; + } + if (segStartIdx == segStopIdx) segStopIdx++; // we only have 1 pixel segment + } + } else { + // we are on the strip located after the matrix + segStartIdx = start; + segStopIdx = stop; + } for (uint8_t b = 0; b < busses.getNumBusses(); b++) { Bus *bus = busses.getBus(b); if (bus == nullptr || bus->getLength()==0) break; if (!bus->isOk()) continue; - if (bus->getStart() >= stop) continue; - if (bus->getStart() + bus->getLength() <= start) continue; + if (bus->getStart() >= segStopIdx) continue; + if (bus->getStart() + bus->getLength() <= segStartIdx) continue; - uint8_t type = bus->getType(); + //uint8_t type = bus->getType(); if (bus->hasRGB() || (cctFromRgb && bus->hasCCT())) capabilities |= SEG_CAPABILITY_RGB; if (!cctFromRgb && bus->hasCCT()) capabilities |= SEG_CAPABILITY_CCT; if (correctWB && (bus->hasRGB() || bus->hasCCT())) capabilities |= SEG_CAPABILITY_CCT; //white balance correction (CCT slider) @@ -1287,14 +1315,50 @@ uint8_t * Segment::getAudioPalette(int pal) { // WS2812FX class implementation /////////////////////////////////////////////////////////////////////////////// -//WLEDMM from +//WLEDMM from util.cpp +// enumerate all ledmapX.json files on FS and extract ledmap names if existing void WS2812FX::enumerateLedmaps() { ledMaps = 1; for (size_t i=1; i<10; i++) { - char fileName[16]; + char fileName[33]; sprintf_P(fileName, PSTR("/ledmap%d.json"), i); bool isFile = WLED_FS.exists(fileName); - if (isFile) ledMaps |= 1 << i; + + #ifndef ESP8266 + if (ledmapNames[i-1]) { //clear old name + delete[] ledmapNames[i-1]; + ledmapNames[i-1] = nullptr; + } + #endif + + if (isFile) { + ledMaps |= 1 << i; + + #ifndef ESP8266 + if (requestJSONBufferLock(21)) { + if (readObjectFromFile(fileName, nullptr, &doc)) { + size_t len = 0; + if (!doc["n"].isNull()) { + // name field exists + const char *name = doc["n"].as(); + if (name != nullptr) len = strlen(name); + if (len > 0 && len < 33) { + ledmapNames[i-1] = new char[len+1]; + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], name, 33); + } + } + if (!ledmapNames[i-1]) { + char tmp[33]; + snprintf_P(tmp, 32, PSTR("ledmap%d.json"), i); + len = strlen(tmp); + ledmapNames[i-1] = new char[len+1]; + if (ledmapNames[i-1]) strlcpy(ledmapNames[i-1], tmp, 33); + } + } + releaseJSONBufferLock(); + } + #endif + } } //WLEDMM add segment names to be used as ledmap names uint8_t segment_index = 0; @@ -1364,10 +1428,11 @@ void WS2812FX::finalizeInit(void) #endif } - if (!isMatrix) { // if 2D then max values defined in setUpMatrix() using panel set-up + if (isMatrix) setUpMatrix(); + else { Segment::maxWidth = _length; Segment::maxHeight = 1; - } + } //initialize leds array. TBD: realloc if nr of leds change if (Segment::_globalLeds) { @@ -1376,17 +1441,20 @@ void WS2812FX::finalizeInit(void) Segment::_globalLeds = nullptr; } if (useLedsArray) { + size_t arrSize = sizeof(CRGB) * getLengthTotal(); #if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM) if (psramFound()) - Segment::_globalLeds = (CRGB*) ps_malloc(sizeof(CRGB) * _length); + Segment::_globalLeds = (CRGB*) ps_malloc(arrSize); else #endif - Segment::_globalLeds = (CRGB*) malloc(sizeof(CRGB) * _length); - memset(Segment::_globalLeds, 0, sizeof(CRGB) * _length); + Segment::_globalLeds = (CRGB*) malloc(arrSize); + memset(Segment::_globalLeds, 0, arrSize); } //segments are created in makeAutoSegments(); + DEBUG_PRINTLN(F("Loading custom palettes")); loadCustomPalettes(); // (re)load all custom palettes + DEBUG_PRINTLN(F("Loading custom ledmaps")); deserializeMap(); // (re)load default ledmap } @@ -1447,15 +1515,15 @@ void WS2812FX::service() { void IRAM_ATTR WS2812FX::setPixelColor(int i, uint32_t col) { - if (i >= _length) return; if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return; busses.setPixelColor(i, col); } uint32_t WS2812FX::getPixelColor(uint16_t i) { - if (i >= _length) return 0; if (i < customMappingSize) i = customMappingTable[i]; + if (i >= _length) return 0; return busses.getPixelColor(i); } @@ -1668,6 +1736,12 @@ uint8_t WS2812FX::getActiveSegmentsNum(void) { return c; } +uint16_t WS2812FX::getLengthTotal(void) { + uint16_t len = Segment::maxWidth * Segment::maxHeight; // will be _length for 1D (see finalizeInit()) but should cover whole matrix for 2D + if (isMatrix && _length > len) len = _length; // for 2D with trailing strip + return len; +} + uint16_t WS2812FX::getLengthPhysical(void) { uint16_t len = 0; for (size_t b = 0; b < busses.getNumBusses(); b++) { @@ -1710,7 +1784,6 @@ void WS2812FX::purgeSegments(bool force) { if (_segments.size() <= 1) return; for (size_t i = _segments.size()-1; i > 0; i--) if (_segments[i].stop == 0 || force) { - DEBUG_PRINT(F("Purging segment segment: ")); DEBUG_PRINTLN(i); deleted++; _segments.erase(_segments.begin() + i); } @@ -1760,45 +1833,31 @@ void WS2812FX::resetSegments(bool boundsOnly) { //WLEDMM add boundsonly } void WS2812FX::makeAutoSegments(bool forceReset) { - if (isMatrix) { - #ifndef WLED_DISABLE_2D - // only create 1 2D segment - if (forceReset || getSegmentsNum() == 0) resetSegments(); // initialises 1 segment - else if (getActiveSegmentsNum() == 1) { - size_t i = getLastActiveSegmentId(); - _segments[i].start = 0; - _segments[i].stop = Segment::maxWidth; - _segments[i].startY = 0; - _segments[i].stopY = Segment::maxHeight; - _segments[i].grouping = 1; - _segments[i].spacing = 0; - _mainSegment = i; - } - // do we have LEDs after the matrix? (ignore buses) - if (autoSegments && _length > Segment::maxWidth*Segment::maxHeight /*&& getActiveSegmentsNum() == 2*/) { - if (_segments.size() == getLastActiveSegmentId()+1) - _segments.push_back(Segment(Segment::maxWidth*Segment::maxHeight, _length)); - else { - size_t i = getLastActiveSegmentId() + 1; - _segments[i].start = Segment::maxWidth*Segment::maxHeight; - _segments[i].stop = _length; - _segments[i].startY = 0; - _segments[i].stopY = 1; - _segments[i].grouping = 1; - _segments[i].spacing = 0; - } - } - #endif - } else if (autoSegments) { //make one segment per bus + if (autoSegments) { //make one segment per bus uint16_t segStarts[MAX_NUM_SEGMENTS] = {0}; uint16_t segStops [MAX_NUM_SEGMENTS] = {0}; - uint8_t s = 0; - for (uint8_t i = 0; i < busses.getNumBusses(); i++) { + size_t s = 0; + + #ifndef WLED_DISABLE_2D + // 2D segment is the 1st one using entire matrix + if (isMatrix) { + segStarts[0] = 0; + segStops[0] = Segment::maxWidth*Segment::maxHeight; + s++; + } + #endif + + for (size_t i = s; i < busses.getNumBusses(); i++) { Bus* b = busses.getBus(i); segStarts[s] = b->getStart(); segStops[s] = segStarts[s] + b->getLength(); + #ifndef WLED_DISABLE_2D + if (isMatrix && segStops[s] < Segment::maxWidth*Segment::maxHeight) continue; // ignore buses comprising matrix + if (isMatrix && segStarts[s] < Segment::maxWidth*Segment::maxHeight) segStarts[s] = Segment::maxWidth*Segment::maxHeight; + #endif + //check for overlap with previous segments for (size_t j = 0; j < s; j++) { if (segStops[j] > segStarts[s] && segStarts[j] < segStops[s]) { @@ -1810,24 +1869,40 @@ void WS2812FX::makeAutoSegments(bool forceReset) { } s++; } + _segments.clear(); _segments.reserve(s); // prevent reallocations - for (size_t i = 0; i < s; i++) { - Segment seg = Segment(segStarts[i], segStops[i]); - seg.selected = true; - _segments.push_back(seg); + // there is always at least one segment (but we need to differentiate between 1D and 2D) + #ifndef WLED_DISABLE_2D + if (isMatrix) + _segments.push_back(Segment(0, Segment::maxWidth, 0, Segment::maxHeight)); + else + #endif + _segments.push_back(Segment(segStarts[0], segStops[0])); + for (size_t i = 1; i < s; i++) { + _segments.push_back(Segment(segStarts[i], segStops[i])); } - _mainSegment = 0; + } else { + if (forceReset || getSegmentsNum() == 0) resetSegments(); //expand the main seg to the entire length, but only if there are no other segments, or reset is forced else if (getActiveSegmentsNum() == 1) { size_t i = getLastActiveSegmentId(); + #ifndef WLED_DISABLE_2D + _segments[i].start = 0; + _segments[i].stop = Segment::maxWidth; + _segments[i].startY = 0; + _segments[i].stopY = Segment::maxHeight; + _segments[i].grouping = 1; + _segments[i].spacing = 0; + #else _segments[i].start = 0; _segments[i].stop = _length; - _mainSegment = 0; + #endif } } + _mainSegment = 0; fixInvalidSegments(); } @@ -1835,14 +1910,30 @@ void WS2812FX::makeAutoSegments(bool forceReset) { void WS2812FX::fixInvalidSegments() { //make sure no segment is longer than total (sanity check) for (size_t i = getSegmentsNum()-1; i > 0; i--) { - if (_segments[i].start >= _length) { _segments.erase(_segments.begin()+i); continue; } - if (_segments[i].stop > _length) _segments[i].stop = _length; - // this is always called as the last step after finalizeInit(), update covered bus types - _segments[i].refreshLightCapabilities(); + if (isMatrix) { + #ifndef WLED_DISABLE_2D + if (_segments[i].start >= Segment::maxWidth * Segment::maxHeight) { + // 1D segment at the end of matrix + if (_segments[i].start >= _length || _segments[i].startY > 0 || _segments[i].stopY > 1) { _segments.erase(_segments.begin()+i); continue; } + if (_segments[i].stop > _length) _segments[i].stop = _length; + continue; + } + if (_segments[i].start >= Segment::maxWidth || _segments[i].startY >= Segment::maxHeight) { _segments.erase(_segments.begin()+i); continue; } + if (_segments[i].stop > Segment::maxWidth) _segments[i].stop = Segment::maxWidth; + if (_segments[i].stopY > Segment::maxHeight) _segments[i].stopY = Segment::maxHeight; + #endif + } else { + if (_segments[i].start >= _length) { _segments.erase(_segments.begin()+i); continue; } + if (_segments[i].stop > _length) _segments[i].stop = _length; + } } + // this is always called as the last step after finalizeInit(), update covered bus types + for (segment &seg : _segments) + seg.refreshLightCapabilities(); } //true if all segments align with a bus, or if a segment covers the total length +//irrelevant in 2D set-up bool WS2812FX::checkSegmentAlignment() { bool aligned = false; for (segment &seg : _segments) { @@ -1890,7 +1981,8 @@ void WS2812FX::printSize() { DEBUG_PRINTF("Modes: %d*%d=%uB\n", sizeof(mode_ptr), _mode.size(), (_mode.capacity()*sizeof(mode_ptr))); DEBUG_PRINTF("Data: %d*%d=%uB\n", sizeof(const char *), _modeData.size(), (_modeData.capacity()*sizeof(const char *))); DEBUG_PRINTF("Map: %d*%d=%uB\n", sizeof(uint16_t), (int)customMappingSize, customMappingSize*sizeof(uint16_t)); - if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%d=%uB\n", sizeof(CRGB), (int)_length, _length*sizeof(CRGB)); + size = getLengthTotal(); + if (useLedsArray) DEBUG_PRINTF("Buffer: %d*%u=%uB\n", sizeof(CRGB), size, size*sizeof(CRGB)); } #endif @@ -1942,22 +2034,22 @@ void WS2812FX::loadCustomPalettes() { } //load custom mapping table from JSON file (called from finalizeInit() or deserializeState()) -void WS2812FX::deserializeMap(uint8_t n) { - // WLEDMM: also supports isMatrix +bool WS2812FX::deserializeMap(uint8_t n) { + // 2D support creates its own ledmap (on the fly) if a ledmap.json exists it will overwrite built one. char fileName[32]; //WLEDMM: als support segment name ledmaps bool isFile = false;; if (n<10) { strcpy_P(fileName, PSTR("/ledmap")); - if (n) sprintf(fileName +7, "%d", n); + if (n) sprintf(fileName +7, "%d", n); //WLEDMM: trick to not include 0 in ledmap.json strcat(fileName, ".json"); isFile = WLED_FS.exists(fileName); } else { //WLEDM add segment name as ledmap.name uint8_t segment_index = 0; for (segment &seg : _segments) { if (n == 10 + segment_index && !isFile && seg.name != nullptr) { - sprintf_P(fileName, PSTR("/lm%s.json"), seg.name); + sprintf_P(fileName, PSTR("/%s.json"), seg.name); isFile = WLED_FS.exists(fileName); } if (isFile) break; @@ -1966,31 +2058,27 @@ void WS2812FX::deserializeMap(uint8_t n) { } if (!isFile) { - // erase custom mapping if selecting nonexistent ledmap.json (n==0) //WLEDM always erase if nonexistant - if (customMappingTable != nullptr) { - //WLEDMM: if isMatrix then not erase but back to matrix default - if (isMatrix) - setUpMatrix(true); - else { - customMappingSize = 0; - delete[] customMappingTable; - customMappingTable = nullptr; - loadedLedmap = 0; - } + // erase custom mapping if selecting nonexistent ledmap.json (n==0) + //WLEDM: doubt this is necessary as return false causes setupMatrix to deal with this + if (!isMatrix && !n && customMappingTable != nullptr) { + customMappingSize = 0; + delete[] customMappingTable; + customMappingTable = nullptr; + loadedLedmap = 0; //WLEDMM } - return; + return false; } - if (!requestJSONBufferLock(7)) return; - - USER_PRINT(F("Reading LED map from ")); //WLEDMM use USER_PRINT - USER_PRINTLN(fileName); + if (!requestJSONBufferLock(7)) return false; if (!readObjectFromFile(fileName, nullptr, &doc)) { releaseJSONBufferLock(); - return; //if file does not exist just exit + return false; //if file does not exist just exit } + USER_PRINT(F("Reading LED map from ")); //WLEDMM use USER_PRINT + USER_PRINTLN(fileName); + // erase old custom ledmap if (customMappingTable != nullptr) { customMappingSize = 0; @@ -2001,16 +2089,20 @@ void WS2812FX::deserializeMap(uint8_t n) { JsonArray map = doc[F("map")]; if (!map.isNull() && map.size()) { // not an empty map - //WLEDMM: if isMatrix then customMap size is whole matrix -#ifndef WLED_DISABLE_2D - if (isMatrix) - customMappingSize = Segment::maxWidth * Segment::maxHeight; //as whole matrix will be stored in setUpMatrix - else -#endif - customMappingSize = map.size(); + + //WLEDMM: support ledmap file properties width and height + if (doc[F("width")]>0 && doc[F("height")]>0) { + Segment::maxWidth = doc[F("width")];; + Segment::maxHeight = doc[F("height")];; + resetSegments(true); //WLEDMM not makeAutoSegments() as we only want to change bounds + } + + customMappingSize = map.size(); customMappingTable = new uint16_t[customMappingSize]; - for (uint16_t i=0; i HSB convert here - Blynk.virtualWrite(V3, bri? 1:0); - Blynk.virtualWrite(V4, effectCurrent); - Blynk.virtualWrite(V5, effectSpeed); - Blynk.virtualWrite(V6, effectIntensity); - Blynk.virtualWrite(V7, nightlightActive); - Blynk.virtualWrite(V8, notifyDirect); - #endif -} - -#ifndef WLED_DISABLE_BLYNK -BLYNK_WRITE(V0) -{ - bri = param.asInt();//bri - stateUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V1) -{ - blHue = param.asInt();//hue - colorHStoRGB(blHue*10,blSat,col); - colorUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V2) -{ - blSat = param.asInt();//sat - colorHStoRGB(blHue*10,blSat,col); - colorUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V3) -{ - bool on = (param.asInt()>0); - if (!on != !bri) {toggleOnOff(); stateUpdated(CALL_MODE_BLYNK);} -} - -BLYNK_WRITE(V4) -{ - effectCurrent = param.asInt()-1;//fx - colorUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V5) -{ - effectSpeed = param.asInt();//sx - colorUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V6) -{ - effectIntensity = param.asInt();//ix - colorUpdated(CALL_MODE_BLYNK); -} - -BLYNK_WRITE(V7) -{ - nightlightActive = (param.asInt()>0); -} - -BLYNK_WRITE(V8) -{ - notifyDirect = (param.asInt()>0); //send notifications -} -#endif diff --git a/wled00/bus_manager.cpp b/wled00/bus_manager.cpp index 91692b5b..08bb5128 100644 --- a/wled00/bus_manager.cpp +++ b/wled00/bus_manager.cpp @@ -18,6 +18,7 @@ void colorRGBtoRGBW(byte* rgb); uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, byte *buffer, uint8_t bri=255, bool isRGBW=false); // enable additional debug output +//WLEDMM: #define DEBUGOUT(x) netDebugEnabled?NetDebug.print(x):Serial.print(x) not supported in this file as netDebugEnabled not in scope #if defined(WLED_DEBUG_HOST) #include "net_debug.h" #define DEBUGOUT NetDebug @@ -361,7 +362,7 @@ void BusOnOff::setPixelColor(uint16_t pix, uint32_t c) { uint8_t b = B(c); uint8_t w = W(c); - _data = bool((r+g+b+w) && _bri) ? 0xFF : 0; + _data = bool(r|g|b|w) && bool(_bri) ? 0xFF : 0; } uint32_t BusOnOff::getPixelColor(uint16_t pix) { @@ -387,19 +388,15 @@ BusNetwork::BusNetwork(BusConfig &bc) : Bus(bc.type, bc.start, bc.autoWhite) { case TYPE_NET_ARTNET_RGB: _rgbw = false; _UDPtype = 2; - break; + break; case TYPE_NET_E131_RGB: _rgbw = false; _UDPtype = 1; - break; - case TYPE_NET_DDP_RGB: - _rgbw = false; - _UDPtype = 0; - break; + break; default: // TYPE_NET_DDP_RGB / TYPE_NET_DDP_RGBW _rgbw = bc.type == TYPE_NET_DDP_RGBW; _UDPtype = 0; - break; + break; } _UDPchannels = _rgbw ? 4 : 3; _data = (byte *)malloc(bc.count * _UDPchannels); @@ -563,4 +560,4 @@ uint16_t BusManager::getTotalLength() { // Bus static member definition int16_t Bus::_cct = -1; uint8_t Bus::_cctBlend = 0; -uint8_t Bus::_gAWM = 255; \ No newline at end of file +uint8_t Bus::_gAWM = 255; diff --git a/wled00/bus_manager.h b/wled00/bus_manager.h index 7b9bc6e4..ffb3bd14 100644 --- a/wled00/bus_manager.h +++ b/wled00/bus_manager.h @@ -140,16 +140,16 @@ class Bus { static void setCCT(uint16_t cct) { _cct = cct; } - static void setCCTBlend(uint8_t b) { - if (b > 100) b = 100; - _cctBlend = (b * 127) / 100; - //compile-time limiter for hardware that can't power both white channels at max - #ifdef WLED_MAX_CCT_BLEND - if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND; - #endif - } - inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; } - inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; } + static void setCCTBlend(uint8_t b) { + if (b > 100) b = 100; + _cctBlend = (b * 127) / 100; + //compile-time limiter for hardware that can't power both white channels at max + #ifdef WLED_MAX_CCT_BLEND + if (_cctBlend > WLED_MAX_CCT_BLEND) _cctBlend = WLED_MAX_CCT_BLEND; + #endif + } + inline void setAutoWhiteMode(uint8_t m) { if (m < 5) _autoWhiteMode = m; } + inline uint8_t getAutoWhiteMode() { return _autoWhiteMode; } inline static void setGlobalAWMode(uint8_t m) { if (m < 5) _gAWM = m; else _gAWM = AW_GLOBAL_DISABLED; } inline static uint8_t getGlobalAWMode() { return _gAWM; } diff --git a/wled00/bus_wrapper.h b/wled00/bus_wrapper.h index ac2a996a..bbf38d2e 100644 --- a/wled00/bus_wrapper.h +++ b/wled00/bus_wrapper.h @@ -182,7 +182,12 @@ #endif //APA102 -#define B_HS_DOT_3 NeoPixelBrightnessBus //hardware SPI +#ifdef WLED_USE_ETHERNET +// fix for #2542 (by @BlackBird77) +#define B_HS_DOT_3 NeoPixelBrightnessBus //hardware HSPI with DMA (ESP32 only) +#else +#define B_HS_DOT_3 NeoPixelBrightnessBus //hardware HSPI +#endif #define B_SS_DOT_3 NeoPixelBrightnessBus //soft SPI //LPD8806 diff --git a/wled00/cfg.cpp b/wled00/cfg.cpp index ae9cee77..32e15ecc 100644 --- a/wled00/cfg.cpp +++ b/wled00/cfg.cpp @@ -17,6 +17,10 @@ void getStringFromJson(char* dest, const char* src, size_t len) { } bool deserializeConfig(JsonObject doc, bool fromFS) { + + //WLEDMM add USER_PRINT + USER_PRINTF("deserializeConfig\n"); + bool needsSave = false; //int rev_major = doc["rev"][0]; // 1 //int rev_minor = doc["rev"][1]; // 0 @@ -100,18 +104,20 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { JsonObject matrix = hw_led[F("matrix")]; if (!matrix.isNull()) { strip.isMatrix = true; + + //WLEDMM: keep storing basic 2d setup CJSON(strip.panels, matrix[F("mpc")]); CJSON(strip.bOrA, matrix["ba"]); //WLEDMM basic or advanced - CJSON(strip.panelsV, matrix[F("mpv")]); //WLEDMM needs to be stored as well - CJSON(strip.panelsH, matrix[F("mph")]); //WLEDMM needs to be stored as well + CJSON(strip.panelsV, matrix[F("mpv")]); + CJSON(strip.panelsH, matrix[F("mph")]); CJSON(strip.matrix.bottomStart, matrix[F("pb")]); CJSON(strip.matrix.rightStart, matrix[F("pr")]); CJSON(strip.matrix.vertical, matrix[F("pv")]); CJSON(strip.matrix.serpentine, matrix["ps"]); - CJSON(strip.panelO.bottomStart, matrix[F("pbl")]); //WLEDMM - CJSON(strip.panelO.rightStart, matrix[F("prl")]); //WLEDMM - CJSON(strip.panelO.vertical, matrix[F("pvl")]); //WLEDMM - CJSON(strip.panelO.serpentine, matrix["psl"]); //WLEDMM + CJSON(strip.panelO.bottomStart, matrix[F("pbl")]); + CJSON(strip.panelO.rightStart, matrix[F("prl")]); + CJSON(strip.panelO.vertical, matrix[F("pvl")]); + CJSON(strip.panelO.serpentine, matrix["psl"]); strip.panel.clear(); JsonArray panels = matrix[F("panels")]; @@ -140,8 +146,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { p.options = 0; strip.panel.push_back(p); } - - strip.setUpMatrix(); + // cannot call strip.setUpMatrix() here due to already locked JSON buffer } #endif @@ -342,18 +347,27 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(strip.paletteBlend, light[F("pal-mode")]); CJSON(autoSegments, light[F("aseg")]); + CJSON(gammaCorrectVal, light["gc"]["val"]); // default 2.8 float light_gc_bri = light["gc"]["bri"]; - float light_gc_col = light["gc"]["col"]; // 2.8 - if (light_gc_bri > 1.5) gammaCorrectBri = true; - else if (light_gc_bri > 0.5) gammaCorrectBri = false; - if (light_gc_col > 1.5) gammaCorrectCol = true; - else if (light_gc_col > 0.5) gammaCorrectCol = false; + float light_gc_col = light["gc"]["col"]; + if (light_gc_bri > 1.0f) gammaCorrectBri = true; + else gammaCorrectBri = false; + if (light_gc_col > 1.0f) gammaCorrectCol = true; + else gammaCorrectCol = false; + if (gammaCorrectVal > 1.0f && gammaCorrectVal <= 3) { + if (gammaCorrectVal != 2.8f) calcGammaTable(gammaCorrectVal); + } else { + gammaCorrectVal = 1.0f; // no gamma correction + gammaCorrectBri = false; + gammaCorrectCol = false; + } JsonObject light_tr = light["tr"]; CJSON(fadeTransition, light_tr["mode"]); int tdd = light_tr["dur"] | -1; if (tdd >= 0) transitionDelay = transitionDelayDefault = tdd * 100; CJSON(strip.paletteFade, light_tr["pal"]); + CJSON(randomPaletteChangeTime, light_tr[F("rpc")]); JsonObject light_nl = light["nl"]; CJSON(nightlightMode, light_nl["mode"]); @@ -415,6 +429,8 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { if (!DMXAddress || DMXAddress > 510) DMXAddress = 1; CJSON(DMXSegmentSpacing, if_live_dmx[F("dss")]); if (DMXSegmentSpacing > 150) DMXSegmentSpacing = 0; + CJSON(e131Priority, if_live_dmx[F("e131prio")]); + if (e131Priority > 200) e131Priority = 200; CJSON(DMXMode, if_live_dmx["mode"]); tdd = if_live[F("timeout")] | -1; @@ -430,17 +446,6 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(alexaNumPresets, interfaces["va"]["p"]); -#ifndef WLED_DISABLE_BLYNK - const char* apikey = interfaces["blynk"][F("token")] | "Hidden"; - tdd = strnlen(apikey, 36); - if (tdd > 20 || tdd == 0) - getStringFromJson(blynkApiKey, apikey, 36); //normally not present due to security - - JsonObject if_blynk = interfaces["blynk"]; - getStringFromJson(blynkHost, if_blynk[F("host")], 33); - CJSON(blynkPort, if_blynk["port"]); -#endif - #ifdef WLED_ENABLE_MQTT JsonObject if_mqtt = interfaces["mqtt"]; CJSON(mqttEnabled, if_mqtt["en"]); @@ -472,6 +477,18 @@ bool deserializeConfig(JsonObject doc, bool fromFS) { CJSON(hueIP[i], if_hue_ip[i]); #endif +//WLEDMM: add netdebug variables +#ifdef WLED_DEBUG_HOST + JsonObject if_ndb = interfaces["ndb"]; + JsonArray if_ndb_ip = if_ndb["ip"]; + for (byte i = 0; i < 4; i++) + CJSON(netDebugPrintIP[i], if_ndb_ip[i]); + CJSON(netDebugPrintPort, if_ndb["port"]); + CJSON(netDebugEnabled, if_ndb["enabled"]); + // USER_PRINTF("deserializeConfig %d\n", netDebugEnabled); + pinManager.manageDebugTXPin(); +#endif + JsonObject if_ntp = interfaces[F("ntp")]; CJSON(ntpEnabled, if_ntp["en"]); getStringFromJson(ntpServerName, if_ntp[F("host")], 33); // "1.wled.pool.ntp.org" @@ -717,9 +734,11 @@ void serializeConfig() { if (strip.isMatrix) { JsonObject matrix = hw_led.createNestedObject(F("matrix")); matrix[F("mpc")] = strip.panels; + + //WLEDMM: keep storing basic 2d setup matrix[F("ba")] = strip.bOrA; //WLEDMM basic or advanced - matrix[F("mph")] = strip.panelsH; //WLEDMM needs to be stored as well - matrix[F("mpv")] = strip.panelsV; //WLEDMM needs to be stored as well + matrix[F("mph")] = strip.panelsH; + matrix[F("mpv")] = strip.panelsV; matrix[F("pb")] = strip.matrix.bottomStart; matrix[F("pr")] = strip.matrix.rightStart; matrix[F("pv")] = strip.matrix.vertical; @@ -822,13 +841,15 @@ void serializeConfig() { light[F("aseg")] = autoSegments; JsonObject light_gc = light.createNestedObject("gc"); - light_gc["bri"] = (gammaCorrectBri) ? 2.8 : 1.0; - light_gc["col"] = (gammaCorrectCol) ? 2.8 : 1.0; + light_gc["bri"] = (gammaCorrectBri) ? gammaCorrectVal : 1.0f; // keep compatibility + light_gc["col"] = (gammaCorrectCol) ? gammaCorrectVal : 1.0f; // keep compatibility + light_gc["val"] = gammaCorrectVal; JsonObject light_tr = light.createNestedObject("tr"); light_tr["mode"] = fadeTransition; light_tr["dur"] = transitionDelayDefault / 100; light_tr["pal"] = strip.paletteFade; + light_tr[F("rpc")] = randomPaletteChangeTime; JsonObject light_nl = light.createNestedObject("nl"); light_nl["mode"] = nightlightMode; @@ -877,6 +898,7 @@ void serializeConfig() { JsonObject if_live_dmx = if_live.createNestedObject("dmx"); if_live_dmx[F("uni")] = e131Universe; if_live_dmx[F("seqskip")] = e131SkipOutOfSequence; + if_live_dmx[F("e131prio")] = e131Priority; if_live_dmx[F("addr")] = DMXAddress; if_live_dmx[F("dss")] = DMXSegmentSpacing; if_live_dmx["mode"] = DMXMode; @@ -895,13 +917,6 @@ void serializeConfig() { if_va["p"] = alexaNumPresets; -#ifndef WLED_DISABLE_BLYNK - JsonObject if_blynk = interfaces.createNestedObject("blynk"); - if_blynk[F("token")] = strlen(blynkApiKey) ? "Hidden":""; - if_blynk[F("host")] = blynkHost; - if_blynk["port"] = blynkPort; -#endif - #ifdef WLED_ENABLE_MQTT JsonObject if_mqtt = interfaces.createNestedObject("mqtt"); if_mqtt["en"] = mqttEnabled; @@ -933,6 +948,18 @@ void serializeConfig() { } #endif +//WLEDMM: add netdebug variables +#ifdef WLED_DEBUG_HOST + JsonObject if_ndb = interfaces.createNestedObject("ndb"); + JsonArray if_ndb_ip = if_ndb.createNestedArray("ip"); + for (byte i = 0; i < 4; i++) { + if_ndb_ip.add(netDebugPrintIP[i]); + } + if_ndb["port"] = netDebugPrintPort; + if_ndb["enabled"] = netDebugEnabled; + // USER_PRINTF("serializeConfig %d\n", netDebugEnabled); +#endif + JsonObject if_ntp = interfaces.createNestedObject("ntp"); if_ntp["en"] = ntpEnabled; if_ntp[F("host")] = ntpServerName; @@ -1004,6 +1031,9 @@ void serializeConfig() { JsonObject usermods_settings = doc.createNestedObject("um"); usermods.addToConfig(usermods_settings); + //WLEDMM add USER_PRINT + USER_PRINTF("serializeConfig\n"); + File f = WLED_FS.open("/cfg.json", "w"); if (f) serializeJson(doc, f); f.close(); @@ -1032,13 +1062,6 @@ bool deserializeConfigSec() { JsonObject interfaces = doc["if"]; -#ifndef WLED_DISABLE_BLYNK - const char* apikey = interfaces["blynk"][F("token")] | "Hidden"; - int tdd = strnlen(apikey, 36); - if (tdd > 20 || tdd == 0) - getStringFromJson(blynkApiKey, apikey, 36); -#endif - #ifdef WLED_ENABLE_MQTT JsonObject if_mqtt = interfaces["mqtt"]; getStringFromJson(mqttPass, if_mqtt["psk"], 65); @@ -1077,10 +1100,6 @@ void serializeConfigSec() { ap["psk"] = apPass; JsonObject interfaces = doc.createNestedObject("if"); -#ifndef WLED_DISABLE_BLYNK - JsonObject if_blynk = interfaces.createNestedObject("blynk"); - if_blynk[F("token")] = blynkApiKey; -#endif #ifdef WLED_ENABLE_MQTT JsonObject if_mqtt = interfaces.createNestedObject("mqtt"); if_mqtt["psk"] = mqttPass; diff --git a/wled00/colors.cpp b/wled00/colors.cpp index 3cba87d2..61457eba 100644 --- a/wled00/colors.cpp +++ b/wled00/colors.cpp @@ -57,39 +57,42 @@ void setRandomColor(byte* rgb) void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb { - float h = ((float)hue)/65535.0; - float s = ((float)sat)/255.0; - byte i = floor(h*6); - float f = h * 6-i; - float p = 255 * (1-s); - float q = 255 * (1-f*s); - float t = 255 * (1-(1-f)*s); + float h = ((float)hue)/65535.0f; + float s = ((float)sat)/255.0f; + int i = floorf(h*6); + float f = h * 6.0f - i; + int p = int(255.0f * (1.0f-s)); + int q = int(255.0f * (1.0f-f*s)); + int t = int(255.0f * (1.0f-(1.0f-f)*s)); + p = constrain(p, 0, 255); + q = constrain(q, 0, 255); + t = constrain(t, 0, 255); switch (i%6) { - case 0: rgb[0]=255,rgb[1]=t,rgb[2]=p;break; - case 1: rgb[0]=q,rgb[1]=255,rgb[2]=p;break; - case 2: rgb[0]=p,rgb[1]=255,rgb[2]=t;break; - case 3: rgb[0]=p,rgb[1]=q,rgb[2]=255;break; - case 4: rgb[0]=t,rgb[1]=p,rgb[2]=255;break; - case 5: rgb[0]=255,rgb[1]=p,rgb[2]=q; + case 0: rgb[0]=255,rgb[1]=t, rgb[2]=p; break; + case 1: rgb[0]=q, rgb[1]=255,rgb[2]=p; break; + case 2: rgb[0]=p, rgb[1]=255,rgb[2]=t; break; + case 3: rgb[0]=p, rgb[1]=q, rgb[2]=255;break; + case 4: rgb[0]=t, rgb[1]=p, rgb[2]=255;break; + case 5: rgb[0]=255,rgb[1]=p, rgb[2]=q; break; } } //get RGB values from color temperature in K (https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html) void colorKtoRGB(uint16_t kelvin, byte* rgb) //white spectrum to rgb, calc { - float r = 0, g = 0, b = 0; - float temp = kelvin / 100; - if (temp <= 66) { + int r = 0, g = 0, b = 0; + float temp = kelvin / 100.0f; + if (temp <= 66.0f) { r = 255; - g = round(99.4708025861 * log(temp) - 161.1195681661); - if (temp <= 19) { + g = roundf(99.4708025861f * logf(temp) - 161.1195681661f); + if (temp <= 19.0f) { b = 0; } else { - b = round(138.5177312231 * log((temp - 10)) - 305.0447927307); + b = roundf(138.5177312231f * logf((temp - 10.0f)) - 305.0447927307f); } } else { - r = round(329.698727446 * pow((temp - 60), -0.1332047592)); - g = round(288.1221695283 * pow((temp - 60), -0.0755148492)); + r = roundf(329.698727446f * powf((temp - 60.0f), -0.1332047592f)); + g = roundf(288.1221695283f * powf((temp - 60.0f), -0.0755148492f)); b = 255; } //g += 12; //mod by Aircoookie, a bit less accurate but visibly less pinkish @@ -147,9 +150,9 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www b = 1.0f; } // Apply gamma correction - r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f; - g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f; - b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f; + r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * powf(r, (1.0f / 2.4f)) - 0.055f; + g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * powf(g, (1.0f / 2.4f)) - 0.055f; + b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * powf(b, (1.0f / 2.4f)) - 0.055f; if (r > b && r > g) { // red is biggest @@ -173,9 +176,9 @@ void colorXYtoRGB(float x, float y, byte* rgb) //coordinates to rgb (https://www b = 1.0f; } } - rgb[0] = 255.0*r; - rgb[1] = 255.0*g; - rgb[2] = 255.0*b; + rgb[0] = byte(255.0f*r); + rgb[1] = byte(255.0f*g); + rgb[2] = byte(255.0f*b); } void colorRGBtoXY(byte* rgb, float* xy) //rgb to coordinates (https://www.developers.meethue.com/documentation/color-conversions-rgb-xy) @@ -242,35 +245,13 @@ float maxf (float v, float w) return v; } -/* -uint32_t colorRGBtoRGBW(uint32_t c) -{ - byte rgb[4]; - rgb[0] = R(c); - rgb[1] = G(c); - rgb[2] = B(c); - rgb[3] = W(c); - colorRGBtoRGBW(rgb); - return RGBW32(rgb[0], rgb[1], rgb[2], rgb[3]); -} - -void colorRGBtoRGBW(byte* rgb) //rgb to rgbw (http://codewelt.com/rgbw). (RGBW_MODE_LEGACY) -{ - float low = minf(rgb[0],minf(rgb[1],rgb[2])); - float high = maxf(rgb[0],maxf(rgb[1],rgb[2])); - if (high < 0.1f) return; - float sat = 100.0f * ((high - low) / high); // maximum saturation is 100 (corrected from 255) - rgb[3] = (byte)((255.0f - sat) / 255.0f * (rgb[0] + rgb[1] + rgb[2]) / 3); -} -*/ - -byte correctionRGB[4] = {0,0,0,0}; -uint16_t lastKelvin = 0; - // adjust RGB values based on color temperature in K (range [2800-10200]) (https://en.wikipedia.org/wiki/Color_balance) +// called from bus manager when color correction is enabled! uint32_t colorBalanceFromKelvin(uint16_t kelvin, uint32_t rgb) { //remember so that slow colorKtoRGB() doesn't have to run for every setPixelColor() + static byte correctionRGB[4] = {0,0,0,0}; + static uint16_t lastKelvin = 0; if (lastKelvin != kelvin) colorKtoRGB(kelvin, correctionRGB); // convert Kelvin to RGB lastKelvin = kelvin; byte rgbw[4]; @@ -345,7 +326,7 @@ static byte gammaT[256] = { // https://github.com/Aircoookie/WLED/issues/2767#issuecomment-1310961308 // unfortunately NepixelsBu has its own internal table, that kills low brightness values similar to the original WLED table. // see https://github.com/Makuna/NeoPixelBus/blob/master/src/internal/NeoGamma.h -static byte gammaT[256] = { +static const byte gammaT[256] = { 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, @@ -373,9 +354,11 @@ uint8_t gamma8_cal(uint8_t b, float gamma) // re-calculates & fills gamma table void calcGammaTable(float gamma) { +#if !defined(WLED_USE_CIE_BRIGHTNESS_TABLE) // WLEDMM not possible when using the CIE table for (uint16_t i = 0; i < 256; i++) { gammaT[i] = gamma8_cal(i, gamma); } +#endif } // used for individual channel or brightness gamma correction diff --git a/wled00/const.h b/wled00/const.h index af6a8088..288b4b3f 100644 --- a/wled00/const.h +++ b/wled00/const.h @@ -5,7 +5,7 @@ * Readability defines and their associated numerical values + compile-time constants */ -#define GRADIENT_PALETTE_COUNT 61 //WLEDMM netmindz ar palette +2, ewowi second Random Cycle palette +1 +#define GRADIENT_PALETTE_COUNT 61 //WLEDMM netmindz ar palette +2, ewowi Random Smooth palette +1 //Defaults #define DEFAULT_CLIENT_SSID "Your_Network" @@ -79,6 +79,17 @@ #define WLED_MAX_COLOR_ORDER_MAPPINGS 10 #endif +#if defined(WLED_MAX_LEDMAPS) && (WLED_MAX_LEDMAPS > 32 || WLED_MAX_LEDMAPS < 10) + #undef WLED_MAX_LEDMAPS +#endif +#ifndef WLED_MAX_LEDMAPS + #ifdef ESP8266 + #define WLED_MAX_LEDMAPS 10 + #else + #define WLED_MAX_LEDMAPS 16 + #endif +#endif + //Usermod IDs #define USERMOD_ID_RESERVED 0 //Unused. Might indicate no usermod present #define USERMOD_ID_UNSPECIFIED 1 //Default value for a general user mod that does not specify a custom ID @@ -120,10 +131,12 @@ #define USERMOD_ID_SD_CARD 37 //Usermod "usermod_sd_card.h" #define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h #define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h +#define USERMOD_ID_KLIPPER 40 // Usermod Klipper percentage //WLEDMM -#define USERMOD_ID_CUSTOMEFFECTS 90 //Usermod "usermod_v2_customeffects.h" +#define USERMOD_ID_ARTIFX 90 //Usermod "usermod_v2_artifx.h" #define USERMOD_ID_WEATHER 91 //Usermod "usermod_v2_weather.h" #define USERMOD_ID_GAMES 92 //Usermod "usermod_v2_games.h" +#define USERMOD_ID_FASTLED 93 //Usermod "usermod_v2_fastled.h" //Access point behavior #define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot @@ -141,7 +154,7 @@ #define CALL_MODE_FX_CHANGED 6 //no longer used #define CALL_MODE_HUE 7 #define CALL_MODE_PRESET_CYCLE 8 -#define CALL_MODE_BLYNK 9 +#define CALL_MODE_BLYNK 9 //no longer used #define CALL_MODE_ALEXA 10 #define CALL_MODE_WS_SEND 11 //special call mode, not for notifier, updates websocket only #define CALL_MODE_BUTTON_PRESET 12 //button/IR JSON preset/macro @@ -351,11 +364,11 @@ #define MAX_LEDS_PER_BUS 2048 // may not be enough for fast LEDs (i.e. APA102) #endif -// string temp buffer (now stored in stack locally) +// string temp buffer (now stored in stack locally) // WLEDMM ...which is actually not the greatest design choice on ESP32 #ifdef ESP8266 #define SETTINGS_STACK_BUF_SIZE 2048 #else -#define SETTINGS_STACK_BUF_SIZE 3096 +#define SETTINGS_STACK_BUF_SIZE 3712 // WLEDMM added 512 bytes of margin (was 3096) #endif #ifdef WLED_USE_ETHERNET @@ -396,8 +409,8 @@ #define JSON_BUFFER_SIZE 24576 #endif -//#define MIN_HEAP_SIZE (MAX_LED_MEMORY+2048) -#define MIN_HEAP_SIZE (8192) +//#define MIN_HEAP_SIZE (8k for AsyncWebServer) +#define MIN_HEAP_SIZE 8192 // Maximum size of node map (list of other WLED instances) #ifdef ESP8266 diff --git a/wled00/data/index.css b/wled00/data/index.css index 913cd360..d12942b6 100644 --- a/wled00/data/index.css +++ b/wled00/data/index.css @@ -392,12 +392,16 @@ button { } .slider { - background-color: var(--c-2); max-width: 300px; - min-width: 280px; + min-width: 260px; margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */ border-radius: 24px; position: relative; + padding-bottom: 2px; +} + +#sliders .slider, #info .slider { + background-color: var(--c-2); } .filter, .option { @@ -425,14 +429,14 @@ button { box-shadow: 4px 4px 10px 4px var(--c-1); color: var(--c-f); text-align: center; - padding: 5px 10px; + padding: 4px 8px; border-radius: 6px; /* Position the tooltip text */ width: 160px; position: absolute; z-index: 1; - bottom: 100%; + bottom: 80%; left: 50%; margin-left: -92px; @@ -647,7 +651,7 @@ img { #wbal .sliderdisplay { background: linear-gradient(90deg, #ff8f1f 0%, #fff 50%, #cbdbff); } /* wrapper divs hidden by default */ -#rgbwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw { +#rgbwrap, #swrap, #hwrap, #kwrap, #wwrap, #wbal, #qcs-w, #hexw { display: none; } @@ -731,9 +735,13 @@ input[type=range]::-moz-range-thumb { #Colors .sliderwrap { width: 260px; - margin: 10px 0 0; + margin: 4px 0 0; } +/* #Colors { + padding-top: 18px; +} + */ /* Dynamically hide brightness slider label */ .hd { display: var(--bhd); @@ -744,13 +752,14 @@ input[type=range]::-moz-range-thumb { margin-top: var(--bmt); } -#picker, #rgbwrap, #kwrap, #wwrap, #wbal, #vwrap, #qcs-w, #hexw, #pall, #ledmap { +#picker, #qcs-w, #hexw, #pall, #ledmap { margin: 0 auto; width: 260px; + /*background-color: unset;*/ } #picker { - margin-top: 10px; + margin-top: -10px !important; } /* buttons */ @@ -1409,6 +1418,9 @@ TD .checkmark, TD .radiomark { .expanded { display: inline-block !important; } +.expanded .segin.hide, .expanded .presin.hide, .expanded .sbs.hide { + display: none !important; +} .m6 { margin: 6px 0; @@ -1505,7 +1517,7 @@ TD .checkmark, TD .radiomark { } } -@media all and (max-width: 1249px) { +@media all and (max-width: 1024px) { #buttonPcm { display: none; } diff --git a/wled00/data/index.htm b/wled00/data/index.htm index c975522d..ebf0d711 100644 --- a/wled00/data/index.htm +++ b/wled00/data/index.htm @@ -52,7 +52,7 @@ setTimeout(()=>{h.appendChild(l)},100); - + @@ -66,7 +66,7 @@ - + @@ -89,94 +89,102 @@
-
-
- -
- -
-

-
-
- -
- -
-

-
-
- -
- -
-

-
-
- -
- -
-
-
-
-

RGB color

-
+
+
+
+
- + +
+
+ Hue +
+
+
+ +
+
+ Saturation +
+
+
+
+ Value/Brightness
-
+
- +
+ Kelvin/Temperature
-
-
- -
+
+ +
+
+ +
+
+ Red channel +
+
+
+ +
+
+ Green channel +
+
+
+ +
+
+ Blue channel
-
-
-

White channel

-
- -
+
+ +
+ +
+
+ White channel
-
-
-

White balance

-
- -
+
+ +
+ +
+
+ White balance
-
-
-
-
-
-
-
-

-
-
-
-
-
R
-
-
- - - -
-

-
- - - -
+
+
+
+
+
+
+

+
+
+
+
+
R
+
+
+ + + +
+

+
+ + + +
+

Color palette

@@ -199,6 +207,12 @@
+
+ +
+
+
+

Effect mode

@@ -304,22 +318,22 @@
+
+
+
+
+
+

Segments

Loading...
+
- -
-
-
-
-
-
-

Transition:  s

+

Transition:  s

@@ -366,7 +380,8 @@

- Made with ❤︎ by Aircoookie and the WLED community + WLED made with ❤︎ by Aircoookie and the WLED community
+ WLED MM made with ❤︎ by Softhack007 & Ewowi and the WLED 2D & Audio Dev community
- + @@ -398,6 +413,6 @@

- + diff --git a/wled00/data/index.js b/wled00/data/index.js index 7091a742..50459b17 100644 --- a/wled00/data/index.js +++ b/wled00/data/index.js @@ -4,6 +4,7 @@ var isOn = false, nlA = false, isLv = false, isInfo = false, isNodes = false, sy var hasWhite = false, hasRGB = false, hasCCT = false; var nlDur = 60, nlTar = 0; var nlMode = false; +var segLmax = 0; // size (in pixels) of largest selected segment var selectedFx = 0; var selectedPal = 0; var csel = 0; // selected color slot (0-2) @@ -63,13 +64,10 @@ function setCSL(cs) let w = cs.dataset.w ? parseInt(cs.dataset.w) : 0; let hasShadow = getComputedStyle(cs).textShadow !== "none"; if (hasRGB && !isRgbBlack(cs.dataset)) { - cs.style.backgroundColor = rgbStr(cs.dataset); if (!hasShadow) cs.style.color = rgbBri(cs.dataset) > 127 ? "#000":"#fff"; // if text has no CSS "shadow" - if (hasWhite && w > 0) { - cs.style.background = `linear-gradient(180deg, ${rgbStr(cs.dataset)} 30%, rgb(${w},${w},${w}))`; - } + cs.style.background = (hasWhite && w > 0) ? `linear-gradient(180deg, ${rgbStr(cs.dataset)} 30%, rgb(${w},${w},${w}))` : rgbStr(cs.dataset); } else { - if (!hasWhite) w = 0; + if (hasRGB && !hasWhite) w = 0; cs.style.background = `rgb(${w},${w},${w})`; if (!hasShadow) cs.style.color = w > 127 ? "#000":"#fff"; } @@ -542,7 +540,7 @@ function populateQL() { var cn = ""; if (pQL.length > 0) { - pQL.sort((a,b) => (a[0]>b[0])); + pQL.sort((a,b) => (a[1]>b[1])); //WLEDMM do not sort on preset id but on ql name cn += `

Quick load

`; for (var key of (pQL||[])) { cn += ``; @@ -573,7 +571,8 @@ function populatePresets(fromls) cn += `
`; if (cfg.comp.pid) cn += `
${i}
`; - cn += `
${isPlaylist(i)?"":""}${pName(i)} + //WLEDMM: show ql if defined + cn += `
${isPlaylist(i)?"":""}${(pJson[i].ql?pJson[i].ql+' ':'') + pName(i)}
@@ -612,7 +611,9 @@ function parseInfo(i) { mw = i.leds.matrix ? i.leds.matrix.w : 0; mh = i.leds.matrix ? i.leds.matrix.h : 0; isM = mw>0 && mh>0; - if (!isM) { + if (isM) { + gId('buttonSr').className = "active"; isLv = true; //WLEDMM: on after load + } else { gId("filter1D").classList.add('hide'); //gId("filter2D").classList.add('hide'); hideModes("2D"); @@ -644,8 +645,10 @@ function populateInfo(i) { var cn=""; var heap = i.freeheap/1000; - heap = heap.toFixed(1); - var theap = (i.totalheap>0)?i.totalheap/1000:-1; theap = theap.toFixed(1); //WLEDMM - total heap is not available on 8266 + var heap = Math.round(i.freeheap/100)/10; // WLEDMM bugfix + var theap = (i.totalheap>0)?i.totalheap/1000:-1; //WLEDMM - total heap is not available on 8266 + var flashsize = i.getflash/1000; //WLEDMM and Athom + flashsize = flashsize.toFixed(1); //WLEDMM and Athom var pwr = i.leds.pwr; var pwru = "Not calculated"; if (pwr > 1000) {pwr /= 1000; pwr = pwr.toFixed((pwr > 10) ? 0 : 1); pwru = pwr + " A";} @@ -665,33 +668,38 @@ function populateInfo(i) if (i.cn) vcn = i.cn; //WLEDMM: add total heap and total PSRAM, and build number, add bin name - if (i.ver.includes("0.14.1.")) vcn = "Sitting Ducks"; // easter egg - if (i.ver.includes("0.14.0.")) vcn = "Lupo"; // check for MM versioning scheme + if (i.ver.includes("0.14.1")) vcn = "Sitting Ducks"; // easter egg + if (i.ver.includes("0.14.0")) vcn = "Lupo"; // check for MM versioning scheme + if (i.ver.includes("0.14.0-b2.2")) vcn = "Sitting Ducks"; // early easter egg + if (i.ver.includes("0.14.0-b15.21")) vcn = "Lupo"; cn += `v${i.ver}  "${vcn}"

(WLEDMM_${i.ver} ${i.rel}.bin)

build ${i.vid}

${urows} ${urows===""?'':''} -${i.opt&0x100?inforow("Debug",""):''} +${i.opt&0x100?inforow("Net Print ☾",""):''} +${i.serialOnline?inforow(i.serialOnline,"TX="+i.sTX,"; RX="+i.sRX):""} +${i.opt&0x100?'':''} ${inforow("Build",i.vid)} -${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")} -${inforow("Uptime",getRuntimeStr(i.uptime))} ${inforow("Estimated current",pwru)} ${inforow("Average FPS",i.leds.fps)} +${inforow("Signal strength",i.wifi.signal +"% ("+ i.wifi.rssi, " dBm)")} +${inforow("Uptime",getRuntimeStr(i.uptime))} -${inforow("MAC address",i.mac)} ${inforow("Filesystem",i.fs.u + "/" + i.fs.t + " kB (" +Math.round(i.fs.u*100/i.fs.t) + "%)")} -${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")} -${theap>0?inforow("Total heap ☾",theap," kB"):""} -${theap>0?inforow("Used heap ☾",((i.totalheap-i.freeheap)/1000).toFixed(1)," kB"):inforow("Free heap",heap," kB")} -${i.minfreeheap?inforow("Max used heap ☾",((i.totalheap-i.minfreeheap)/1000).toFixed(1)," kB"):""} +${theap>0?inforow("Heap ☾",((i.totalheap-i.freeheap)/1000).toFixed(0)+"/"+theap.toFixed(0)+" kB"," ("+Math.round((i.totalheap-i.freeheap)/(10*theap))+"%)"):""} +${i.minfreeheap?inforow("Max used heap ☾",((i.totalheap-i.minfreeheap)/1000).toFixed(1)+" kB"," ("+Math.round((i.totalheap-i.minfreeheap)/(10*theap))+"%)"):""} ${inforow("Free heap",heap," kB")} -${i.tpram?inforow("Total PSRAM ☾",(i.tpram/1024).toFixed(1)," kB"):""} -${i.psram?((i.tpram-i.psram)>16383?inforow("Used PSRAM ☾",((i.tpram-i.psram)/1024).toFixed(1)," kB"):inforow("Used PSRAM",(i.tpram-i.psram)," B")):""} +${inforow("Flash Size ☾",flashsize," kB")} +${i.tpram?inforow("PSRAM ☾",(i.tpram/1024).toFixed(1)," kB"):""} +${i.psram?((i.tpram-i.psram)>16383?inforow("Used PSRAM ☾",((i.tpram-i.psram)/1024).toFixed(1)," kB"):inforow("Used PSRAM ☾",(i.tpram-i.psram)," B")):""} +${i.psusedram?((i.tpram-i.psusedram)>16383?inforow("Max used PSRAM ☾",((i.tpram-i.psusedram)/1024).toFixed(1)," kB"):inforow("Max used PSRAM ☾",(i.tpram-i.psusedram)," B")):""} ${i.psram?inforow("Free PSRAM",(i.psram/1024).toFixed(1)," kB"):""} -${i.psusedram?((i.tpram-i.psusedram)>16383?inforow("Max Used PSRAM ☾",((i.tpram-i.psusedram)/1024).toFixed(1)," kB"):inforow("Max Used PSRAM",(i.tpram-i.psusedram)," B")):""} +${inforow("MAC address",i.mac)} +${inforow("Environment",i.arch + " " + i.core + " (" + i.lwip + ")")} ${i.e32model?inforow(i.e32model + " ☾",i.e32cores +" core(s)"," "+i.e32speed+" Mhz"):""} ${i.e32flash?inforow("Flash "+i.e32flash+"MB"+" mode "+i.e32flashmode+i.e32flashtext + " ☾",i.e32flashspeed," Mhz"):""} +${i.e32code?inforow("Last ESP Restart ☾",i.e32code+" "+i.e32text):""} ${i.e32core0code?inforow("Core0 rst reason ☾",i.e32core0code, " "+i.e32core0text):""} ${i.e32core1code?inforow("Core1 rst reason ☾",i.e32core1code, " "+i.e32core1text):""} @@ -710,7 +718,8 @@ function populateSegments(s) let li = lastinfo; segCount = 0; lowestUnused = 0; lSeg = 0; - ledmapFileNames = []; + ledmapNr = s.ledmap; //WLEDMM + ledmapFileNames = []; //WLEDMM for (var inst of (s.seg||[])) { segCount++; @@ -722,7 +731,7 @@ function populateSegments(s) let sg = gId(`seg${i}`); let exp = sg ? (sg.classList.contains('expanded') || (i===0 && cfg.comp.segexp)) : false; - ledmapFileNames.push("lm" + (inst.n?inst.n:"default") + ".json"); //WLEDMM + ledmapFileNames.push((inst.n?inst.n:"default") + ".json"); //WLEDMM let segp = `
@@ -762,9 +771,9 @@ function populateSegments(s)
`; - //WLEDMM Custom Effects + //WLEDMM ARTIFX let fxName = eJson.find((o)=>{return o.id==selectedFx}).name; - let cusEff = `
`; + let cusEff = `
`; cn += `




- - - + + + ${isM&&staX'+ ''+ - ''+ - ''+ + ''+ + ''+ ''+ '':''} - + - - + +
${isM&&staX @@ -787,24 +796,24 @@ function populateSegments(s) ${isM&&staX
${isM&&staX'+rvXck:''}${isM&&staX'+rvXck:''}
Start Y'+(cfg.comp.seglen?'Height':'Stop Y')+'
'+miYck+'
'+rvYck+'
Grouping Spacing
@@ -812,7 +821,7 @@ function populateSegments(s) ${!(isM&&staX1&&stoX-staX>1?map2D:''} ${s.AudioReactive && s.AudioReactive.on ? "" : sndSim} - ${s.CustomEffects && s.CustomEffects.on && fxName.includes("Custom Effect") ? cusEff : ""} + ${s.ARTIFX && s.ARTIFX.on && fxName.includes("ARTI-FX") ? cusEff : ""}
"; gId("ledmap").innerHTML = cont; gId("ledmap").classList.remove('hide'); } else { gId("ledmap").classList.add('hide'); } - if (isM) drawSegments(); //WLEDMM + if (isM) drawSegmentView(); //WLEDMM } function populateEffects() @@ -887,6 +899,7 @@ function populateEffects() let m = (eP.length<4 || eP[3]==='')?'1':eP[3]; // flags if (id == 0) m = ''; // solid has no flags if (m.length>0) { + if (m.includes('0')) nm += "•"; // 0D effects (PWM & On/Off) if (m.includes('1')) nm += "⋮"; // 1D effects if (m.includes("1.5d")) nm += "⋮"; // WLEDMM: vStrips if (m.includes('2')) nm += "▦"; // 2D effects @@ -1080,7 +1093,7 @@ function toggleBubble(e) } // updates segment length upon input of segment values -function updateLen(s, draw=true) //WLEDMM conditonally draw segment visualisation +function updateLen(s, draw=true) //WLEDMM conditonally draw segment view { if (!gId(`seg${s}s`)) return; var start = parseInt(gId(`seg${s}s`).value); @@ -1152,11 +1165,13 @@ function updateLen(s, draw=true) //WLEDMM conditonally draw segment visualisatio gId(`seg${s}len`).innerHTML = out; - if (draw && isM) drawSegments(); //WLEDMM draw new segment visualization if something changes in a segment + if (draw && isM) drawSegmentView(); //WLEDMM draw new segmentview if something changes in a segment + gId("effectGFX").style.display = isM? "inline":"none"; + gId("segGFX").style.display = isM? "inline":"none"; } //WLEDMM -function drawSegments() { +function drawSegmentView() { var px, py, pw, ph; var topLeftX, topLeftY; @@ -1187,25 +1202,22 @@ function drawSegments() { if (!ctx) { //WLEDMM: add canvas, initialize and set UI var canvas = gId("canvasSegments"); - canvas.hidden = false; ctx = canvas.getContext('2d'); peek(canvasPeek); } + let segments = gId("Segments"); let windowWidth = Math.min(window.innerWidth*0.98, maxWidth*30); - ctx.canvas.width = ctx.canvas.parentElement.offsetWidth > 800?windowWidth:300; //Mobile and non pc mode gets 300, pc 800 + let windowWidthFactor = maxWidth > maxHeight?1:maxWidth/maxHeight; + ctx.canvas.width = (segments.offsetWidth > 800?windowWidth:300) * windowWidthFactor; //Mobile and non pc mode gets 300, pc 800 ctx.canvas.height = ctx.canvas.width / maxWidth * maxHeight; - canvasPeek.width = canvasPeek.parentElement.offsetWidth > 800?windowWidth:300; - canvasPeek.height = canvasPeek.width / maxWidth * maxHeight; + canvasPeek.width = ctx.canvas.width; + canvasPeek.height = ctx.canvas.height; ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); var ppL = ctx.canvas.width / maxWidth; //pixels per led // console.log("dim", ctx.canvas.width , maxWidth, ctx.canvas.height , maxHeight, ppL); - ctx.lineWidth = 1; - ctx.strokeStyle="yellow"; - ctx.strokeRect(0, 0, ctx.canvas.width, ctx.canvas.height); - var colorArray = [[255,0,0], [0,255,0], [0,0,255], [255,0,255], [255,165,0], [255,255,0]]; // ["red", "green", "blue", "magenta", "orange", "yellow"]; @@ -1214,9 +1226,11 @@ function drawSegments() { if (!initSegmentVars(p)) break; - ctx.lineWidth = 3; - ctx.strokeStyle="white"; - ctx.strokeRect(topLeftX, topLeftY, pw*ppL, ph*ppL); + if (gId("segcont").children.length > 1) { //Estetic: Don't draw surrounding box if only one segment + ctx.lineWidth = 3; + ctx.strokeStyle="white"; + ctx.strokeRect(topLeftX, topLeftY, pw*ppL, ph*ppL); + } var fx = parseInt(gId("seg"+p+"fx").value); @@ -1292,29 +1306,31 @@ function drawSegments() { } // for each segment - gId("MD").innerHTML = "☾ W*H=LC: " + maxWidth + " x " + maxHeight + " = " + maxWidth * maxHeight; + if (gId("segcont").children.length > 1) { //Only show this if more then one segment + gId("MD").innerHTML = "total W*H=LC: " + maxWidth + " x " + maxHeight + " = " + maxWidth * maxHeight; + } + gId("MD").style.display = gId("segcont").children.length > 1?"inline":"none" function post() { for (let p=0; p1) { //only show number if more than one segment + if (gId("segcont").children.length>1) { //only show number and name if more than one segment ctx.font = '40px Arial'; ctx.fillStyle = "orange"; ctx.fillText(p, topLeftX + pw/2*ppL - 10, topLeftY + ph/2*ppL + 10); + + //show name of fx + ctx.font = '20px Arial'; + ctx.fillStyle = "white"; + var name = eJson.find((o)=>{return o.id==fx}).name; + ctx.fillText(name, topLeftX+10, topLeftY + ph*ppL - 10); } - - //show name of fx - ctx.font = '20px Arial'; - ctx.fillStyle = "white"; - var name = eJson.find((o)=>{return o.id==fx}).name; - ctx.fillText(name, topLeftX + ppL, topLeftY + ph*ppL - 10); } } //draw the ledmap if (ledmapNr>=0 && ctx) { //WLEDMM: @Troy#2642 : include ledmap = 0 as default ledmap - // console.log("Before fetch ledmap ", lastinfo.ledmap); var fileName; if (ledmapNr==0) fileName = "ledmap.json"; //0 is ledmap.json, not ledmap0.json @@ -1322,14 +1338,21 @@ function drawSegments() { fileName = "ledmap"+ledmapNr+".json"; else fileName = ledmapFileNames[ledmapNr-10]; + fetchAndExecute((loc?`http://${locip}`:'.') + "/", fileName , function(text) { var ledmapJson = JSON.parse(text); var counter = 0; var noMap = []; for (let i=0;i=0) customMappingTable[ledmapJson["map"][i]] = i; + + for (let i=0;i