diff options
author | Mark Kriegsman <kriegsman@tr.org> | 2014-10-05 22:42:40 +0400 |
---|---|---|
committer | Mark Kriegsman <kriegsman@tr.org> | 2014-10-05 22:42:40 +0400 |
commit | 73989e3f0bd417fd5746292ca73fe27aa6fc7cc9 (patch) | |
tree | 71e23082d3e5ed83031cd60891b40e9c1a2e8c0b | |
parent | 91c36a8737bc807e26c61c21155504b08e6b5741 (diff) |
Fix for fill_gradient, switch to templates for a few functions to allow use on CHSV arrays as well as CRGB arrays, e.g., if there ever were such a thing as CHSVPalette.
-rw-r--r-- | colorutils.cpp | 124 | ||||
-rw-r--r-- | colorutils.h | 139 |
2 files changed, 156 insertions, 107 deletions
diff --git a/colorutils.cpp b/colorutils.cpp index 0f8d3832..6a12fb11 100644 --- a/colorutils.cpp +++ b/colorutils.cpp @@ -6,14 +6,31 @@ #include "colorutils.h" -void fill_solid( struct CRGB * pFirstLED, int numToFill, - const struct CRGB& color) + + +void fill_solid( struct CRGB * leds, int numToFill, + const struct CRGB& color) +{ + for( int i = 0; i < numToFill; i++) { + leds[i] = color; + } +} + +void fill_solid( struct CHSV * targetArray, int numToFill, + const struct CHSV& hsvColor) { for( int i = 0; i < numToFill; i++) { - pFirstLED[i] = color; + targetArray[i] = hsvColor; } } + +// void fill_solid( struct CRGB* targetArray, int numToFill, +// const struct CHSV& hsvColor) +// { +// fill_solid<CRGB>( targetArray, numToFill, (CRGB) hsvColor); +// } + void fill_rainbow( struct CRGB * pFirstLED, int numToFill, uint8_t initialhue, uint8_t deltahue ) @@ -28,74 +45,21 @@ void fill_rainbow( struct CRGB * pFirstLED, int numToFill, } } - -#define saccum87 int16_t - -void fill_gradient( CRGB* leds, - uint16_t startpos, CHSV startcolor, - uint16_t endpos, CHSV endcolor, - TGradientDirectionCode directionCode ) +void fill_rainbow( struct CHSV * targetArray, int numToFill, + uint8_t initialhue, + uint8_t deltahue ) { - // if the points are in the wrong order, straighten them - if( endpos < startpos ) { - uint16_t t = endpos; - CHSV tc = endcolor; - startpos = t; - startcolor = tc; - endcolor = startcolor; - endpos = startpos; - } - - saccum87 huedistance87; - saccum87 satdistance87; - saccum87 valdistance87; - - satdistance87 = (endcolor.sat - startcolor.sat) << 7; - valdistance87 = (endcolor.val - startcolor.val) << 7; - - uint8_t huedelta8 = endcolor.hue - startcolor.hue; - - if( directionCode == SHORTEST_HUES ) { - directionCode = FORWARD_HUES; - if( huedelta8 > 127) { - directionCode = BACKWARD_HUES; - } - } - - if( directionCode == LONGEST_HUES ) { - directionCode = FORWARD_HUES; - if( huedelta8 < 128) { - directionCode = BACKWARD_HUES; - } - } - - if( directionCode == FORWARD_HUES) { - huedistance87 = huedelta8 << 7; - } - else /* directionCode == BACKWARD_HUES */ - { - huedistance87 = (uint8_t)(256 - huedelta8) << 7; - huedistance87 = -huedistance87; - } - - uint16_t pixeldistance = endpos - startpos; - uint16_t p2 = pixeldistance / 2; - int16_t divisor = p2 ? p2 : 1; - saccum87 huedelta87 = huedistance87 / divisor; - saccum87 satdelta87 = satdistance87 / divisor; - saccum87 valdelta87 = valdistance87 / divisor; - - accum88 hue88 = startcolor.hue << 8; - accum88 sat88 = startcolor.sat << 8; - accum88 val88 = startcolor.val << 8; - for( uint16_t i = startpos; i <= endpos; i++) { - leds[i] = CHSV( hue88 >> 8, sat88 >> 8, val88 >> 8); - hue88 += huedelta87; - sat88 += satdelta87; - val88 += valdelta87; + CHSV hsv; + hsv.hue = initialhue; + hsv.val = 255; + hsv.sat = 255; + for( int i = 0; i < numToFill; i++) { + targetArray[i] = hsv; + hsv.hue += deltahue; } } + void fill_gradient_RGB( CRGB* leds, uint16_t startpos, CRGB startcolor, uint16_t endpos, CRGB endcolor ) @@ -136,32 +100,6 @@ void fill_gradient_RGB( CRGB* leds, } } - -void fill_gradient( CRGB* leds, uint16_t numLeds, const CHSV& c1, const CHSV& c2, TGradientDirectionCode directionCode ) -{ - uint16_t last = numLeds - 1; - fill_gradient( leds, 0, c1, last, c2, directionCode); -} - - -void fill_gradient( CRGB* leds, uint16_t numLeds, const CHSV& c1, const CHSV& c2, const CHSV& c3, TGradientDirectionCode directionCode ) -{ - uint16_t half = (numLeds / 2); - uint16_t last = numLeds - 1; - fill_gradient( leds, 0, c1, half, c2, directionCode); - fill_gradient( leds, half, c2, last, c3, directionCode); -} - -void fill_gradient( CRGB* leds, uint16_t numLeds, const CHSV& c1, const CHSV& c2, const CHSV& c3, const CHSV& c4, TGradientDirectionCode directionCode ) -{ - uint16_t onethird = (numLeds / 3); - uint16_t twothirds = ((numLeds * 2) / 3); - uint16_t last = numLeds - 1; - fill_gradient( leds, 0, c1, onethird, c2, directionCode); - fill_gradient( leds, onethird, c2, twothirds, c3, directionCode); - fill_gradient( leds, twothirds, c3, last, c4, directionCode); -} - #if 0 void fill_gradient( const CHSV& c1, const CHSV& c2) { diff --git a/colorutils.h b/colorutils.h index 181970e7..c2e1ec65 100644 --- a/colorutils.h +++ b/colorutils.h @@ -7,17 +7,27 @@ // fill_solid - fill a range of LEDs with a solid color -void fill_solid( struct CRGB * pFirstLED, int numToFill, +// Example: fill_solid( leds, NUM_LEDS, CRGB(50,0,200)); + +void fill_solid( struct CRGB * leds, int numToFill, const struct CRGB& color); +void fill_solid( struct CHSV* targetArray, int numToFill, + const struct CHSV& hsvColor); + + // fill_rainbow - fill a range of LEDs with a rainbow of colors, at // full saturation and full value (brightness) void fill_rainbow( struct CRGB * pFirstLED, int numToFill, uint8_t initialhue, uint8_t deltahue = 5); + +void fill_rainbow( struct CHSV * targetArray, int numToFill, + uint8_t initialhue, + uint8_t deltahue = 5); -// fill_gradient - fill a range of LEDs with a smooth HSV gradient +// fill_gradient - fill an array of colors with a smooth HSV gradient // between two specified HSV colors. // Since 'hue' is a value around a color wheel, // there are always two ways to sweep from one hue @@ -31,24 +41,125 @@ void fill_rainbow( struct CRGB * pFirstLED, int numToFill, // The default is SHORTEST_HUES, as this is nearly // always what is wanted. // +// fill_gradient can write the gradient colors EITHER +// (1) into an array of CRGBs (e.g., into leds[] array, or an RGB Palette) +// OR +// (2) into an array of CHSVs (e.g. an HSV Palette). +// +// In the case of writing into a CRGB array, the gradient is +// computed in HSV space, and then HSV values are converted to RGB +// as they're written into the RGB array. + typedef enum { FORWARD_HUES, BACKWARD_HUES, SHORTEST_HUES, LONGEST_HUES } TGradientDirectionCode; -void fill_gradient( struct CRGB* leds, + + +#define saccum87 int16_t + +template <typename T> +void fill_gradient( T* targetArray, uint16_t startpos, CHSV startcolor, uint16_t endpos, CHSV endcolor, - TGradientDirectionCode directionCode = SHORTEST_HUES ); + TGradientDirectionCode directionCode = SHORTEST_HUES ) +{ + // if the points are in the wrong order, straighten them + if( endpos < startpos ) { + uint16_t t = endpos; + CHSV tc = endcolor; + startpos = t; + startcolor = tc; + endcolor = startcolor; + endpos = startpos; + } + + saccum87 huedistance87; + saccum87 satdistance87; + saccum87 valdistance87; + + satdistance87 = (endcolor.sat - startcolor.sat) << 7; + valdistance87 = (endcolor.val - startcolor.val) << 7; + + uint8_t huedelta8 = endcolor.hue - startcolor.hue; + + if( directionCode == SHORTEST_HUES ) { + directionCode = FORWARD_HUES; + if( huedelta8 > 127) { + directionCode = BACKWARD_HUES; + } + } + + if( directionCode == LONGEST_HUES ) { + directionCode = FORWARD_HUES; + if( huedelta8 < 128) { + directionCode = BACKWARD_HUES; + } + } + + if( directionCode == FORWARD_HUES) { + huedistance87 = huedelta8 << 7; + } + else /* directionCode == BACKWARD_HUES */ + { + huedistance87 = (uint8_t)(256 - huedelta8) << 7; + huedistance87 = -huedistance87; + } + + uint16_t pixeldistance = endpos - startpos; + int16_t divisor = pixeldistance ? pixeldistance : 1; + + saccum87 huedelta87 = huedistance87 / divisor; + saccum87 satdelta87 = satdistance87 / divisor; + saccum87 valdelta87 = valdistance87 / divisor; + + huedelta87 *= 2; + satdelta87 *= 2; + valdelta87 *= 2; + + accum88 hue88 = startcolor.hue << 8; + accum88 sat88 = startcolor.sat << 8; + accum88 val88 = startcolor.val << 8; + for( uint16_t i = startpos; i <= endpos; i++) { + targetArray[i] = CHSV( hue88 >> 8, sat88 >> 8, val88 >> 8); + hue88 += huedelta87; + sat88 += satdelta87; + val88 += valdelta87; + } +} + -// Convenience functions to fill a range of leds[] with a +// Convenience functions to fill an array of colors with a // two-color, three-color, or four-color gradient -void fill_gradient( struct CRGB* leds, uint16_t numLeds, - const CHSV& c1, const CHSV& c2, - TGradientDirectionCode directionCode = SHORTEST_HUES ); -void fill_gradient( struct CRGB* leds, uint16_t numLeds, - const CHSV& c1, const CHSV& c2, const CHSV& c3, - TGradientDirectionCode directionCode = SHORTEST_HUES ); -void fill_gradient( struct CRGB* leds, uint16_t numLeds, - const CHSV& c1, const CHSV& c2, const CHSV& c3, const CHSV& c4, - TGradientDirectionCode directionCode = SHORTEST_HUES ); +template <typename T> +void fill_gradient( T* targetArray, uint16_t numLeds, const CHSV& c1, const CHSV& c2, + TGradientDirectionCode directionCode = SHORTEST_HUES ) +{ + uint16_t last = numLeds - 1; + fill_gradient( targetArray, 0, c1, last, c2, directionCode); +} + +template <typename T> +void fill_gradient( T* targetArray, uint16_t numLeds, + const CHSV& c1, const CHSV& c2, const CHSV& c3, + TGradientDirectionCode directionCode = SHORTEST_HUES ) +{ + uint16_t half = (numLeds / 2); + uint16_t last = numLeds - 1; + fill_gradient( targetArray, 0, c1, half, c2, directionCode); + fill_gradient( targetArray, half, c2, last, c3, directionCode); +} + +template <typename T> +void fill_gradient( T* targetArray, uint16_t numLeds, + const CHSV& c1, const CHSV& c2, const CHSV& c3, const CHSV& c4, + TGradientDirectionCode directionCode = SHORTEST_HUES ) +{ + uint16_t onethird = (numLeds / 3); + uint16_t twothirds = ((numLeds * 2) / 3); + uint16_t last = numLeds - 1; + fill_gradient( targetArray, 0, c1, onethird, c2, directionCode); + fill_gradient( targetArray, onethird, c2, twothirds, c3, directionCode); + fill_gradient( targetArray, twothirds, c3, last, c4, directionCode); +} // convenience synonym #define fill_gradient_HSV fill_gradient |