Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macropad hotkeys: Add screensaver mode to prevent OLED burn-in #2883

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
48 changes: 47 additions & 1 deletion Macropad_Hotkeys/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,29 @@
# CONFIGURABLES ------------------------

MACRO_FOLDER = '/macros'

SCREENSAVER_START_TIME = 10 * 60 # seconds of inactivity will clear oled to avoid burn in

# CLASSES AND FUNCTIONS ----------------

class App:
""" Class representing a host-side application, for which we have a set
of macro sequences. Project code was originally more complex and
this was helpful, but maybe it's excessive now?"""

# Class-level variables (shared among all instances)
last_activity_time = time.monotonic()
in_screensaver_mode = False
breathing_brightness = 0.1 # Initial brightness
breathing_direction = 1 # 1 for increasing brightness, -1 for decreasing

def __init__(self, appdata):
self.name = appdata['name']
self.macros = appdata['macros']

def switch(self):
""" Activate application settings; update OLED labels and LED
colors. """
App.last_activity_time = time.monotonic()
group[13].text = self.name # Application name
if self.name:
rect.fill = 0xFFFFFF
Expand All @@ -57,6 +65,29 @@ def switch(self):
macropad.pixels.show()
macropad.display.refresh()

# SCREENSAVER MODE HELPERS -------------

def enter_screensaver_mode():
macropad.display.auto_refresh = False
macropad.display_sleep = True
for i in range(12):
macropad.pixels[i] = 0 # Turn off all key LEDs
macropad.pixels.show()
App.in_screensaver_mode = True

def wake_from_screensaver():
App.in_screensaver_mode = False
macropad.display_sleep = False
macropad.display.auto_refresh = True
apps[app_index].switch() # Redraw the OLED and LEDs

def screensaver_breathing_effect():
App.breathing_brightness += 0.001 * App.breathing_direction
if App.breathing_brightness >= 1.0 or App.breathing_brightness <= 0.1:
App.breathing_direction *= -1 # Reverse direction
pixel_brightness = int(255 * App.breathing_brightness)
macropad.pixels[0] = (0, pixel_brightness, 0) # Green key for breathing effect
macropad.pixels.show()

# INITIALIZATION -----------------------

Expand Down Expand Up @@ -111,9 +142,13 @@ def switch(self):
# MAIN LOOP ----------------------------

while True:
current_time = time.monotonic()

# Read encoder position. If it's changed, switch apps.
position = macropad.encoder
if position != last_position:
if App.in_screensaver_mode:
wake_from_screensaver()
app_index = position % len(apps)
apps[app_index].switch()
last_position = position
Expand All @@ -132,6 +167,12 @@ def switch(self):
else:
event = macropad.keys.events.get()
if not event or event.key_number >= len(apps[app_index].macros):
if App.in_screensaver_mode:
screensaver_breathing_effect() # Continue breathing effect in screensaver mode
else:
time_since_last_activity = current_time - App.last_activity_time
if time_since_last_activity > SCREENSAVER_START_TIME:
enter_screensaver_mode()
continue # No key events, or no corresponding macro, resume loop
key_number = event.key_number
pressed = event.pressed
Expand All @@ -140,8 +181,13 @@ def switch(self):
# and there IS a corresponding macro available for it...other situations
# are avoided by 'continue' statements above which resume the loop.

App.last_activity_time = current_time # Reset inactivity timer
sequence = apps[app_index].macros[key_number][2]
if pressed:
if App.in_screensaver_mode:
wake_from_screensaver()
continue # Skip this event, as it was used for screen wake up

# 'sequence' is an arbitrary-length list, each item is one of:
# Positive integer (e.g. Keycode.KEYPAD_MINUS): key pressed
# Negative integer: (absolute value) key released
Expand Down