diff --git a/platformio.ini b/platformio.ini index 93ca4974..94bb35e7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -187,6 +187,7 @@ build_flags = -D DECODE_SONY=true -D DECODE_SAMSUNG=true -D DECODE_LG=true + -D FASTLED_NO_FASTLED ;-Dregister= # remove warnings in C++17 due to use of deprecated register keyword by the FastLED library ;; warning: this breaks framework code on ESP32-C3 and ESP32-S2 -DWLED_USE_MY_CONFIG ; -D USERMOD_SENSORSTOMQTT @@ -240,6 +241,8 @@ upload_speed = 115200 lib_compat_mode = strict lib_deps = fastled/FastLED @ 3.6.0 + ;; fastled/FastLED @ 3.7.1 + ;; https://github.com/softhack007/FastLED.git#ESP32-C6 ;; patched version needed for -C6 IRremoteESP8266 @ 2.8.2 ;;makuna/NeoPixelBus @ 2.7.5 ;; WLEDMM will be added in board specific sections ;;https://github.com/Aircoookie/ESPAsyncWebServer.git @ ~2.0.7 @@ -1602,6 +1605,67 @@ lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation ; RAM: [=== ] 28.1% (used 91960 bytes from 327680 bytes) ; Flash: [==========] 97.8% (used 1537777 bytes from 1572864 bytes) + +;; softhack007: my favourite HUB75 buildenv - fastest possible +[env:esp32_4MB_V4_HUB75_forum] +extends = esp32_4MB_V4_S_base +platform_packages = ${esp32_4MB_V4_S_base.platform_packages} +;; toolchain-xtensa-esp32@~11.2 ;; for trying out newer gcc @11.2.0+2022r1 ;; 25fps -> 30fps;; FastLED 3.7.1 required !! + +build_unflags = ${esp32_4MB_V4_S_base.build_unflags} + ${Speed_Flags.build_unflags} ;; to override -Os + ;; -D WLED_ENABLE_DMX_INPUT + -DARDUINO_EVENT_RUNNING_CORE=1 + ;;-DCORE_DEBUG_LEVEL=0 + ;; -D NDEBUG + -D NO_CIE1931 ;; Do use LED brightness compensation described in CIE 1931 + +build_flags = ${esp32_4MB_V4_S_base.esp32_build_flags} + ;; -Wsuggest-attribute=const -Wsuggest-attribute=pure + ;; -Wmissing-noreturn -Wmissing-return + ;; -Wall -Wextra + -Wno-unused-value -Wno-format -Wno-type-limits + -D WLED_RELEASE_NAME=esp32_4MB_V4_HUB75 + ${Speed_Flags.build_flags} ;; -O2 -> optimize for speed instead of size + ;; -D 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 WLEDMM_FASTPATH ; WLEDMM experimental option. Reduces audio lag (latency), and allows for faster LED framerates. May break compatibility with previous versions. + -D WLED_DISABLE_LOXONE + -D WLED_DISABLE_ALEXA + -D WLED_DISABLE_HUESYNC + -D WLED_DISABLE_MQTT + -D WLED_DISABLE_INFRARED + -D WLED_DISABLE_ADALIGHT + ;; -D WLED_DEBUG + ;; -D SR_DEBUG + -D WLED_BOOTUPDELAY=350 + -D WLED_ENABLE_HUB75MATRIX -DESP32_FORUM_PINOUT + ;; -D HUB75_NO_DOUBLEBUFFER ;; -D PIXEL_COLOUR_DEPTH_BITS=12 + ${common_mm.animartrix_build_flags} + ;;-DARDUINO_EVENT_RUNNING_CORE=0 ;; assign Wifi to core0, to have more CPU on core#1 (arduino loop) + ;;-DARDUINO_RUNNING_CORE=1 ;; should be default, but does not hurt + -DCONFIG_MBEDTLS_DYNAMIC_BUFFER=1 ;; optional - seems to move more buffers into PSRAM + ;; -D CONFIG_ESP32_REV_MIN=3 ;; disables PSRAM bug workarounds in the core, reducing the code size and improving overall performance. + -D JSON_BUFFER_SIZE=18432 -D MIN_HEAP_SIZE=6144 + -D MAX_SEGMENT_DATA=40960 ;; default 32767 + -D WLEDMM_SAVE_FLASH + -D WLED_DISABLE_BROWNOUT_DET + ;;-DCORE_DEBUG_LEVEL=1 + ;;-D WLED_DISABLE_PARTICLESYSTEM1D + ;;-D WLED_DISABLE_PARTICLESYSTEM2D + ;;-D WLED_DISABLE_PARTICLESYSTEM_BUFFER + +lib_deps = ${esp32_4MB_V4_S_base.esp32_lib_deps} + ${common_mm.animartrix_lib_deps} +lib_ignore = IRremoteESP8266 ; use with WLED_DISABLE_INFRARED for faster compilation + ;; ${common_mm.DMXin_lib_ignore} + +board_build.partitions = ${esp32.big_partitions} +board_build.f_flash = 80000000L ; use full 80MHz speed for flash (default = 40Mhz) +board_build.flash_mode = qio ; (dio = dual i/o; more compatible than qio = quad i/o) + + ; compiled with ESP-IDF 4.4.1 [env:esp32_4MB_V4_M] extends = esp32_4MB_V4_M_base diff --git a/wled00/FX.cpp b/wled00/FX.cpp index ad7e95d3..bd95e060 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -98,6 +98,14 @@ static long map2(long x, long in_min, long in_max, long out_min, long out_max) } +static um_data_t* getAudioData() { + um_data_t *um_data; + if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + // add support for no audio + um_data = simulateSound(SEGMENT.soundSim); + } + return um_data; +} // effect functions /* @@ -1994,11 +2002,7 @@ uint16_t mode_partyjerk() { * step: pos */ - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; SEGENV.aux0++; @@ -6519,11 +6523,7 @@ uint16_t mode_ripplepeak(void) { // * Ripple peak. By Andrew Tuli if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Ripple* ripples = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; #ifdef ESP32 float FFT_MajorPeak = *(float*) um_data->u_data[4]; @@ -6619,11 +6619,7 @@ uint16_t mode_2DSwirl(void) { uint8_t nj = (cols - 1) - j; uint16_t ms = strip.now; - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //ewowi: use instead of sampleAvg??? int16_t volumeRaw = *(int16_t*) um_data->u_data[1]; @@ -6656,11 +6652,7 @@ uint16_t mode_2DWaverly(void) { SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; float agcSensitivity= *(float*) um_data->u_data[10]; @@ -6714,11 +6706,7 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; //SEGMENT.fade_out(240); @@ -6766,11 +6754,7 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // printUmData(); @@ -6817,11 +6801,7 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; // int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; //WLEDMM: this variable not used here float soundPressure = *(float*) um_data->u_data[9]; @@ -6894,11 +6874,7 @@ static const char _data_FX_MODE_GRAVIMETER[] PROGMEM = "Gravimeter ☾@Rate of f // * JUGGLES // ////////////////////// uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -6921,11 +6897,7 @@ static const char _data_FX_MODE_JUGGLES[] PROGMEM = "Juggles@!,# of balls;!,!;!; uint16_t mode_matripix(void) { // Matripix. By Andrew Tuline. With some enhancements by @softhack007 // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; float volumeSmth = *(float*) um_data->u_data[0]; float soundPressure = *(float*) um_data->u_data[9]; @@ -6977,11 +6949,7 @@ static const char _data_FX_MODE_MATRIPIX[] PROGMEM = "Matripix ☾@!,Brightness, uint16_t mode_midnoise(void) { // Midnoise. By Andrew Tuline. // Changing xdist to SEGENV.aux0 and ydist to SEGENV.aux1. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -7020,11 +6988,7 @@ uint16_t mode_noisefire(void) { // Noisefire. By Andrew Tuline. CRGB::DarkOrange, CRGB::DarkOrange, CRGB::Orange, CRGB::Orange, CRGB::Yellow, CRGB::Orange, CRGB::Yellow, CRGB::Yellow); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) SEGMENT.fill(BLACK); @@ -7048,11 +7012,7 @@ static const char _data_FX_MODE_NOISEFIRE[] PROGMEM = "Noisefire@!,!;;;01v;m12=2 /////////////////////// uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7090,11 +7050,7 @@ uint16_t mode_pixelwave(void) { // Pixelwave. By Andrew Tuline. SEGMENT.fill(BLACK); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; uint8_t secondHand = micros()/(256-SEGMENT.speed)/500+1 % 16; @@ -7128,11 +7084,7 @@ uint16_t mode_plasmoid(void) { // Plasmoid. By Andrew Tuline. if (!SEGENV.allocateData(sizeof(plasphase))) return mode_static(); //allocation failed Plasphase* plasmoip = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) { @@ -7171,11 +7123,7 @@ uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline. uint8_t fadeVal = map2(SEGMENT.speed,0,255, 224, 254); uint16_t pos = random16(SEGLEN); // Set a random starting position. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; uint8_t *binNum = (uint8_t*)um_data->u_data[7]; @@ -7223,11 +7171,7 @@ uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline. } SEGMENT.fade_out(fadeVal); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); int16_t volumeRaw = *(int16_t*)um_data->u_data[1]; if (volumeRaw > 1) { @@ -7252,10 +7196,7 @@ uint16_t mode_pixels(void) { // Pixels. By Andrew Tuline. if (!SEGENV.allocateData(32*sizeof(uint8_t))) return mode_static(); //allocation failed uint8_t *myVals = reinterpret_cast(SEGENV.data); // Used to store a pile of samples because WLED frame rate and WLED sample rate are not synchronized. Frame rate is too low. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float volumeSmth = *(float*) um_data->u_data[0]; if (SEGENV.call == 0) {SEGENV.setUpLeds(); SEGMENT.fill(BLACK);} // WLEDMM use lossless getPixelColor() @@ -7285,11 +7226,7 @@ static const char _data_FX_MODE_PIXELS[] PROGMEM = "Pixels@Fade rate,# of pixels uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; if (SEGENV.call == 0) { @@ -7319,11 +7256,7 @@ static const char _data_FX_MODE_BLURZ[] PROGMEM = "Blurz@Fade rate,Blur;!,Color uint16_t mode_blurz(void) { // Blurz. By Andrew Tuline. // Hint: Looks best with segment brightness set to max (use global brightness to reduce brightness) // even with 1D effect we have to take logic for 2D segments for allocation as fill_solid() fills whole segment - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7371,11 +7304,7 @@ uint16_t mode_DJLight(void) { // Written by Stefan Petrick, Ad // No need to prevent from executing on single led strips, only mid will be set (mid = 0) const int mid = SEGLEN / 2; - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7441,11 +7370,7 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN. // Start frequency = 60 Hz and log10(60) = 1.78 // End frequency = MAX_FREQUENCY in Hz and lo10(MAX_FREQUENCY) = MAX_FREQ_LOG10 - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[SEGENV.check1 ? 8:4]; // WLEDMM may use FFT_MajorPeakSmth float my_magnitude = *(float*)um_data->u_data[5] / 4.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7486,11 +7411,7 @@ static const char _data_FX_MODE_FREQMAP[] PROGMEM = "Freqmap@Fade rate,Starting /////////////////////// uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Pleschung. // No need to prevent from executing on single led strips, we simply change pixel 0 each time and avoid the shift - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7545,11 +7466,7 @@ static const char _data_FX_MODE_FREQMATRIX[] PROGMEM = "Freqmatrix@Speed,Sound e // SEGMENT.speed select faderate // SEGMENT.intensity select colour index uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline. - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float my_magnitude = *(float*)um_data->u_data[5] / 16.0f; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7592,11 +7509,7 @@ static const char _data_FX_MODE_FREQPIXELS[] PROGMEM = "Freqpixels@Fade rate,Sta // Depending on the music stream you have you might find it useful to change the frequency mapping. uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschung. With some enhancements by @softhack007 // As before, this effect can also work on single pixels, we just lose the shifting effect - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; @@ -7666,11 +7579,7 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline. if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed Gravity* gravcen = reinterpret_cast(SEGENV.data); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*)um_data->u_data[4]; float volumeSmth = *(float*)um_data->u_data[0]; if (FFT_MajorPeak < 1) FFT_MajorPeak = 1; // log10(0) is "forbidden" (throws exception) @@ -7719,11 +7628,7 @@ static const char _data_FX_MODE_GRAVFREQ[] PROGMEM = "Gravfreq ☾@Rate of fall, // ** Noisemove // ////////////////////// uint16_t mode_noisemove(void) { // Noisemove. By: Andrew Tuline - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7752,11 +7657,7 @@ static const char _data_FX_MODE_NOISEMOVE[] PROGMEM = "Noisemove@Speed of perlin // ** Rocktaves // ////////////////////// uint16_t mode_rocktaves(void) { // Rocktaves. Same note from each octave is same colour. By: Andrew Tuline - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); float FFT_MajorPeak = *(float*) um_data->u_data[8]; // WLEDMM use FFT_MajorPeakSmth float my_magnitude = *(float*) um_data->u_data[5] / 16.0f; @@ -7800,11 +7701,7 @@ uint16_t mode_waterfall(void) { // Waterfall. By: Andrew Tulin // effect can work on single pixels, we just lose the shifting effect if (SEGENV.call == 0) SEGMENT.fill(BLACK); - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t samplePeak = *(uint8_t*)um_data->u_data[3]; float FFT_MajorPeak = *(float*) um_data->u_data[4]; uint8_t *maxVol = (uint8_t*)um_data->u_data[6]; @@ -7865,11 +7762,7 @@ uint16_t mode_2DGEQ(void) { // By Will Tatam. Code reduction by Ewoud Wijma. if (!SEGENV.allocateData(cols*sizeof(uint16_t))) return mode_static(); //allocation failed uint16_t *previousBarHeight = reinterpret_cast(SEGENV.data); //array of previous bar heights per frequency band - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -7976,11 +7869,7 @@ uint16_t mode_2DFunkyPlank(void) { // Written by ??? Adapted by Wil bandInc = (NUMB_BANDS / cols); } - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values @@ -8069,10 +7958,7 @@ uint16_t mode_2DAkemi(void) { const float lightFactor = 0.15f; const float normalFactor = 0.4f; - um_data_t *um_data = nullptr; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t fftResult[NUM_GEQ_CHANNELS] = {0}; if (um_data->u_data != nullptr) memcpy(fftResult, um_data->u_data[2], sizeof(fftResult)); // WLEDMM buffer curent values float base = fftResult[0]/255.0f; @@ -8458,11 +8344,7 @@ uint16_t mode_GEQLASER(void) { uint16_t horizon = map2(SEGMENT.custom1,0,255,rows-1,0); uint8_t depth = SEGMENT.custom2; // depth of perspective. 255 = infinite ("laser") - um_data_t *um_data; - if (!usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { - // add support for no audio - um_data = simulateSound(SEGMENT.soundSim); - } + um_data_t *um_data = getAudioData(); uint8_t *fftResult = (uint8_t*)um_data->u_data[2]; uint8_t heights[NUM_GEQ_CHANNELS] = { 0 }; diff --git a/wled00/FX.h b/wled00/FX.h index f45556e6..546e8b98 100644 --- a/wled00/FX.h +++ b/wled00/FX.h @@ -87,11 +87,13 @@ bool strip_uses_global_leds(void) __attribute__((pure)); // WLEDMM implemented #ifndef MAX_NUM_SEGMENTS #define MAX_NUM_SEGMENTS 32 #endif + #ifndef MAX_SEGMENT_DATA #if defined(ARDUINO_ARCH_ESP32S2) #define MAX_SEGMENT_DATA 24576 #else #define MAX_SEGMENT_DATA 32767 #endif + #endif #endif /* How much data bytes each segment should max allocate to leave enough space for other segments, @@ -437,6 +439,7 @@ typedef struct Segment { #ifdef WLEDMM_FASTPATH // WLEDMM cache some values that won't change while drawing a frame bool _isSimpleSegment = false; + bool _isSuperSimpleSegment = false; bool _isValid2D = false; uint8_t _brightness = 255; // final pixel brightness - including transitions and segment opacity bool _firstFill = true; // dirty HACK support diff --git a/wled00/FX_2Dfcn.cpp b/wled00/FX_2Dfcn.cpp index 9660df63..bb0b1861 100644 --- a/wled00/FX_2Dfcn.cpp +++ b/wled00/FX_2Dfcn.cpp @@ -241,6 +241,7 @@ void Segment::startFrame(void) { _isValid2D = isActive() && is2D(); _brightness = currentBri(on ? opacity : 0); _isSimpleSegment = (grouping == 1) && (spacing == 0); // we can handle pixels faster when no grouping or spacing is involved + _isSuperSimpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); // fastest - we only draw one pixel per call // if (reverse_y) _isSimpleSegment = false; // for A/B testing _2dWidth = is2D() ? calc_virtualWidth() : virtualLength(); _2dHeight = calc_virtualHeight(); @@ -279,7 +280,11 @@ void IRAM_ATTR __attribute__((hot)) Segment::setPixelColorXY_fast(int x, int y, // set the requested pixel strip.setPixelColorXY_fast(start + x, startY + y, scaled_col); + #ifdef WLEDMM_FASTPATH + bool simpleSegment = _isSuperSimpleSegment; + #else bool simpleSegment = !mirror && !mirror_y; + #endif if (simpleSegment) return; // WLEDMM shortcut when no mirroring needed // handle mirroring @@ -306,7 +311,7 @@ void IRAM_ATTR_YN Segment::setPixelColorXY_slow(int x, int y, uint32_t col) //WL void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: IRAM_ATTR conditionally #endif { - if (Segment::maxHeight==1) return; // not a matrix set-up + if ((Segment::maxHeight==1) || !isActive()) return; // not a matrix set-up const int_fast16_t cols = virtualWidth(); // WLEDMM optimization const int_fast16_t rows = virtualHeight(); @@ -335,7 +340,11 @@ void IRAM_ATTR_YN Segment::setPixelColorXY(int x, int y, uint32_t col) //WLEDMM: if (transpose) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed // WLEDMM shortcut when no grouping/spacing used + #ifdef WLEDMM_FASTPATH + bool simpleSegment = _isSuperSimpleSegment; + #else bool simpleSegment = !mirror && !mirror_y && (grouping == 1) && (spacing == 0); + #endif if (simpleSegment) { strip.setPixelColorXY(start + x, startY + y, col); return; @@ -441,20 +450,21 @@ uint32_t IRAM_ATTR_YN Segment::getPixelColorXY(int x, int y) const { // Blends the specified color with the existing pixel color. void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) { - setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); + if (blend == UINT8_MAX) setPixelColorXY(x, y, color); + else setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. void IRAM_ATTR_YN Segment::addPixelColorXY(int x, int y, uint32_t color, bool fast) { - if (!isActive()) return; // not active - if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY + // if (x >= virtualWidth() || y >= virtualHeight() || x<0 || y<0) return; // if pixel would fall out of virtual segment just exit //WLEDMM uint32_t col = getPixelColorXY(x,y); col = color_add(col, color, fast); setPixelColorXY(x, y, col); } void Segment::fadePixelColorXY(uint16_t x, uint16_t y, uint8_t fade) { - if (!isActive()) return; // not active + // if (!isActive()) return; // not active //WLEDMM sanity check is repeated in getPixelColorXY / setPixelColorXY CRGB pix = CRGB(getPixelColorXY(x,y)).nscale8_video(fade); setPixelColorXY(x, y, pix); } diff --git a/wled00/FX_fcn.cpp b/wled00/FX_fcn.cpp index 0f6eb6da..b5e84039 100644 --- a/wled00/FX_fcn.cpp +++ b/wled00/FX_fcn.cpp @@ -102,6 +102,12 @@ Segment::Segment(const Segment &orig) { DEBUG_PRINTLN(F("-- Copy segment constructor --")); memcpy((void*)this, (void*)&orig, sizeof(Segment)); //WLEDMM copy to this transitional = false; // copied segment cannot be in transition +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to the new segment + // _isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif name = nullptr; data = nullptr; _dataLen = 0; @@ -143,8 +149,17 @@ void Segment::allocLeds() { // move constructor --> moves everything (including buffer) from orig to this Segment::Segment(Segment &&orig) noexcept { DEBUG_PRINTLN(F("-- Move segment constructor --")); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); orig.transitional = false; // old segment cannot be in transition any more +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -169,6 +184,12 @@ Segment& Segment::operator= (const Segment &orig) { // copy source memcpy((void*)this, (void*)&orig, sizeof(Segment)); transitional = false; +#ifdef WLEDMM_FASTPATH + // WLEDMM prevent any fast draw calls to this segment until the next frame starts + //_isValid2D = false; + _isSimpleSegment = false; + _isSuperSimpleSegment = false; +#endif // erase pointers to allocated data name = nullptr; data = nullptr; @@ -196,7 +217,16 @@ Segment& Segment::operator= (Segment &&orig) noexcept { deallocateData(); // free old runtime data if (_t) { delete _t; _t = nullptr; } if (ledsrgb && !Segment::_globalLeds) free(ledsrgb); //WLEDMM: not needed anymore as we will use leds from copy. no need to nullify ledsrgb as it gets new value in memcpy +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any fast draw calls to old and new segment + orig._isSimpleSegment = false; + orig._isSuperSimpleSegment = false; +#endif memcpy((void*)this, (void*)&orig, sizeof(Segment)); +#ifdef WLEDMM_FASTPATH + // WLEDMM temporarily prevent any draw calls to old segment + orig._isValid2D = false; +#endif orig.name = nullptr; orig.data = nullptr; orig._dataLen = 0; @@ -956,8 +986,8 @@ void IRAM_ATTR_YN __attribute__((hot)) Segment::setPixelColor(int i, uint32_t co float rad = 0.0f; for (unsigned count = 0; count < numSteps; count++) { // may want to try float version as well (with or without antialiasing) - int x = roundf(sinf(rad) * radius); - int y = roundf(cosf(rad) * radius); + int x = max(0, min(vW-1, (int)roundf(sinf(rad) * radius))); + int y = max(0, min(vH-1, (int)roundf(cosf(rad) * radius))); setPixelColorXY(x, y, col); if(useSymmetry) setPixelColorXY(y, x, col);// WLEDMM rad += step; @@ -1388,7 +1418,8 @@ void __attribute__((hot)) Segment::fill(uint32_t c) { // Blends the specified color with the existing pixel color. void Segment::blendPixelColor(int n, uint32_t color, uint8_t blend) { - setPixelColor(n, color_blend(getPixelColor(n), color, blend)); + if (blend == UINT8_MAX) setPixelColor(n, color); + else setPixelColor(n, color_blend(getPixelColor(n), color, blend)); } // Adds the specified color with the existing pixel color perserving color balance. @@ -1420,7 +1451,7 @@ void Segment::fadePixelColor(uint16_t n, uint8_t fade) { /* * fade out function, higher rate = quicker fade */ -void Segment::fade_out(uint8_t rate) { +void __attribute__((hot)) Segment::fade_out(uint8_t rate) { if (!isActive()) return; // not active const uint_fast16_t cols = is2D() ? virtualWidth() : virtualLength(); // WLEDMM use fast int types const uint_fast16_t rows = virtualHeight(); // will be 1 for 1D diff --git a/wled00/wled.h b/wled00/wled.h index c1f56732..ed232910 100644 --- a/wled00/wled.h +++ b/wled00/wled.h @@ -8,7 +8,7 @@ */ // version code in format yymmddb (b = daily build) -#define VERSION 2408080 +#define VERSION 2408160 // WLEDMM - you can check for this define in usermods, to only enabled WLEDMM specific code in the "right" fork. Its not defined in AC WLED. #define _MoonModules_WLED_