/ adafruit_fancyled / fastled_helpers.py
fastled_helpers.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2017 PaintYourDragon for Adafruit Industries 4 # 5 # Permission is hereby granted, free of charge, to any person obtaining a copy 6 # of this software and associated documentation files (the "Software"), to deal 7 # in the Software without restriction, including without limitation the rights 8 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 # copies of the Software, and to permit persons to whom the Software is 10 # furnished to do so, subject to the following conditions: 11 # 12 # The above copyright notice and this permission notice shall be included in 13 # all copies or substantial portions of the Software. 14 # 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 # THE SOFTWARE. 22 """ 23 `adafruit_fancyled.fastled_helpers` 24 ==================================================== 25 26 CircuitPython "helper" library based on the Arduino FastLED library. 27 Uses similar function names to assist with porting of existing Arduino FastLED 28 projects to CircuitPython. 29 30 * Author(s): PaintYourDragon 31 """ 32 33 # imports 34 35 __version__ = "0.0.0-auto.0" 36 __repo__ = "https://github.com/Adafruit/Adafruit_CircuitPython_FancyLED.git" 37 38 from math import floor 39 from adafruit_fancyled import adafruit_fancyled as fancy 40 41 # These are helper functions that provide more FastLED-like calls for 42 # fancyled functions. 43 # Function names are kept the same as FastLED, which normally upsets pylint. 44 # Disable name-checking so this passes muster. 45 # pylint: disable=invalid-name 46 47 GFACTOR = 2.5 # Default gamma-correction factor for function below 48 49 50 def applyGamma_video(n, g_r=GFACTOR, g_g=None, g_b=None, inplace=False): 51 """ Approximates various invocations of FastLED's many-ways-overloaded 52 applyGamma_video() function. 53 54 ACCEPTS: One of three ways: 55 1. A single brightness level (0-255) and optional gamma-correction 56 factor (float usu. > 1.0, default if unspecified is 2.5). 57 2. A single CRGB, CHSV or packed integer type and optional gamma 58 factor or separate R, G, B gamma values. 59 3. A list of CRGB, CHSV or packed integer types (and optional gamma(s)). 60 61 In the tuple/list cases, the 'inplace' flag determines whether 62 a new tuple/list is calculated and returned, or the existing 63 value is modified in-place. By default this is 'False'. 64 Can also use the napplyGamma_video() function to more directly 65 approximate FastLED syntax/behavior. 66 67 RETURNS: Corresponding to above cases: 68 1. Single gamma-corrected brightness level (0-255). 69 2. A gamma-corrected CRGB value (even if input is CHSV or packed). 70 3. A list of gamma-corrected CRGB values. 71 72 In the tuple/list cases, there is NO return value if 'inplace' 73 is true -- the original values are modified. 74 """ 75 76 # If single gamma value is passed, keep that, otherwise convert 77 # gamma values to tuple for gamma_adjust function. 78 if g_g is not None and g_b is not None: 79 g_r = (g_r, g_g, g_b) 80 81 return fancy.gamma_adjust(n, g_r, inplace=inplace) 82 83 84 def napplyGamma_video(n, g_r=GFACTOR, g_g=None, g_b=None): 85 """ In-place version of applyGamma_video() (to mimic FastLED function 86 name). This is for RGB tuples and tuple lists (not the prior function's 87 integer case) 88 """ 89 90 return applyGamma_video(n, g_r, g_g, g_b, inplace=True) 91 92 93 def loadDynamicGradientPalette(src, size): 94 """ Kindasorta like FastLED's loadDynamicGradientPalette() function, 95 with some gotchas. 96 97 ACCEPTS: Gradient palette data as a 'bytes' type (makes it easier to copy 98 over gradient palettes from existing FastLED Arduino sketches)... 99 each palette entry is four bytes: a relative position (0-255) 100 within the overall resulting palette (whatever its size), and 101 3 values for R, G and B...and a length for a new palette list 102 to be allocated. 103 104 RETURNS: list of CRGB colors. 105 """ 106 107 # Convert gradient from bytelist (groups of 4) to list of tuples, 108 # each consisting of a position (0.0 to 1.0) and CRGB color. 109 # (This is what FancyLED's expand_gradient needs for input.) 110 grad = [] 111 for i in range(0, len(src), 4): 112 grad.append((src[i] / 255.0, fancy.CRGB(src[i + 1], src[i + 2], src[i + 3]))) 113 114 # Create palette (CRGB list) matching 'size' length 115 return fancy.expand_gradient(grad, size) 116 117 118 def ColorFromPalette(pal, pos, brightness=255, blend=False): 119 """ Approximates the FastLED ColorFromPalette() function 120 121 ACCEPTS: color palette (list of CRGB, CSHV and/or packed ints), 122 palette index (x16) + blend factor of next index (0-15) -- 123 e.g. pass 32 to retrieve palette index 2, or 40 for an 124 interpolated value between palette index 2 and 3, optional 125 brightness (0-255), optional blend flag (True/False) 126 127 RETURNS: CRGB color, no gamma correction 128 """ 129 130 # Alter 'pos' from FastLED-like behavior to fancyled range 131 if blend: 132 # Continuous interpolation 0.0 to 1.0 133 pos = (pos / 16.0) / len(pal) 134 else: 135 # No blending -- quantize to nearest palette bin 136 pos = floor(pos / 16.0) / len(pal) 137 138 color = fancy.palette_lookup(pal, pos) 139 140 if brightness < 1.0: 141 brightness /= 255.0 142 if isinstance(color, fancy.CHSV): 143 color = fancy.CRGB(color) 144 elif isinstance(color, int): 145 color = fancy.unpack(color) 146 color.red *= brightness 147 color.green *= brightness 148 color.blue *= brightness 149 150 return color 151 152 153 def hsv2rgb_spectrum(hue, sat, val): 154 155 """ This is named the same thing as FastLED's simpler HSV to RGB function 156 (spectrum, vs rainbow) but implementation is a bit different for the 157 sake of getting something running (adapted from some NeoPixel code). 158 159 ACCEPTS: hue, saturation, value in range 0 to 255 160 RETURNS: CRGB color. 161 """ 162 163 return fancy.CRGB(fancy.CHSV(hue / 255, sat / 255, val / 255)) 164 165 166 # pylint: enable=invalid-name