From 0ba5911f8f6bbbf0ef4d4b71a66e19c4cb381e3b Mon Sep 17 00:00:00 2001 From: Kyle Brown Date: Tue, 19 Feb 2019 18:07:22 -0800 Subject: [PATCH] More animations, now based on time and intervals. Massively WIP --- kmk/firmware.py | 17 ++------ kmk/rgb.py | 100 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 80 insertions(+), 37 deletions(-) diff --git a/kmk/firmware.py b/kmk/firmware.py index 8bcdb82..991c42f 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -93,7 +93,7 @@ class Firmware: pixel_pin = None num_pixels = None pixels = None - pixel_state = 0, 0 + pixel_state = rgb.pixelinit() def __init__(self): # Attempt to sanely guess a coord_mapping if one is not provided @@ -239,7 +239,6 @@ class Firmware: if self.debug_enabled: print("Firin' lazers. Keyboard is booted.") - while True: state_changed = False @@ -275,15 +274,7 @@ class Firmware: if self.debug_enabled and state_changed: print('New State: {}'.format(self._state._to_dict())) - gc.collect() - ''' - test = rgb.color_chase(self.pixels, - self.num_pixels, - color=(255,0,0), - color2=(0,255,255), - animation_state=self.pixel_state[0]) + if self.pixel_state['animation_mode'] is not None: + self.pixel_state = rgb.animate(self.pixel_state, self.pixels) - if test is not None: - # Debugging some strange errors with NoneType - self.pixel_state = test - ''' + gc.collect() diff --git a/kmk/rgb.py b/kmk/rgb.py index 3b719b8..29a5095 100644 --- a/kmk/rgb.py +++ b/kmk/rgb.py @@ -1,3 +1,6 @@ +from math import sin, exp, pi +import time + COLORS = { 'OFF': (0, 0, 0), 'RED': (255, 0, 0), @@ -16,29 +19,19 @@ def pixelinit(): 's': 255, 'v': 255, 'animation_mode': None, - 'speed': 0, + 'pos': 0, + 'timer': None, + 'intervals': (0, 0, 0, 0), + 'speed': 120, # Bigger is slower 'enable': True } -def color_chase(pixels, num_pixels, color, color2=COLORS['OFF'], speed=100, animation_state=0): - if animation_state not in range(num_pixels): - color = color2 - pixels[int(animation_state - num_pixels)] = color - - else: - pixels[animation_state] = color - - pixels.show() - animation_state += 1 - - if animation_state >= num_pixels * 2: - animation_state = 0 - - return animation_state, 0 +def time_ms(): + return time.monotonic_ns() / 10 -def sethsv(hue, sat, val, pixels, index): +def hsv_to_rgb(hue, sat, val): r = 0 g = 0 b = 0 @@ -46,7 +39,7 @@ def sethsv(hue, sat, val, pixels, index): RGBLIGHT_LIMIT_VAL = 255 if val > RGBLIGHT_LIMIT_VAL: - val=RGBLIGHT_LIMIT_VAL + val=RGBLIGHT_LIMIT_VAL if sat == 0: r = val @@ -83,25 +76,84 @@ def sethsv(hue, sat, val, pixels, index): g = base b = val - color - rgb = (r, g, b) - setrgb(rgb, pixels, index) + return r, g, b -def setrgb(rgb, pixels, index): +def set_hsv(hue, sat, val, pixels, index): + set_rgb(hsv_to_rgb(hue, sat, val), pixels, index) + + +def set_hsv_fill(hue, sat, val, pixels): + pixels.fill(hsv_to_rgb(hue, sat, val)) + pixels.show() + + +def set_rgb(rgb, pixels, index): pixels[index] = (rgb[0], rgb[1], rgb[2]) + pixels.show() -def setrgbfill(rgb, pixels): +def set_rgb_fill(rgb, pixels): pixels.fill(rgb[0], rgb[1], rgb[2]) + pixels.show() -def increasehue(hue, step): +def increase_hue(hue, step): return hue + step % 360 -def decreasehue(hue, step): +def decrease_hue(hue, step): if hue - step < 0: return (hue + 360 - step) % 360 else: return hue - step % 360 + +def animate(state, pixels): + if state['animation_mode'] == 'breathing': + return effect_breathing(state, pixels) + elif state['animation_mode'] == 'rainbow': + return effect_rainbow(state, pixels) + + return state + + +def animation_step(state): + interval = state['time'] - time_ms() + if interval in state['intervals']: + return interval + else: + return False + + +def effect_breathing(state, pixels): + if animation_step(state): + # http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ + state['v'] = (exp(sin(state['step'] / 2000.0 * pi)) - 0.36787944) * 108.0 + set_hsv_fill(state['h'], state['s'], state['v'], pixels) + + return state + + +def effect_rainbow(state, pixels): + if animation_step(state): + state['h'] = increase_hue(state['h'], 1) + set_hsv_fill(state['h'], state['s'], state['v'], pixels) + + return state + + +def effect_rainbow_swirl(state, pixels): + interval = animation_step(state) + if interval: + MAX_RGB_NUM = 12 # TODO Actually pass this + for i in range(0, MAX_RGB_NUM): + state['h'] = (360 / MAX_RGB_NUM * i + state['h']) % 360 + set_hsv_fill(state['h'], state['s'], state['v'], pixels) + + if interval % 2: + state['h'] = increase_hue(state['h'], 1) + else: + state['h'] = decrease_hue(state['h'], 1) + + return state