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

leds: added get_steady()

parent ef4e2ab0
No related branches found
No related tags found
1 merge request!438leds: added get_steady()
Pipeline #8523 passed
...@@ -58,6 +58,11 @@ STATIC mp_obj_t mp_leds_get_slew_rate() { ...@@ -58,6 +58,11 @@ STATIC mp_obj_t mp_leds_get_slew_rate() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_slew_rate_obj, STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_slew_rate_obj,
mp_leds_get_slew_rate); mp_leds_get_slew_rate);
STATIC mp_obj_t mp_leds_get_steady() {
return mp_obj_new_bool(st3m_leds_get_steady());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_steady_obj, mp_leds_get_steady);
STATIC mp_obj_t mp_led_set_rgb(size_t n_args, const mp_obj_t *args) { STATIC mp_obj_t mp_led_set_rgb(size_t n_args, const mp_obj_t *args) {
uint8_t index = mp_obj_get_int(args[0]); uint8_t index = mp_obj_get_int(args[0]);
float red = mp_obj_get_float(args[1]); float red = mp_obj_get_float(args[1]);
...@@ -165,6 +170,7 @@ STATIC const mp_rom_map_elem_t mp_module_leds_globals_table[] = { ...@@ -165,6 +170,7 @@ STATIC const mp_rom_map_elem_t mp_module_leds_globals_table[] = {
MP_ROM_PTR(&mp_leds_get_slew_rate_obj) }, MP_ROM_PTR(&mp_leds_get_slew_rate_obj) },
{ MP_ROM_QSTR(MP_QSTR_set_slew_rate), { MP_ROM_QSTR(MP_QSTR_set_slew_rate),
MP_ROM_PTR(&mp_leds_set_slew_rate_obj) }, MP_ROM_PTR(&mp_leds_set_slew_rate_obj) },
{ MP_ROM_QSTR(MP_QSTR_get_steady), MP_ROM_PTR(&mp_leds_get_steady_obj) },
}; };
STATIC MP_DEFINE_CONST_DICT(mp_module_leds_globals, STATIC MP_DEFINE_CONST_DICT(mp_module_leds_globals,
......
...@@ -38,6 +38,7 @@ typedef struct { ...@@ -38,6 +38,7 @@ typedef struct {
uint8_t brightness; uint8_t brightness;
uint8_t slew_rate; uint8_t slew_rate;
bool auto_update; bool auto_update;
bool is_steady;
uint8_t timer; uint8_t timer;
st3m_leds_gamma_table_t gamma_red; st3m_leds_gamma_table_t gamma_red;
...@@ -67,7 +68,7 @@ static void set_single_led(uint8_t index, st3m_u8_rgb_t c) { ...@@ -67,7 +68,7 @@ static void set_single_led(uint8_t index, st3m_u8_rgb_t c) {
static uint16_t led_get_slew(uint16_t old, uint16_t new, uint16_t slew) { static uint16_t led_get_slew(uint16_t old, uint16_t new, uint16_t slew) {
new = new << 8; new = new << 8;
if (slew == 255) return new; if (slew == 255 || (old == new)) return new;
int16_t bonus = ((int16_t)slew) - 225; int16_t bonus = ((int16_t)slew) - 225;
slew = 30 + (slew << 2) + ((slew * slew) >> 3); slew = 30 + (slew << 2) + ((slew * slew) >> 3);
if (bonus > 0) { if (bonus > 0) {
...@@ -105,13 +106,17 @@ void st3m_leds_update_hardware() { ...@@ -105,13 +106,17 @@ void st3m_leds_update_hardware() {
if (state.auto_update) leds_update_target(); if (state.auto_update) leds_update_target();
bool is_different = false; bool is_different = false;
bool is_steady = true;
for (int i = 0; i < 40; i++) { for (int i = 0; i < 40; i++) {
st3m_u8_rgb_t ret = state.target[i]; st3m_u8_rgb_t ret = state.target[i];
st3m_u16_rgb_t c; st3m_u16_rgb_t c;
c.r = led_get_slew(state.slew_output[i].r, ret.r, state.slew_rate); st3m_u16_rgb_t prev = state.slew_output[i];
c.g = led_get_slew(state.slew_output[i].g, ret.g, state.slew_rate); c.r = led_get_slew(prev.r, ret.r, state.slew_rate);
c.b = led_get_slew(state.slew_output[i].b, ret.b, state.slew_rate); c.g = led_get_slew(prev.g, ret.g, state.slew_rate);
c.b = led_get_slew(prev.b, ret.b, state.slew_rate);
if ((prev.r != c.r) || (prev.g != c.g) || (prev.b != c.b))
is_steady = false;
state.slew_output[i] = c; state.slew_output[i] = c;
c.r = ((uint32_t)c.r * state.brightness) >> 8; c.r = ((uint32_t)c.r * state.brightness) >> 8;
...@@ -129,6 +134,7 @@ void st3m_leds_update_hardware() { ...@@ -129,6 +134,7 @@ void st3m_leds_update_hardware() {
is_different = true; is_different = true;
} }
} }
state.is_steady = is_steady;
UNLOCK; UNLOCK;
if (is_different || (state.timer > 10)) { if (is_different || (state.timer > 10)) {
...@@ -164,6 +170,7 @@ void st3m_leds_set_single_rgb(uint8_t index, float red, float green, ...@@ -164,6 +170,7 @@ void st3m_leds_set_single_rgb(uint8_t index, float red, float green,
state.target_buffer[index].r = (uint8_t)(red * 255); state.target_buffer[index].r = (uint8_t)(red * 255);
state.target_buffer[index].g = (uint8_t)(green * 255); state.target_buffer[index].g = (uint8_t)(green * 255);
state.target_buffer[index].b = (uint8_t)(blue * 255); state.target_buffer[index].b = (uint8_t)(blue * 255);
state.is_steady = false;
UNLOCK_INCOMING; UNLOCK_INCOMING;
} }
...@@ -277,6 +284,13 @@ uint8_t st3m_leds_get_slew_rate() { ...@@ -277,6 +284,13 @@ uint8_t st3m_leds_get_slew_rate() {
return res; return res;
} }
bool st3m_leds_get_steady() {
LOCK;
uint8_t res = state.is_steady;
UNLOCK;
return res;
}
void st3m_leds_set_auto_update(bool on) { void st3m_leds_set_auto_update(bool on) {
LOCK; LOCK;
state.auto_update = on; state.auto_update = on;
......
...@@ -44,9 +44,7 @@ uint8_t st3m_leds_get_brightness(); ...@@ -44,9 +44,7 @@ uint8_t st3m_leds_get_brightness();
// to 255 to disable. Currently clocks at 50Hz. // to 255 to disable. Currently clocks at 50Hz.
void st3m_leds_set_slew_rate(uint8_t slew_rate); void st3m_leds_set_slew_rate(uint8_t slew_rate);
uint8_t st3m_leds_get_slew_rate(); uint8_t st3m_leds_get_slew_rate();
bool st3m_leds_get_steady();
void st3m_leds_set_max_slew_rate(uint8_t slew_rate);
uint8_t st3m_leds_get_max_slew_rate();
// Update LEDs. Ie., copy the LED state from the first buffer into the second // Update LEDs. Ie., copy the LED state from the first buffer into the second
// buffer, effectively scheduling the LED state to be presented to the user. // buffer, effectively scheduling the LED state to be presented to the user.
......
...@@ -30,7 +30,6 @@ class App(Application): ...@@ -30,7 +30,6 @@ class App(Application):
self.mid_x = 42 self.mid_x = 42
self.led_accumulator_ms = 0 self.led_accumulator_ms = 0
self.blueish = False self.blueish = False
self.half_time = 600
def draw_widget(self, label): def draw_widget(self, label):
ctx = self.ctx ctx = self.ctx
...@@ -213,10 +212,6 @@ class App(Application): ...@@ -213,10 +212,6 @@ class App(Application):
tmp = 0 tmp = 0
elif tmp > 255: elif tmp > 255:
tmp = 255 tmp = 255
if tmp < 120:
self.half_time = 600 + (120 - tmp) * (120 - tmp) / 2
else:
self.half_time = 600
if tmp != settings.num_leds_speed.value: if tmp != settings.num_leds_speed.value:
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)
...@@ -237,8 +232,7 @@ class App(Application): ...@@ -237,8 +232,7 @@ class App(Application):
def think(self, ins, delta_ms): def think(self, ins, delta_ms):
super().think(ins, delta_ms) super().think(ins, delta_ms)
self.delta_ms += delta_ms self.delta_ms += delta_ms
if self.focused_widget == 2:
self.led_accumulator_ms += delta_ms
if ( if (
self.input.buttons.app.right.pressed self.input.buttons.app.right.pressed
or self.input.buttons.app.right.repeated or self.input.buttons.app.right.repeated
...@@ -249,9 +243,13 @@ class App(Application): ...@@ -249,9 +243,13 @@ class App(Application):
if self.input.buttons.app.middle.pressed: if self.input.buttons.app.middle.pressed:
self.select_pressed = True self.select_pressed = True
while self.led_accumulator_ms > self.half_time: if self.focused_widget == 3 and leds.get_steady():
self.led_accumulator_ms = self.led_accumulator_ms % self.half_time self.led_accumulator_ms += delta_ms
if self.led_accumulator_ms > 1000:
self.led_accumulator_ms = 0
led_patterns.shift_all_hsv(h=0.8) led_patterns.shift_all_hsv(h=0.8)
leds.update()
def on_enter(self, vm): def on_enter(self, vm):
super().on_enter(vm) super().on_enter(vm)
......
...@@ -3,6 +3,7 @@ from st3m.goose import Dict, Any, List, Optional ...@@ -3,6 +3,7 @@ from st3m.goose import Dict, Any, List, Optional
from st3m.ui.view import View, ViewManager from st3m.ui.view import View, ViewManager
from st3m.input import InputState from st3m.input import InputState
from ctx import Context from ctx import Context
from st3m.ui import colours, led_patterns
import json import json
import errno import errno
...@@ -45,6 +46,8 @@ class ShoegazeApp(Application): ...@@ -45,6 +46,8 @@ class ShoegazeApp(Application):
self._rand_rot = 0.0 self._rand_rot = 0.0
self.delay_on = True self.delay_on = True
self.organ_on = False self.organ_on = False
self.hue_change = False
self.hue = 0
self._set_chord(3, force_update=True) self._set_chord(3, force_update=True)
def _build_synth(self) -> None: def _build_synth(self) -> None:
...@@ -146,11 +149,10 @@ class ShoegazeApp(Application): ...@@ -146,11 +149,10 @@ class ShoegazeApp(Application):
self._update_connections() self._update_connections()
def _set_chord(self, i: int, force_update=False) -> None: def _set_chord(self, i: int, force_update=False) -> None:
hue = int(54 * (i + 0.5)) % 360
if i != self.chord_index or force_update: if i != self.chord_index or force_update:
self.hue = (54 * (i + 0.5)) * math.tau / 360
self.chord_index = i self.chord_index = i
leds.set_all_hsv(hue, 1, 0.7) self.hue_change = True
leds.update()
if self.organ_on and self._organ_chords[i] is not None: if self.organ_on and self._organ_chords[i] is not None:
self.chord = self._organ_chords[i] self.chord = self._organ_chords[i]
else: else:
...@@ -255,10 +257,22 @@ class ShoegazeApp(Application): ...@@ -255,10 +257,22 @@ class ShoegazeApp(Application):
self.bass_string.decay = 1000 self.bass_string.decay = 1000
self.bass_string.signals.trigger.start() self.bass_string.signals.trigger.start()
if self.hue_change:
leds.set_slew_rate(min(self.max_slew_rate, 200))
leds.set_all_rgb(*colours.hsv_to_rgb(self.hue, 1, 0.7))
leds.update()
self.hue_change = False
elif leds.get_steady():
leds.set_slew_rate(min(self.max_slew_rate, 50))
led_patterns.pretty_pattern()
leds.set_all_rgba(*colours.hsv_to_rgb(self.hue, 1, 0.7), 0.75)
leds.update()
def on_enter(self, vm: Optional[ViewManager]) -> None: def on_enter(self, vm: Optional[ViewManager]) -> None:
if self.blm is None: if self.blm is None:
self._build_synth() self._build_synth()
self.blm.foreground = True self.blm.foreground = True
self.max_slew_rate = leds.get_slew_rate()
self._set_chord(self.chord_index, force_update=True) self._set_chord(self.chord_index, force_update=True)
def on_exit(self) -> None: def on_exit(self) -> None:
......
...@@ -22,6 +22,16 @@ def get_slew_rate() -> int: ...@@ -22,6 +22,16 @@ def get_slew_rate() -> int:
Get maximum change rate of brightness. See set_slew_rate() Get maximum change rate of brightness. See set_slew_rate()
""" """
def get_steady() -> bool:
"""
Returns true if the LED engine is certain that there is no further color change
until user input occurs, meaning that the last animation has finished and there
is no unprocessed data is queued up. The LED task consumes data at 50Hz.
If you use this function to time next animation frames be sure to set a maximum
rate so that users with a high slew rate setting will not get strobelighted!
"""
def set_rgb(i: int, r: float, g: float, b: float) -> None: def set_rgb(i: int, r: float, g: float, b: float) -> None:
"""Set LED i to rgb value r, g, b """Set LED i to rgb value r, g, b
......
...@@ -15,6 +15,19 @@ def _clip(val): ...@@ -15,6 +15,19 @@ def _clip(val):
return val return val
def _hue_blend(h1, h2, n):
"""
mixes two hues together while accounting for overflow.
n in range [0..1] blends between [h1..h2]
"""
if abs(h2 - h1) < (math.tau / 2):
return h2 * n + h1 * (1 - n)
elif h2 > h1:
return h2 * n + (h1 + math.tau) * (1 - n)
else:
return (h2 + math.tau) * n + h1 * (1 - n)
def set_menu_colors(): def set_menu_colors():
""" """
set all LEDs to the configured menu colors if provided in set all LEDs to the configured menu colors if provided in
...@@ -65,12 +78,7 @@ def pretty_pattern(): ...@@ -65,12 +78,7 @@ def pretty_pattern():
hsv_old = colours.rgb_to_hsv(*leds.get_rgb(g)) hsv_old = colours.rgb_to_hsv(*leds.get_rgb(g))
hsv_mixed = [0.0, 0.0, 0.0] hsv_mixed = [0.0, 0.0, 0.0]
k = (i - 39) / 8 k = (i - 39) / 8
if abs(hsv[0] - hsv_old[0]) < math.tau / 2: hsv_mixed[0] = _hue_blend(hsv[0], hsv_old[0], k)
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): for h in range(1, 3):
hsv_mixed[h] = hsv_old[h] * k + hsv[h] * (1 - k) hsv_mixed[h] = hsv_old[h] * k + hsv[h] * (1 - k)
......
...@@ -17,6 +17,10 @@ def get_rgb(ix): ...@@ -17,6 +17,10 @@ def get_rgb(ix):
return 0, 0, 0 return 0, 0, 0
def get_steady():
return False
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