diff --git a/Archive/Docs.md b/Archive/Docs.md index 8cbf80f..2015331 100644 --- a/Archive/Docs.md +++ b/Archive/Docs.md @@ -1084,9 +1084,7 @@ Pretty much the same as MI, but with the following tweaks for Organelle Mother o --- ## Screensaver -After a default timeout (3 minutes), the display will be blanked and in MI Mode a "screensaver" animation will show on the LEDs. The rightmost pot (#5) can be turned to adjust the color. Touching any keys or any of the other pots will exit the screensaver. - -In S1/S2 the screen will blank, but there is no LED animation. +After a default timeout (3 minutes), the display will be blanked and a "screensaver" animation will show on the white keyboard LEDs. The rightmost pot (#5) can be turned to adjust the color. Turning it all the way down will turn off the LEDs. Touching any keys or any of the other pots will exit the screensaver. --- diff --git a/Archive/OMX-27-firmware/src/modes/omx_screensaver.cpp b/Archive/OMX-27-firmware/src/modes/omx_screensaver.cpp index f3cf5e1..7c37db0 100644 --- a/Archive/OMX-27-firmware/src/modes/omx_screensaver.cpp +++ b/Archive/OMX-27-firmware/src/modes/omx_screensaver.cpp @@ -5,6 +5,7 @@ #include "../hardware/omx_disp.h" #include "../hardware/omx_leds.h" +// Maps pot value to full HSV hue range (0-65535) void OmxScreensaver::setScreenSaverColor() { colorConfig.screensaverColor = map(potSettings.analog[4]->getValue(), potMinVal, potMaxVal, 0, ssMaxColorDepth); @@ -28,12 +29,12 @@ void OmxScreensaver::updateScreenSaverState() { if (screenSaverCounter > screensaverInterval) { - if (!screenSaverActive) - { - screenSaverActive = true; - setScreenSaverColor(); - } - } + if (!screenSaverActive) + { + screenSaverActive = true; + setScreenSaverColor(); + } + } else if (screenSaverCounter < 10) { ssstep = 0; @@ -75,71 +76,79 @@ void OmxScreensaver::resetCounter() void OmxScreensaver::updateLEDs() { - unsigned long playstepmillis = millis(); - if (playstepmillis > nextStepTimeSS) + // - Animation state advances on time gate (every 80ms) + // - LED rendering happens EVERY call for instant color response + // - Smooth gradient wave animation with optimized RGB scaling + unsigned long currentMillis = millis(); + + // Advance animation state on time gate only + if (currentMillis >= nextStepTimeSS) { - ssstep = ssstep % 16; - ssloop = ssloop % 16; + ssstep++; + if (ssstep >= 16) + { + ssstep = 0; + ssloop++; + if (ssloop >= 16) + { + ssloop = 0; + } + } + nextStepTimeSS = currentMillis + sleepTick; + } - int j = 26 - ssloop; - int i = ssstep + 11; + // Always turn off keypad LEDs (1-10) + for (int z = 1; z < 11; z++) + { + strip.setPixelColor(z, 0, 0, 0); + } - for (int z = 1; z < 11; z++) + // Check for LED off mode (pot at minimum) + if (colorConfig.screensaverColor < ssMinThreshold) + { + for (int w = 11; w < 27; w++) { - strip.setPixelColor(z, 0); + strip.setPixelColor(w, 0, 0, 0); } - if (colorConfig.screensaverColor < ssMaxColorDepth) + } + else + { + // Calculate base color once, then scale RGB per LED + const uint32_t baseColor = strip.ColorHSV(colorConfig.screensaverColor, 255, 255); + const uint8_t baseR = (baseColor >> 16) & 0xFF; + const uint8_t baseG = (baseColor >> 8) & 0xFF; + const uint8_t baseB = baseColor & 0xFF; + + // Wave position: 0-255 continuous range, multiply by 4 for visible speed + const int wavePos = ((ssloop * 16 + ssstep) * 4) & 0xFF; + + // Render smooth traveling gradient wave + for (int ledNum = 0; ledNum < 16; ledNum++) { - if (!ssreverse) + const int ledIndex = ledNum + 11; + + // Calculate phase: creates one wavelength across the 16 LEDs + int phase = (wavePos + (ledNum * 16)) & 0xFF; + + // Triangle wave for smooth brightness: 0 -> 255 -> 0 + uint8_t brightness; + if (phase < 128) { - // turn off all leds - for (int x = 0; x < 16; x++) - { - if (i < j) - { - strip.setPixelColor(x + 11, 0); - } - if (x + 11 > j) - { - strip.setPixelColor(x + 11, strip.gamma32(strip.ColorHSV(colorConfig.screensaverColor))); - } - } - strip.setPixelColor(i + 1, strip.gamma32(strip.ColorHSV(colorConfig.screensaverColor))); + brightness = phase * 2; } else { - for (int y = 0; y < 16; y++) - { - if (i >= j) - { - strip.setPixelColor(y + 11, 0); - } - if (y + 11 < j) - { - strip.setPixelColor(y + 11, strip.gamma32(strip.ColorHSV(colorConfig.screensaverColor))); - } - } - strip.setPixelColor(i + 1, strip.gamma32(strip.ColorHSV(colorConfig.screensaverColor))); + brightness = (255 - phase) * 2; } - } - else - { - for (int w = 0; w < 27; w++) - { - strip.setPixelColor(w, 0); - } - } - ssstep++; - if (ssstep == 16) - { - ssloop++; - } - if (ssloop == 16) - { - ssreverse = !ssreverse; - } - nextStepTimeSS = nextStepTimeSS + sleepTick; - omxLeds.setDirty(); + // Scale RGB by brightness (fast integer math) + const uint8_t r = (baseR * brightness) >> 8; + const uint8_t g = (baseG * brightness) >> 8; + const uint8_t b = (baseB * brightness) >> 8; + + strip.setPixelColor(ledIndex, strip.gamma32(strip.Color(r, g, b))); + } } -} + + omxLeds.setDirty(); +} \ No newline at end of file diff --git a/Archive/OMX-27-firmware/src/modes/omx_screensaver.h b/Archive/OMX-27-firmware/src/modes/omx_screensaver.h index b7abd7b..9ade481 100644 --- a/Archive/OMX-27-firmware/src/modes/omx_screensaver.h +++ b/Archive/OMX-27-firmware/src/modes/omx_screensaver.h @@ -19,11 +19,11 @@ class OmxScreensaver : public OmxModeInterface void onEncoderChanged(Encoder::Update enc) override; - void onEncoderButtonDown() override{}; - void onEncoderButtonDownLong() override{}; + void onEncoderButtonDown() override {}; + void onEncoderButtonDownLong() override {}; void onKeyUpdate(OMXKeypadEvent e) override; - void onKeyHeldUpdate(OMXKeypadEvent e){}; + void onKeyHeldUpdate(OMXKeypadEvent e) {}; void onDisplayUpdate() override; @@ -31,7 +31,11 @@ class OmxScreensaver : public OmxModeInterface void setScreenSaverColor(); elapsedMillis screenSaverCounter = 0; unsigned long screensaverInterval = 1000 * 60 * 3; // 3 minutes default - uint32_t ssMaxColorDepth = 65528; // used by setScreenSaverColor(). Allows for full rainbow of colors, plus a little extra for 'black' + // unsigned long screensaverInterval = 1000 * 10; // 10 sec for debug + + // Pot 5 (analog[4]) controls color via HSV hue value (0-65535 for full rainbow) + uint32_t ssMaxColorDepth = 65535; // Full HSV color range (16-bit) + uint32_t ssMinThreshold = 1000; // Below this value = LEDs off int ssstep = 0; int ssloop = 0; @@ -41,4 +45,4 @@ class OmxScreensaver : public OmxModeInterface int sleepTick = 80; bool screenSaverActive; -}; +}; \ No newline at end of file