From 3df6f286a63c9cf1a593cca81eaaebf86396673c Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 5 May 2023 13:32:35 +0200 Subject: [PATCH 1/3] game of life: minor change to stay compatible with newer FastLed versions added explicit conversion operator CRGB -> uint32_t --- wled00/FX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index acde24a9..dc0708a1 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -4922,7 +4922,7 @@ uint16_t mode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https: } // i,j // Rules of Life - uint32_t col = prevLeds[XY(x,y)]; + uint32_t col = uint32_t(prevLeds[XY(x,y)]); // softhack007: explicit conversion added - needed with newer fastled releases uint32_t bgc = RGBW32(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0); if ((col != bgc) && (neighbors < 2)) SEGMENT.setPixelColorXY(x,y, bgc); // Loneliness else if ((col != bgc) && (neighbors > 3)) SEGMENT.setPixelColorXY(x,y, bgc); // Overpopulation From 61bbea0e5e8504204ff5ec940e1ed3df5126b9a7 Mon Sep 17 00:00:00 2001 From: Frank <91616163+softhack007@users.noreply.github.com> Date: Fri, 5 May 2023 18:07:00 +0200 Subject: [PATCH 2/3] bugfix for large JSON files (>64Kb) WLED was using uint16_t internally to index files, which leads to random behaviour when the real filesize is above 64Kb. Better to use size_t which is the "right" type that can hold the largest possible size. --- wled00/file.cpp | 52 ++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/wled00/file.cpp b/wled00/file.cpp index 1186560e..ec9d800b 100644 --- a/wled00/file.cpp +++ b/wled00/file.cpp @@ -10,7 +10,11 @@ #endif #endif +#if defined(WLEDMM_FASTPATH) // WLEMM use bigger buffer when reading, to reduce number of file operations +#define FS_BUFSIZE 512 +#else #define FS_BUFSIZE 256 +#endif /* * Structural requirements for files managed by writeObjectToFile() and readObjectFromFile() utilities: @@ -27,9 +31,10 @@ // There are no consecutive spaces longer than this in the file, so if more space is required, findSpace() can return false immediately // Actual space may be lower -uint16_t knownLargestSpace = UINT16_MAX; +constexpr size_t MAX_SPACE = UINT16_MAX * 2U; // WLEDMM smallest supported config has 128Kb flash size +static volatile size_t knownLargestSpace = MAX_SPACE; -File f; +static File f; // WLEDMM //wrapper to find out how long closing takes void closeFile() { @@ -44,7 +49,7 @@ void closeFile() { //find() that reads and buffers data from file stream in 256-byte blocks. //Significantly faster, f.find(key) can take SECONDS for multi-kB files -bool bufferedFind(const char *target, bool fromStart = true) { +static bool bufferedFind(const char *target, bool fromStart = true) { #ifdef WLED_DEBUG_FS DEBUGFS_PRINT("Find "); DEBUGFS_PRINTLN(target); @@ -59,8 +64,8 @@ bool bufferedFind(const char *target, bool fromStart = true) { if (fromStart) f.seek(0); while (f.position() < f.size() -1) { - uint16_t bufsize = f.read(buf, FS_BUFSIZE); - uint16_t count = 0; + size_t bufsize = f.read(buf, FS_BUFSIZE); // WLEDMM size_t instead if uint16_t + size_t count = 0; // WLEDMM while (count < bufsize) { if(buf[count] != target[index]) index = 0; // reset index if any char does not match @@ -80,7 +85,7 @@ bool bufferedFind(const char *target, bool fromStart = true) { } //find empty spots in file stream in 256-byte blocks. -bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) { +static bool bufferedFindSpace(size_t targetLen, bool fromStart = true) { #ifdef WLED_DEBUG_FS DEBUGFS_PRINTF("Find %d spaces\n", targetLen); @@ -95,20 +100,20 @@ bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) { if (!f || !f.size()) return false; - uint16_t index = 0; + size_t index = 0; // WLEDMM size_t instead if uint16_t byte buf[FS_BUFSIZE]; if (fromStart) f.seek(0); while (f.position() < f.size() -1) { - uint16_t bufsize = f.read(buf, FS_BUFSIZE); - uint16_t count = 0; + size_t bufsize = f.read(buf, FS_BUFSIZE); // WLEDMM + size_t count = 0; // WLEDMM while (count < bufsize) { if(buf[count] == ' ') { if(++index >= targetLen) { // return true if space long enough if (fromStart) { f.seek((f.position() - bufsize) + count +1 - targetLen); - knownLargestSpace = UINT16_MAX; //there may be larger spaces after, so we don't know + knownLargestSpace = MAX_SPACE; //there may be larger spaces after, so we don't know // WLEDMM smallest supported config has 128Kb flash size } DEBUGFS_PRINTF("Found at pos %d, took %d ms", f.position(), millis() - s); return true; @@ -116,7 +121,7 @@ bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) { } else { if (!fromStart) return false; if (index) { - if (knownLargestSpace < index || knownLargestSpace == UINT16_MAX) knownLargestSpace = index; + if (knownLargestSpace < index || (knownLargestSpace == MAX_SPACE)) knownLargestSpace = index; // WLEDMM index = 0; // reset index if not space } } @@ -129,7 +134,7 @@ bool bufferedFindSpace(uint16_t targetLen, bool fromStart = true) { } //find the closing bracket corresponding to the opening bracket at the file pos when calling this function -bool bufferedFindObjectEnd() { +static bool bufferedFindObjectEnd() { #ifdef WLED_DEBUG_FS DEBUGFS_PRINTLN(F("Find obj end")); uint32_t s = millis(); @@ -142,8 +147,8 @@ bool bufferedFindObjectEnd() { byte buf[FS_BUFSIZE]; while (f.position() < f.size() -1) { - uint16_t bufsize = f.read(buf, FS_BUFSIZE); - uint16_t count = 0; + size_t bufsize = f.read(buf, FS_BUFSIZE); // WLEDMM size_t instead of uint16_t + size_t count = 0; // WLEDMM while (count < bufsize) { if (buf[count] == '{') objDepth++; @@ -161,13 +166,13 @@ bool bufferedFindObjectEnd() { } //fills n bytes from current file pos with ' ' characters -void writeSpace(uint16_t l) +static void writeSpace(size_t l) { byte buf[FS_BUFSIZE]; memset(buf, ' ', FS_BUFSIZE); while (l > 0) { - uint16_t block = (l>FS_BUFSIZE) ? FS_BUFSIZE : l; + size_t block = (l>FS_BUFSIZE) ? FS_BUFSIZE : l; // WLEDMM size_t instead of uint16_t f.write(buf, block); l -= block; } @@ -270,9 +275,11 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) s = millis(); #endif - uint32_t pos = 0; + size_t pos = 0; f = WLED_FS.open(file, "r+"); - if (!f && !WLED_FS.exists(file)) f = WLED_FS.open(file, "w+"); + if (!f && !WLED_FS.exists(file)) { f = WLED_FS.open(file, "w+"); + if(f) { DEBUG_PRINTF(PSTR("FILE '%s' open to write, size =%d\n"), file, (int)f.size());} // WLEDMM additional debug message + } if (!f) { DEBUGFS_PRINTLN(F("Failed to open!")); return false; @@ -287,7 +294,7 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) pos = f.position(); //measure out end of old object bufferedFindObjectEnd(); - uint32_t pos2 = f.position(); + size_t pos2 = f.position(); // WLEDMM uint32_t oldLen = pos2 - pos; DEBUGFS_PRINTF("Old obj len %d\n", oldLen); @@ -298,7 +305,7 @@ bool writeObjectToFile(const char* file, const char* key, JsonDocument* content) //3. The new content is larger than the old, but smaller than old + trailing spaces, overwrite with new //4. The new content is larger than old + trailing spaces, delete old and append - uint32_t contentLen = 0; + size_t contentLen = 0; // WLEDMM if (!content->isNull()) contentLen = measureJson(*content); if (contentLen && contentLen <= oldLen) { //replace and fill diff with spaces @@ -341,6 +348,7 @@ bool readObjectFromFile(const char* file, const char* key, JsonDocument* dest) #endif f = WLED_FS.open(file, "r"); if (!f) return false; + else { DEBUG_PRINTF(PSTR("FILE '%s' open to read, size %d bytes\n"), file, (int)f.size());} // WLEDMM additional debug message if (key != nullptr && !bufferedFind(key)) //key does not exist in file { @@ -375,7 +383,7 @@ void updateFSInfo() { //Un-comment any file types you need -String getContentType(AsyncWebServerRequest* request, String filename){ +static String getContentType(AsyncWebServerRequest* request, String filename){ if(request->hasArg("download")) return "application/octet-stream"; else if(filename.endsWith(".htm")) return "text/html"; else if(filename.endsWith(".html")) return "text/html"; @@ -394,7 +402,7 @@ String getContentType(AsyncWebServerRequest* request, String filename){ } bool handleFileRead(AsyncWebServerRequest* request, String path){ - DEBUG_PRINTLN("FileRead: " + path); + DEBUG_PRINTLN("WS FileRead: " + path); if(path.endsWith("/")) path += "index.htm"; if(path.indexOf("sec") > -1) return false; String contentType = getContentType(request, path); From b22d94f154a3b20f2a31ef11f728f0b2cecf70eb Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 6 May 2023 15:40:27 +0200 Subject: [PATCH 3/3] Freqmatrix math optimizations * avoid over-complicated math stunts (pixVal to intensity to value) * more accurate handling of sensitivity * better default values --- wled00/FX.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/wled00/FX.cpp b/wled00/FX.cpp index dc0708a1..cae0b2b1 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -6966,15 +6966,14 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch SEGMENT.fill(BLACK); } - uint8_t secondHand = micros()/(256-SEGMENT.speed)/500 % 16; + uint8_t secondHand = (SEGMENT.speed < 255) ? (micros()/(256-SEGMENT.speed)/500 % 16) : 0; if((SEGMENT.speed > 254) || (SEGENV.aux0 != secondHand)) { // WLEDMM allow run run at full speed SEGENV.aux0 = secondHand; - uint8_t sensitivity = map(SEGMENT.custom3, 0, 31, 1, 10); // reduced resolution slider - int pixVal = (volumeSmth * SEGMENT.intensity * sensitivity) / 256.0f; - if (pixVal > 255) pixVal = 255; - - float intensity = map(pixVal, 0, 255, 0, 100) / 100.0f; // make a brightness from the last avg + // Pixel brightness (value) based on volume * sensitivity * intensity + uint_fast8_t sensitivity10 = map(SEGMENT.custom3, 0, 31, 10, 100); // reduced resolution slider // WLEDMM sensitivity * 10, to avoid losing precision + int pixVal = volumeSmth * (float)SEGMENT.intensity * (float)sensitivity10 / 2560.0f; // WLEDMM 2560 due to sensitivity * 10 + if (pixVal > 255) pixVal = 255; // make a brightness from the last avg CRGB color = CRGB::Black; @@ -6983,15 +6982,15 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch // With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz // we will treat everything with less than 65Hz as 0 - if (FFT_MajorPeak < 80) { - color = CRGB::Black; - } else { + if ((FFT_MajorPeak > 80.0f) && (volumeSmth > 0.25f)) { // WLEDMM + // Pixel color (hue) based on major frequency int upperLimit = 80 + 42 * SEGMENT.custom2; int lowerLimit = 80 + 3 * SEGMENT.custom1; - uint8_t i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // may under/overflow - so we enforce uint8_t - uint16_t b = 255 * intensity; - if (b > 255) b = 255; - color = CHSV(i, 240, (uint8_t)b); // implicit conversion to RGB supplied by FastLED + //uint8_t i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // (original formula) may under/overflow - so we enforce uint8_t + int freqMapped = lowerLimit!=upperLimit ? mapf(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // WLEDMM preserve overflows + uint8_t i = abs(freqMapped) & 0xFF; // WLEDMM we embrace overflow ;-) by "modulo 256" + + color = CHSV(i, 240, (uint8_t)pixVal); // implicit conversion to RGB supplied by FastLED } // shift the pixels one pixel up @@ -7001,7 +7000,7 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch return FRAMETIME; } // mode_freqmatrix() -static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Time delay,Sound effect,Low bin,High bin,Sensivity;;;1f;m12=3,si=0"; // Corner, Beatsin +static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Time delay,Sound effect,Low bin,High bin,Sensivity;;;1f;c1=18,c2=48,c3=6,m12=3,si=0"; // Corner, Beatsin; notes range C3 to C7 ////////////////////// @@ -7093,7 +7092,7 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun // direct frequency scaling int upperLimit = 80 + 42 * SEGMENT.custom2; // max 80hz-10Khz int lowerLimit = 80 + 3 * SEGMENT.custom1; // min 80hz-850hz - i = lowerLimit!=upperLimit ? map(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // may under/overflow - so we enforce uint8_t + i = lowerLimit!=upperLimit ? mapf(FFT_MajorPeak, lowerLimit, upperLimit, 0, 255) : FFT_MajorPeak; // may under/overflow - so we enforce uint8_t } else { // Musical Scale (logarythmic scaling) float upperLimit = logf(80 + 42 * SEGMENT.custom2); // max 80hz-10Khz