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() {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_leds_get_slew_rate_obj,
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) {
uint8_t index = mp_obj_get_int(args[0]);
float red = mp_obj_get_float(args[1]);
......@@ -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_QSTR(MP_QSTR_set_slew_rate),
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,
......
......@@ -38,6 +38,7 @@ typedef struct {
uint8_t brightness;
uint8_t slew_rate;
bool auto_update;
bool is_steady;
uint8_t timer;
st3m_leds_gamma_table_t gamma_red;
......@@ -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) {
new = new << 8;
if (slew == 255) return new;
if (slew == 255 || (old == new)) return new;
int16_t bonus = ((int16_t)slew) - 225;
slew = 30 + (slew << 2) + ((slew * slew) >> 3);
if (bonus > 0) {
......@@ -105,13 +106,17 @@ void st3m_leds_update_hardware() {
if (state.auto_update) leds_update_target();
bool is_different = false;
bool is_steady = true;
for (int i = 0; i < 40; i++) {
st3m_u8_rgb_t ret = state.target[i];
st3m_u16_rgb_t c;
c.r = led_get_slew(state.slew_output[i].r, ret.r, state.slew_rate);
c.g = led_get_slew(state.slew_output[i].g, ret.g, state.slew_rate);
c.b = led_get_slew(state.slew_output[i].b, ret.b, state.slew_rate);
st3m_u16_rgb_t prev = state.slew_output[i];
c.r = led_get_slew(prev.r, ret.r, 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;
c.r = ((uint32_t)c.r * state.brightness) >> 8;
......@@ -129,6 +134,7 @@ void st3m_leds_update_hardware() {
is_different = true;
}
}
state.is_steady = is_steady;
UNLOCK;
if (is_different || (state.timer > 10)) {
......@@ -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].g = (uint8_t)(green * 255);
state.target_buffer[index].b = (uint8_t)(blue * 255);
state.is_steady = false;
UNLOCK_INCOMING;
}
......@@ -277,6 +284,13 @@ uint8_t st3m_leds_get_slew_rate() {
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) {
LOCK;
state.auto_update = on;
......
......@@ -44,9 +44,7 @@ uint8_t st3m_leds_get_brightness();
// to 255 to disable. Currently clocks at 50Hz.
void st3m_leds_set_slew_rate(uint8_t slew_rate);
uint8_t st3m_leds_get_slew_rate();
void st3m_leds_set_max_slew_rate(uint8_t slew_rate);
uint8_t st3m_leds_get_max_slew_rate();
bool st3m_leds_get_steady();
// 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.
......
......@@ -30,7 +30,6 @@ class App(Application):
self.mid_x = 42
self.led_accumulator_ms = 0
self.blueish = False
self.half_time = 600
def draw_widget(self, label):
ctx = self.ctx
......@@ -213,10 +212,6 @@ class App(Application):
tmp = 0
elif 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:
settings.num_leds_speed.set_value(tmp)
leds.set_slew_rate(settings.num_leds_speed.value)
......@@ -237,8 +232,7 @@ class App(Application):
def think(self, ins, delta_ms):
super().think(ins, delta_ms)
self.delta_ms += delta_ms
if self.focused_widget == 2:
self.led_accumulator_ms += delta_ms
if (
self.input.buttons.app.right.pressed
or self.input.buttons.app.right.repeated
......@@ -249,9 +243,13 @@ class App(Application):
if self.input.buttons.app.middle.pressed:
self.select_pressed = True
while self.led_accumulator_ms > self.half_time:
self.led_accumulator_ms = self.led_accumulator_ms % self.half_time
if self.focused_widget == 3 and leds.get_steady():
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)
leds.update()
def on_enter(self, vm):
super().on_enter(vm)
......
......@@ -3,6 +3,7 @@ from st3m.goose import Dict, Any, List, Optional
from st3m.ui.view import View, ViewManager
from st3m.input import InputState
from ctx import Context
from st3m.ui import colours, led_patterns
import json
import errno
......@@ -45,6 +46,8 @@ class ShoegazeApp(Application):
self._rand_rot = 0.0
self.delay_on = True
self.organ_on = False
self.hue_change = False
self.hue = 0
self._set_chord(3, force_update=True)
def _build_synth(self) -> None:
......@@ -146,11 +149,10 @@ class ShoegazeApp(Application):
self._update_connections()
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:
self.hue = (54 * (i + 0.5)) * math.tau / 360
self.chord_index = i
leds.set_all_hsv(hue, 1, 0.7)
leds.update()
self.hue_change = True
if self.organ_on and self._organ_chords[i] is not None:
self.chord = self._organ_chords[i]
else:
......@@ -255,10 +257,22 @@ class ShoegazeApp(Application):
self.bass_string.decay = 1000
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:
if self.blm is None:
self._build_synth()
self.blm.foreground = True
self.max_slew_rate = leds.get_slew_rate()
self._set_chord(self.chord_index, force_update=True)
def on_exit(self) -> None:
......
......@@ -22,6 +22,16 @@ def get_slew_rate() -> int:
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:
"""Set LED i to rgb value r, g, b
......
......@@ -15,6 +15,19 @@ def _clip(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():
"""
set all LEDs to the configured menu colors if provided in
......@@ -65,12 +78,7 @@ def pretty_pattern():
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)
hsv_mixed[0] = _hue_blend(hsv[0], hsv_old[0], k)
for h in range(1, 3):
hsv_mixed[h] = hsv_old[h] * k + hsv[h] * (1 - k)
......
......@@ -17,6 +17,10 @@ def get_rgb(ix):
return 0, 0, 0
def get_steady():
return False
def set_all_rgb(r, g, b):
for i in range(40):
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