From ea19f5bb30330e915527a20c662930fbff0f83a5 Mon Sep 17 00:00:00 2001 From: xs5871 Date: Thu, 24 Mar 2022 21:23:53 +0000 Subject: [PATCH] convert hsv_to_rgb to faster 16bit fixed point --- kmk/extensions/rgb.py | 165 ++++++++++++++++++++---------------------- 1 file changed, 80 insertions(+), 85 deletions(-) diff --git a/kmk/extensions/rgb.py b/kmk/extensions/rgb.py index 41acad0..33cde31 100644 --- a/kmk/extensions/rgb.py +++ b/kmk/extensions/rgb.py @@ -8,10 +8,68 @@ from kmk.keys import make_key from kmk.kmktime import PeriodicTimer from kmk.utils import clamp - rgb_config = {} +def hsv_to_rgb(hue, sat, val): + ''' + Converts HSV values, and returns a tuple of RGB values + :param hue: + :param sat: + :param val: + :return: (r, g, b) + ''' + if sat == 0: + return (val, val, val) + + hue = 6 * (hue & 0xFF) + frac = hue & 0xFF + sxt = hue >> 8 + + base = (0xFF - sat) * val + color = (val * sat * frac) >> 8 + val <<= 8 + + if sxt == 0: + r = val + g = base + color + b = base + elif sxt == 1: + r = val - color + g = val + b = base + elif sxt == 2: + r = base + g = val + b = base + color + elif sxt == 3: + r = base + g = val - color + b = val + elif sxt == 4: + r = base + color + g = base + b = val + elif sxt == 5: + r = val + g = base + b = val - color + + return (r >> 8), (g >> 8), (b >> 8) + + +def hsv_to_rgbw(self, hue, sat, val): + ''' + Converts HSV values, and returns a tuple of RGBW values + :param hue: + :param sat: + :param val: + :return: (r, g, b, w) + ''' + rgb = hsv_to_rgb(hue, sat, val) + return rgb[0], rgb[1], rgb[2], min(rgb) + + class AnimationModes: OFF = 0 STATIC = 1 @@ -31,14 +89,14 @@ class RGB(Extension): self, pixel_pin, num_pixels=0, - val_limit=100, + val_limit=255, hue_default=0, - sat_default=100, + sat_default=255, rgb_order=(1, 0, 2), # GRB WS2812 - val_default=100, - hue_step=5, - sat_step=5, - val_step=5, + val_default=255, + hue_step=4, + sat_step=13, + val_step=13, animation_speed=1, breathe_center=1, # 1.0-2.7 knight_effect_length=3, @@ -175,69 +233,6 @@ class RGB(Extension): def on_powersave_disable(self, sandbox): self._do_update() - def hsv_to_rgb(self, hue, sat, val): - ''' - Converts HSV values, and returns a tuple of RGB values - :param hue: - :param sat: - :param val: - :return: (r, g, b) - ''' - r = 0 - g = 0 - b = 0 - - if val > self.val_limit: - val = self.val_limit - - if sat == 0: - r = val - g = val - b = val - - else: - base = ((100 - sat) * val) / 100 - color = (val - base) * ((hue % 60) / 60) - - x = int(hue / 60) - if x == 0: - r = val - g = base + color - b = base - elif x == 1: - r = val - color - g = val - b = base - elif x == 2: - r = base - g = val - b = base + color - elif x == 3: - r = base - g = val - color - b = val - elif x == 4: - r = base + color - g = base - b = val - elif x == 5: - r = val - g = base - b = val - color - - return int(r), int(g), int(b) - - def hsv_to_rgbw(self, hue, sat, val): - ''' - Converts HSV values, and returns a tuple of RGBW values - :param hue: - :param sat: - :param val: - :return: (r, g, b, w) - ''' - rgb = self.hsv_to_rgb(hue, sat, val) - return rgb[0], rgb[1], rgb[2], min(rgb) - def set_hsv(self, hue, sat, val, index): ''' Takes HSV values and displays it on a single LED/Neopixel @@ -248,9 +243,9 @@ class RGB(Extension): ''' if self.pixels: if self.rgbw: - self.set_rgb(self.hsv_to_rgbw(hue, sat, val), index) + self.set_rgb(hsv_to_rgbw(hue, sat, val), index) else: - self.set_rgb(self.hsv_to_rgb(hue, sat, val), index) + self.set_rgb(hsv_to_rgb(hue, sat, val), index) def set_hsv_fill(self, hue, sat, val): ''' @@ -261,9 +256,9 @@ class RGB(Extension): ''' if self.pixels: if self.rgbw: - self.set_rgb_fill(self.hsv_to_rgbw(hue, sat, val)) + self.set_rgb_fill(hsv_to_rgbw(hue, sat, val)) else: - self.set_rgb_fill(self.hsv_to_rgb(hue, sat, val)) + self.set_rgb_fill(hsv_to_rgb(hue, sat, val)) def set_rgb(self, rgb, index): ''' @@ -288,42 +283,42 @@ class RGB(Extension): def increase_hue(self, step=None): ''' - Increases hue by step amount rolling at 360 and returning to 0 + Increases hue by step amount rolling at 256 and returning to 0 :param step: ''' if step is None: step = self.hue_step - self.hue = (self.hue + step) % 360 + self.hue = (self.hue + step) % 256 if self._check_update(): self._do_update() def decrease_hue(self, step=None): ''' - Decreases hue by step amount rolling at 0 and returning to 360 + Decreases hue by step amount rolling at 0 and returning to 256 :param step: ''' if step is None: step = self.hue_step if (self.hue - step) <= 0: - self.hue = (self.hue + 360 - step) % 360 + self.hue = (self.hue + 256 - step) % 256 else: - self.hue = (self.hue - step) % 360 + self.hue = (self.hue - step) % 256 if self._check_update(): self._do_update() def increase_sat(self, step=None): ''' - Increases saturation by step amount stopping at 100 + Increases saturation by step amount stopping at 255 :param step: ''' if step is None: step = self.sat_step - self.sat = clamp(self.sat + step, 0, 100) + self.sat = clamp(self.sat + step, 0, 255) if self._check_update(): self._do_update() @@ -336,7 +331,7 @@ class RGB(Extension): if step is None: step = self.sat_step - self.sat = clamp(self.sat - step, 0, 100) + self.sat = clamp(self.sat - step, 0, 255) if self._check_update(): self._do_update() @@ -349,7 +344,7 @@ class RGB(Extension): if step is None: step = self.val_step - self.val = clamp(self.val + step, 0, 100) + self.val = clamp(self.val + step, 0, 255) if self._check_update(): self._do_update() @@ -362,7 +357,7 @@ class RGB(Extension): if step is None: step = self.val_step - self.val = clamp(self.val - step, 0, 100) + self.val = clamp(self.val - step, 0, 255) if self._check_update(): self._do_update() @@ -478,7 +473,7 @@ class RGB(Extension): self.disable_auto_write = True # Turn off instantly showing for i in range(0, self.num_pixels): self.set_hsv( - (self.hue - (i * self.num_pixels)) % 360, self.sat, self.val, i + (self.hue - (i * self.num_pixels)) % 256, self.sat, self.val, i ) # Show final results