diff --git a/kmk/firmware.py b/kmk/firmware.py index db34eb0..ae0806e 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -80,6 +80,7 @@ class Firmware: hid_helper = USB_HID + # Split config extra_data_pin = None split_offsets = () split_flip = False @@ -90,9 +91,21 @@ class Firmware: uart = None uart_flip = True uart_pin = None + + # RGB config pixel_pin = None num_pixels = None rgb_order = (1, 0, 2) # GRB WS2812 + val_limit = 255 + hue_default = 0 + sat_default = 100 + val_default = val_limit + hue_step = 1 + sat_step = 1 + val_step = 1 + animation_speed = 1 + breathe_center = 1.5 # 1.0-2.7 + animation_mode = 'static' pixels = None def __init__(self): @@ -210,7 +223,11 @@ class Firmware: self.uart = self.init_uart(self.uart_pin) if self.pixel_pin is not None: - self.pixels = rgb.RGB(self.pixel_pin, self.rgb_order, self.num_pixels) + self.pixels = rgb.RGB(self.pixel_pin, self.rgb_order, self.num_pixels, + self.hue_step, self.sat_step, self.val_step, + self.hue_default, self.sat_default, self.val_default, + self.breathe_center, self.val_limit, self.animation_mode + ) self.matrix = MatrixScanner( @@ -268,6 +285,9 @@ class Firmware: if self.debug_enabled and state_changed: print('New State: {}'.format(self._state._to_dict())) + if self.debug_enabled and state_changed and self.pixels.enabled: + print('New State: {}'.format(self.pixels)) + if self.pixels.animation_mode is not None: self.pixels = self.pixels.animate() diff --git a/kmk/handlers/stock.py b/kmk/handlers/stock.py index 2e135c4..b24ec10 100644 --- a/kmk/handlers/stock.py +++ b/kmk/handlers/stock.py @@ -175,6 +175,11 @@ def rgb_mode_breathe(key, state, *args, **kwargs): return state +def rgb_mode_breathe_rainbow(key, state, *args, **kwargs): + state.config.pixels.animation_mode = 'breathing_rainbow' + return state + + def rgb_mode_rainbow(key, state, *args, **kwargs): state.config.pixels.animation_mode = 'rainbow' return state diff --git a/kmk/keys.py b/kmk/keys.py index 5ab8849..d74b0b4 100644 --- a/kmk/keys.py +++ b/kmk/keys.py @@ -638,6 +638,7 @@ make_key(names=('RGB_VAD',), on_press=handlers.rgb_vad) make_key(names=('RGB_MODE_PLAIN', 'RGB_M_P'), on_press=handlers.rgb_mode_static) make_key(names=('RGB_MODE_BREATHE', 'RGB_M_B'), on_press=handlers.rgb_mode_breathe) make_key(names=('RGB_MODE_RAINBOW', 'RGB_M_R'), on_press=handlers.rgb_mode_rainbow) +make_key(names=('RGB_MODE_BREATHE_RAINBOW', 'RGB_M_BR'), on_press=handlers.rgb_mode_breathe_rainbow) make_key( names=('LEADER', 'LEAD'), on_press=handlers.leader_pressed, diff --git a/kmk/rgb.py b/kmk/rgb.py index bc0a12a..7b942b4 100644 --- a/kmk/rgb.py +++ b/kmk/rgb.py @@ -4,25 +4,31 @@ import time class RGB: - hue = 240 + hue = 0 sat = 100 val = 80 - animation_mode = 'breathing' pos = 0 time = floor(time.monotonic() * 10) intervals = (30, 20, 10, 5) - speed = 120 # Bigger is slower + animation_speed = 1 enabled = True neopixel = None rgbw = False - num_pixels = 0 disable_auto_write = False - hue_step = 5 + + # Set by config + num_pixels = 0 + hue_step = 1 sat_step = 5 val_step = 5 - limit_val = 255 + breath_center = 1.5 # 1.0-2.7 + val_limit = 255 + animation_mode = 'static' - def __init__(self, pixel_pin, rgb_order, num_pixels=0): + def __init__(self, pixel_pin, rgb_order, num_pixels, + hue_step, sat_step, val_step, + hue_default, sat_default, val_default, + breath_center, val_limit, animation_mode): try: import neopixel self.neopixel = neopixel.NeoPixel(pixel_pin, @@ -32,6 +38,15 @@ class RGB: if len(rgb_order) == 4: self.rgbw = True self.num_pixels = num_pixels + self.hue_step = hue_step + self.sat_step = sat_step + self.val_step = val_step + self.hue = hue_default + self.sat = sat_default + self.val = val_default + self.breath_center = breath_center + self.val_limit = val_limit + self.animation_mode = animation_mode except ImportError as e: print(e) @@ -47,7 +62,7 @@ class RGB: 'animation_mode': self.animation_mode, 'time': self.time, 'intervals': self.intervals, - 'speed': self.speed, + 'animation_speed': self.animation_speed, 'enabled': self.enabled, 'neopixel': self.neopixel, 'disable_auto_write': self.disable_auto_write, @@ -69,10 +84,9 @@ class RGB: r = 0 g = 0 b = 0 - self.limit_val = 255 - if val > 255: - val = 255 + if val > self.val_limit: + val = self.val_limit if sat == 0: r = val @@ -80,8 +94,8 @@ class RGB: b = val else: - base = ((255 - sat) * val) >> 8 - color = (val - base) * (hue % 60) / 60 + base = ((100 - sat) * val) / 100 + color = floor((val - base) * ((hue % 60) / 60)) x = floor(hue / 60) if x == 0: @@ -183,7 +197,7 @@ class RGB: Decreases hue by step amount rolling at 0 and returning to 360 :param step: ''' - if self.hue - step < 0: + if (self.hue - step) <= 0: self.hue = (self.hue + 360 - step) % 360 else: self.hue = (self.hue - step) % 360 @@ -203,7 +217,7 @@ class RGB: Decreases saturation by step amount stopping at 0 :param step: ''' - if self.sat + step <= 0: + if (self.sat - step) <= 0: self.sat = 0 else: self.sat -= step @@ -213,7 +227,7 @@ class RGB: Increases value by step amount stopping at 100 :param step: ''' - if self.val + step >= 100: + if (self.val + step) >= 100: self.val = 100 else: self.val += step @@ -223,7 +237,7 @@ class RGB: Decreases value by step amount stopping at 0 :param step: ''' - if self.val + step <= 0: + if (self.val - step) <= 0: self.val = 0 else: self.val -= step @@ -253,7 +267,9 @@ class RGB: return self.effect_breathing() elif self.animation_mode == 'rainbow': return self.effect_rainbow() - if self.animation_mode == 'static': + elif self.animation_mode == 'breathing_rainbow': + return self.effect_breathing_rainbow() + elif self.animation_mode == 'static': return self.effect_static() else: self.off() @@ -275,34 +291,39 @@ class RGB: return self def effect_breathing(self): - RGBLIGHT_EFFECT_BREATHE_CENTER = 1.5 # 1.0-2.7 - RGBLIGHT_EFFECT_BREATHE_MAX = 100 # 0-255 # http://sean.voisen.org/blog/2011/10/breathing-led-with-arduino/ - # https://github.com/qmk/qmk_firmware/blob/9f1d781fcb7129a07e671a46461e501e3f1ae59d/quantum/rgblight.c#L787 - self.val = floor((exp(sin((self.pos/255.0)*pi)) - RGBLIGHT_EFFECT_BREATHE_CENTER/M_E)* - (RGBLIGHT_EFFECT_BREATHE_MAX/(M_E-1/M_E))) - self.pos = (self.pos + 1) % 256; + # https://github.com/qmk/qmk_firmware/blob/9f1d781fcb7129a07e671a46461e501e3f1ae59d/quantum/rgblight.c#L806 + self.val = floor((exp(sin((self.pos / 255.0) * pi)) - self.breath_center / M_E) * + (self.val_limit / (M_E - 1 / M_E))) + self.pos = (self.pos + self.animation_speed) % 256 self.set_hsv_fill(self.hue, self.sat, self.val) return self + def effect_breathing_rainbow(self): + if self.animation_step(): + self.increase_hue(self.animation_speed) + self.effect_breathing() + + return self + def effect_rainbow(self): - if self.animation_step(self): - self.increase_hue(self.hue, 1) + if self.animation_step(): + self.increase_hue(self.animation_speed) self.set_hsv_fill(self.hue, self.sat, self.val) return self def effect_rainbow_swirl(self): - interval = self.animation_step(self) + interval = self.animation_step() if interval: for i in range(0, self.num_pixels): self.hue = (360 / self.num_pixels * i + self.hue) % 360 self.set_hsv_fill(self.hue, self.sat, self.val) if interval % 2: - self.increase_hue(self.hue, 1) + self.increase_hue(self.animation_speed) else: - self.decrease_hue(self.hue, 1) + self.decrease_hue(self.animation_speed) return self diff --git a/user_keymaps/kdb424/nyquist_converter.py b/user_keymaps/kdb424/nyquist_converter.py index 8979510..b3f9915 100644 --- a/user_keymaps/kdb424/nyquist_converter.py +++ b/user_keymaps/kdb424/nyquist_converter.py @@ -29,6 +29,13 @@ keyboard.debug_enabled = True keyboard.pixel_pin = board.TX keyboard.num_pixels = 12 +keyboard.val_limit = 150 +keyboard.hue_step = 5 +keyboard.sat_step = 5 +keyboard.val_step = 5 +keyboard.hue_default = 260 +keyboard.animation_speed = 1 + OFF = (0, 0, 0) BLUE = (0, 0, 100) CYAN = (0, 100, 100) @@ -69,58 +76,74 @@ r3 = 4 def base(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'breathing' - keyboard.pixels.fill(OFF) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'breathing' + keyboard.pixels.neopixel(OFF) + keyboard.pixels.neopixelshow() + ''' return df_pressed(*args, **kwargs) def layer1p(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'User' - keyboard.pixels.fill(WHITE) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'User' + keyboard.pixels.neopixel.fill(WHITE) + keyboard.pixels.neopixel.show() + ''' return mo_pressed(*args, **kwargs) def layer1r(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'breathing' - keyboard.pixels.fill(OFF) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'breathing' + keyboard.pixels.neopixel.fill(OFF) + keyboard.pixels.neopixel.show() + ''' return mo_released(*args, **kwargs) def layer2p(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'User' - keyboard.pixels.fill(BLUE) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'User' + keyboard.pixels.neopixel.fill(BLUE) + keyboard.pixels.neopixel.show() + ''' return lt_pressed(*args, **kwargs) def layer2r(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'breathing' - keyboard.pixels.fill(OFF) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'breathing' + keyboard.pixels.neopixel.fill(OFF) + keyboard.pixels.neopixel.show() + ''' return lt_released(*args, **kwargs) def layer3p(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'User' - keyboard.pixels.fill(PURPLE) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'User' + keyboard.pixels.neopixel.fill(PURPLE) + keyboard.pixels.neopixel.show() + ''' return mo_pressed(*args, **kwargs) def layer3r(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'breathing' - keyboard.pixels.fill(OFF) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'breathing' + keyboard.pixels.neopixel.fill(OFF) + keyboard.pixels.neopixel.show() + ''' return mo_released(*args, **kwargs) def gaming(*args, **kwargs): - keyboard.pixel_state['animation_mode'] = 'User' - keyboard.pixels.fill(CYAN) - keyboard.pixels.show() + ''' + keyboard.pixels.animation_mode = 'User' + keyboard.pixels.neopixel.fill(CYAN) + keyboard.pixels.neopixel.show() + ''' return df_pressed(*args, **kwargs) @@ -205,11 +228,11 @@ keyboard.keymap = [ ], [ # r3 - [KC.GESC, KC.N1, KC.N2, KC.N3, KC.N4, KC.N5, KC.N6, KC.N7, KC.F10, KC.F11, KC.F12, KC.DEL], - [_______, _______, _______, _______, _______, _______, _______, _______, KC.F7, KC.F8, KC.F9, SHFT_INS], - [_______, _______, _______, _______, _______, _______, _______, _______, KC.F4, KC.F5, KC.F6, KC.VOLU], - [_______, _______, _______, _______, _______, _______, _______, _______, KC.F1, KC.F2, KC.F4, KC.VOLD], - [BASE, GAMING, _______, _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX], + [KC.GESC, KC.RGB_HUI, KC.RGB_HUD, KC.RGB_SAI, KC.RGB_SAD, KC.RGB_VAI, KC.RGB_VAD, _______, KC.F10, KC.F11, KC.F12, KC.DEL], + [KC.RGB_M_P, _______, _______, _______, _______, _______, _______, _______, KC.F7, KC.F8, KC.F9, SHFT_INS], + [KC.RGB_M_B, _______, _______, _______, _______, _______, _______, _______, KC.F4, KC.F5, KC.F6, KC.VOLU], + [KC.RGB_M_BR, _______, _______, _______, _______, _______, _______, _______, KC.F1, KC.F2, KC.F4, KC.VOLD], + [BASE, GAMING, _______, _______, _______, _______, _______, _______, _______, _______, _______, XXXXXXX], ], ]