Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions Archive/Docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -1084,9 +1084,7 @@ Pretty much the same as MI, but with the following tweaks for Organelle Mother o
---

## Screensaver <a name="screensaver"></a>
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.

---

Expand Down
131 changes: 70 additions & 61 deletions Archive/OMX-27-firmware/src/modes/omx_screensaver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down Expand Up @@ -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();
}
14 changes: 9 additions & 5 deletions Archive/OMX-27-firmware/src/modes/omx_screensaver.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,23 @@ 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;

private:
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;
Expand All @@ -41,4 +45,4 @@ class OmxScreensaver : public OmxModeInterface
int sleepTick = 80;

bool screenSaverActive;
};
};