Skip to content
Snippets Groups Projects
Commit ef4e2ab0 authored by moon2's avatar moon2 :speech_balloon:
Browse files

leds: added random menu mode

parent e9061d24
Branches
Tags
No related merge requests found
.. py:module:: led_patterns
``st3m.ui.led_patterns`` module
===============================
None of these functions call ``leds.update()``, to actually see the changes you have to do that yourself!
.. py:function:: highlight_petal_rgb(num : int, r : float, g : float, b : float, num_leds : int = 5) -> None
Sets the LED closest to the petal and num_leds-1 around it to the given rgb color.
If num_leds is uneven the appearance will be symmetric.
.. py:function:: shift_all_hsv(h : float = 0, s : float = 0, v : float = 0) -> None
Shifts all LEDs by the given values. Clips effective ``s`` and ``v``.
.. py:function:: pretty_pattern() -> None
Generates a random pretty pattern and loads it into the LED buffer.
.. py:function:: set_menu_colors() -> None
If not disabled in settings: Tries to load LED colors from /flash/menu_leds.json. Else, or in
case of missing file, call ``pretty_pattern()``. Note: There is no caching, it tries to attempt
to read the file every time, if you need something faster use ``leds.get_rgb`` to cache it in the
application.
...@@ -50,6 +50,7 @@ User manual ...@@ -50,6 +50,7 @@ User manual
api/ctx.rst api/ctx.rst
api/leds.rst api/leds.rst
api/colours.rst api/colours.rst
api/led_patterns.rst
api/uos.rst api/uos.rst
api/sys_buttons.rst api/sys_buttons.rst
api/sys_display.rst api/sys_display.rst
......
...@@ -3,7 +3,7 @@ import math, random, sys_display ...@@ -3,7 +3,7 @@ import math, random, sys_display
from st3m import settings from st3m import settings
import leds import leds
import sys_display import sys_display
from st3m.ui import colours from st3m.ui import colours, led_patterns
class App(Application): class App(Application):
...@@ -22,12 +22,12 @@ class App(Application): ...@@ -22,12 +22,12 @@ class App(Application):
self.angle = 0 self.angle = 0
self.focused_widget = 1 self.focused_widget = 1
self.active = False self.active = False
self.num_widgets = 4 self.num_widgets = 5
self.overhang = -20 self.overhang = -20
self.line_height = 24 self.line_height = 24
self.input.buttons.app.left.repeat_enable(800, 300) self.input.buttons.app.left.repeat_enable(800, 300)
self.input.buttons.app.right.repeat_enable(800, 300) self.input.buttons.app.right.repeat_enable(800, 300)
self.mid_x = 50 self.mid_x = 42
self.led_accumulator_ms = 0 self.led_accumulator_ms = 0
self.blueish = False self.blueish = False
self.half_time = 600 self.half_time = 600
...@@ -107,6 +107,19 @@ class App(Application): ...@@ -107,6 +107,19 @@ class App(Application):
ctx.text(choices[a] + " ") ctx.text(choices[a] + " ")
return no return no
def draw_boolean(self, label, value, on_str="on", off_str="off"):
ctx = self.ctx
self.draw_widget(label)
if self.widget_no == self.focused_widget and self.active:
value = not value
self.active = False
if value:
ctx.text(on_str)
else:
ctx.text(off_str)
return value
def draw_number(self, label, step_size, no, unit=""): def draw_number(self, label, step_size, no, unit=""):
ctx = self.ctx ctx = self.ctx
self.draw_widget(label) self.draw_widget(label)
...@@ -171,7 +184,21 @@ class App(Application): ...@@ -171,7 +184,21 @@ class App(Application):
self.draw_bg() self.draw_bg()
tmp = self.draw_number( tmp = self.draw_number(
"led brightness", 5, int(settings.num_leds_brightness.value) "display brightness",
5,
int(settings.num_display_brightness.value),
unit="%",
)
if tmp < 5:
tmp = 5
if tmp > 100:
tmp = 100
if tmp != settings.num_display_brightness.value:
settings.num_display_brightness.set_value(tmp)
sys_display.set_backlight(settings.num_display_brightness.value)
tmp = self.draw_number(
"LED brightness", 5, int(settings.num_leds_brightness.value)
) )
if tmp < 5: if tmp < 5:
tmp = 5 tmp = 5
...@@ -181,7 +208,7 @@ class App(Application): ...@@ -181,7 +208,7 @@ class App(Application):
settings.num_leds_brightness.set_value(tmp) settings.num_leds_brightness.set_value(tmp)
leds.set_brightness(settings.num_leds_brightness.value) leds.set_brightness(settings.num_leds_brightness.value)
tmp = self.draw_number("led speed", 5, int(settings.num_leds_speed.value)) tmp = self.draw_number("LED speed", 5, int(settings.num_leds_speed.value))
if tmp < 0: if tmp < 0:
tmp = 0 tmp = 0
elif tmp > 255: elif tmp > 255:
...@@ -194,19 +221,13 @@ class App(Application): ...@@ -194,19 +221,13 @@ class App(Application):
settings.num_leds_speed.set_value(tmp) settings.num_leds_speed.set_value(tmp)
leds.set_slew_rate(settings.num_leds_speed.value) leds.set_slew_rate(settings.num_leds_speed.value)
tmp = self.draw_number( tmp = self.draw_boolean(
"display brightness", "menu LEDs", settings.onoff_leds_random_menu.value, "random", "user"
5,
int(settings.num_display_brightness.value),
unit="%",
) )
if tmp < 5: if tmp != settings.onoff_leds_random_menu.value:
tmp = 5 settings.onoff_leds_random_menu.set_value(tmp)
if tmp > 100: led_patterns.pretty_pattern()
tmp = 100 leds.update()
if tmp != settings.num_display_brightness.value:
settings.num_display_brightness.set_value(tmp)
sys_display.set_backlight(settings.num_display_brightness.value)
self.delta_ms = 0 self.delta_ms = 0
self.select_pressed = False self.select_pressed = False
...@@ -230,15 +251,7 @@ class App(Application): ...@@ -230,15 +251,7 @@ class App(Application):
while self.led_accumulator_ms > self.half_time: while self.led_accumulator_ms > self.half_time:
self.led_accumulator_ms = self.led_accumulator_ms % self.half_time self.led_accumulator_ms = self.led_accumulator_ms % self.half_time
self.leds_shift_hue(0.8) led_patterns.shift_all_hsv(h=0.8)
def leds_shift_hue(self, val):
for i in range(40):
rgb = leds.get_rgb(i)
h, s, v = colours.rgb_to_hsv(*rgb)
h += val
leds.set_rgb(i, *colours.hsv_to_rgb(h, s, v))
leds.update()
def on_enter(self, vm): def on_enter(self, vm):
super().on_enter(vm) super().on_enter(vm)
......
...@@ -10,7 +10,7 @@ from st3m.goose import Optional, List, Dict ...@@ -10,7 +10,7 @@ from st3m.goose import Optional, List, Dict
from st3m.logging import Log from st3m.logging import Log
from st3m import settings from st3m import settings
from ctx import Context from ctx import Context
from st3m import led_patterns from st3m.ui import led_patterns
import leds import leds
import toml import toml
......
import leds
import json
def set_menu_colors():
"""
set all LEDs to the configured menu colors if provided in
/flash/menu_leds.json. leds.update() must be called externally.
"""
path = "/flash/menu_leds.json"
try:
with open(path, "r") as f:
settings = json.load(f)
except OSError:
leds.set_all_rgb(0, 0, 0)
return
for i in range(40):
col = settings["leds"][i]
leds.set_rgb(i, col[0], col[1], col[2])
def highlight_petal(num, r, g, b, num_leds=5):
"""
Sets the LED closest to the petal and num_leds-1 around it to
the color. If num_leds is uneven the appearance will be symmetric.
leds.update() must be called externally.
"""
num = num % 10
if num_leds < 0:
num_leds = 0
for i in range(num_leds):
leds.set_rgb((num * 4 + i - num_leds // 2) % 40, r, g, b)
...@@ -20,7 +20,7 @@ from st3m.application import ( ...@@ -20,7 +20,7 @@ from st3m.application import (
) )
from st3m.about import About from st3m.about import About
from st3m import settings_menu as settings, logging, processors, wifi from st3m import settings_menu as settings, logging, processors, wifi
from st3m import led_patterns from st3m.ui import led_patterns
import st3m.wifi import st3m.wifi
import captouch, audio, leds, gc, sys_buttons, sys_display, sys_mode, media import captouch, audio, leds, gc, sys_buttons, sys_display, sys_mode, media
......
...@@ -241,11 +241,16 @@ num_speaker_max_db = StringTunable( ...@@ -241,11 +241,16 @@ num_speaker_max_db = StringTunable(
) )
num_display_brightness = StringTunable( num_display_brightness = StringTunable(
"Display Brightness", "system.brightness.display", 100 "Display Brightness", "system.appearance.display_brightness", 100
)
num_leds_brightness = StringTunable(
"LED Brightness", "system.appearance.leds_brightness", 70
) )
num_leds_brightness = StringTunable("LED Brightness", "system.brightness.leds", 70)
num_leds_speed = StringTunable("LED speed", "system.brightness.leds_speed", 235) num_leds_speed = StringTunable("LED Speed", "system.appearance.leds_speed", 235)
onoff_leds_random_menu = OnOffTunable(
"Random Menu LEDs", "system.appearance.leds_random_menu", False
)
# List of all settings to be loaded/saved # List of all settings to be loaded/saved
load_save_settings: List[UnaryTunable] = [ load_save_settings: List[UnaryTunable] = [
...@@ -273,6 +278,7 @@ load_save_settings: List[UnaryTunable] = [ ...@@ -273,6 +278,7 @@ load_save_settings: List[UnaryTunable] = [
num_display_brightness, num_display_brightness,
num_leds_brightness, num_leds_brightness,
num_leds_speed, num_leds_speed,
onoff_leds_random_menu,
] ]
......
import leds
import json
import math
import random
from st3m.ui import colours
from st3m.settings import onoff_leds_random_menu
def _clip(val):
if val > 1.0:
return 1.0
if val < 0.0:
return 1.0
return val
def set_menu_colors():
"""
set all LEDs to the configured menu colors if provided in
/flash/menu_leds.json and settings.onoff_leds_random_menu
is false, else calls pretty_pattern.
leds.update() must be called externally.
"""
if onoff_leds_random_menu.value:
pretty_pattern()
return
path = "/flash/menu_leds.json"
try:
with open(path, "r") as f:
settings = json.load(f)
except OSError:
pretty_pattern()
return
for i in range(40):
col = settings["leds"][i]
leds.set_rgb(i, col[0], col[1], col[2])
def pretty_pattern():
"""
generates a pretty random pattern.
leds.update() must be called externally.
"""
hsv = [0.0, 0.0, 0.0]
hsv[0] = random.random() * math.tau
hsv[1] = random.random() * 0.3 + 0.7
hsv[2] = random.random() * 0.3 + 0.7
start = int(random.random() * 40)
for i in range(48):
hsv[0] += (random.random() - 0.5) * 2
for j in range(1, 3):
hsv[j] += (random.random() - 0.5) / 2
# asymmetric clipping: draw it to bright colors
if hsv[j] < 0.7:
hsv[j] = 0.7 + (0.7 - hsv[j]) / 2
if hsv[j] > 1:
hsv[j] = 1
g = (i + start) % 40
if i < 40:
leds.set_rgb(g, *colours.hsv_to_rgb(*hsv))
else:
hsv_old = colours.rgb_to_hsv(*leds.get_rgb(g))
hsv_mixed = [0.0, 0.0, 0.0]
k = (i - 39) / 8
if abs(hsv[0] - hsv_old[0]) < math.tau / 2:
hsv_mixed[0] = hsv_old[0] * k + hsv[0] * (1 - k)
elif hsv[0] > hsv_old[0]:
hsv_mixed[0] = (hsv_old[0] + math.tau) * k + hsv[0] * (1 - k)
else:
hsv_mixed[0] = hsv_old[0] * k + (hsv[0] + math.tau) * (1 - k)
for h in range(1, 3):
hsv_mixed[h] = hsv_old[h] * k + hsv[h] * (1 - k)
leds.set_rgb(j, *colours.hsv_to_rgb(*hsv_mixed))
def shift_all_hsv(h=0, s=0, v=0):
for i in range(40):
hue, sat, val = colours.rgb_to_hsv(*leds.get_rgb(i))
hue += h
sat = _clip(sat + s)
val = _clip(val + v)
leds.set_rgb(i, *colours.hsv_to_rgb(hue, sat, val))
def highlight_petal_rgb(num, r, g, b, num_leds=5):
"""
Sets the LED closest to the petal and num_leds-1 around it to
the color. If num_leds is uneven the appearance will be symmetric.
leds.update() must be called externally.
"""
num = num % 10
if num_leds < 0:
num_leds = 0
for i in range(num_leds):
leds.set_rgb((num * 4 + i - num_leds // 2) % 40, r, g, b)
...@@ -13,6 +13,10 @@ def set_rgb(ix, r, g, b): ...@@ -13,6 +13,10 @@ def set_rgb(ix, r, g, b):
_sim.set_led_rgb(ix, r, g, b) _sim.set_led_rgb(ix, r, g, b)
def get_rgb(ix):
return 0, 0, 0
def set_all_rgb(r, g, b): def set_all_rgb(r, g, b):
for i in range(40): for i in range(40):
set_rgb(i, r, g, b) set_rgb(i, r, g, b)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment