diff --git a/RGBShades.ino b/RGBShades.ino index ca4a9cd..09e49e7 100644 --- a/RGBShades.ino +++ b/RGBShades.ino @@ -64,7 +64,9 @@ functionList effectList[] = {threeSine, colorFill, sideRain, shadesOutline, - hearts}; + hearts, + pickHueStartColor, + pickHueAmount}; // Timing parameters #define cycleTime 15000 diff --git a/effects.h b/effects.h index f966704..923f4f4 100644 --- a/effects.h +++ b/effects.h @@ -13,8 +13,13 @@ void threeSine() { // startup tasks if (effectInit == false) { effectInit = true; - effectDelay = 20; + if(doHueSubsection)//Pause the effect to show the last saved hue amount + { + effectDelay = 600; + return; + } } + effectDelay = 20; // Draw one frame of the animation into the LED array for (byte x = 0; x < kMatrixWidth; x++) { @@ -25,8 +30,20 @@ void threeSine() { byte sinDistanceR = qmul8(abs(y*(255/kMatrixHeight) - sin8(sineOffset*9+x*16)),2); byte sinDistanceG = qmul8(abs(y*(255/kMatrixHeight) - sin8(sineOffset*10+x*16)),2); byte sinDistanceB = qmul8(abs(y*(255/kMatrixHeight) - sin8(sineOffset*11+x*16)),2); - - leds[XY(x,y)] = CRGB(255-sinDistanceR, 255-sinDistanceG, 255-sinDistanceB); + + if(doHueSubsection) + { + CRGB firstColor = SectionCHSV(0, 255, 255); + CRGB secondColor = SectionCHSV(85, 255, 255); + CRGB thirdColor = SectionCHSV(170, 255, 255); + leds[XY(x,y)] = + firstColor.nscale8(255-sinDistanceR) + + secondColor.nscale8(255-sinDistanceG) + + thirdColor.nscale8(255-sinDistanceB); + }else + { + leds[XY(x,y)] = CRGB(255-sinDistanceR, 255-sinDistanceG, 255-sinDistanceB); + } } } @@ -57,7 +74,7 @@ void plasma() { for (int x = 0; x < kMatrixWidth; x++) { for (int y = 0; y < kMatrixHeight; y++) { byte color = sin8(sqrt(sq(((float)x-7.5)*10+xOffset-127)+sq(((float)y-2)*10+yOffset-127))+offset); - leds[XY(x,y)] = CHSV(color, 255, 255); + leds[XY(x,y)] = SectionCHSV(color, 255, 255); } } @@ -83,7 +100,7 @@ void rider() { int brightness = abs(x*(256/kMatrixWidth) - triwave8(riderPos)*2 + 127)*3; if (brightness > 255) brightness = 255; brightness = 255 - brightness; - CRGB riderColor = CHSV(cycleHue, 255, brightness); + CRGB riderColor = SectionCHSV(cycleHue, 255, brightness); for (byte y = 0; y < kMatrixHeight; y++) { leds[XY(x,y)] = riderColor; } @@ -107,7 +124,7 @@ void glitter() { // Draw one frame of the animation into the LED array for (int x = 0; x < kMatrixWidth; x++) { for (int y = 0; y 8) { - leds[XY(x,y)] = CRGB::Red; + leds[XY(x,y)] = SectionCHSV(0, 255, 255); } else { leds[XY(x,y)] = CRGB::Black; } @@ -204,7 +226,7 @@ void sideRain() { scrollArray(rainDir); byte randPixel = random8(kMatrixHeight); for (byte y = 0; y < kMatrixHeight; y++) leds[XY((kMatrixWidth-1) * rainDir,y)] = CRGB::Black; - leds[XY((kMatrixWidth-1)*rainDir, randPixel)] = CHSV(cycleHue, 255, 255); + leds[XY((kMatrixWidth-1)*rainDir, randPixel)] = SectionCHSV(cycleHue, 255, 255); } @@ -221,7 +243,10 @@ void confetti() { // scatter random colored pixels at several random coordinates for (byte i = 0; i < 4; i++) { - leds[XY(random16(kMatrixWidth),random16(kMatrixHeight))] = ColorFromPalette(currentPalette, random16(255), 255);//CHSV(random16(255), 255, 255); + if (!doHueSubsection) + leds[XY(random16(kMatrixWidth),random16(kMatrixHeight))] = ColorFromPalette(currentPalette, random16(255), 255); + else + leds[XY(random16(kMatrixWidth), random16(kMatrixHeight))] = SectionCHSV(random16(255), 255, 255); random16_add_entropy(1); } @@ -240,7 +265,7 @@ void slantBars() { for (byte x = 0; x < kMatrixWidth; x++) { for (byte y = 0; y < kMatrixHeight; y++) { - leds[XY(x,y)] = CHSV(cycleHue, 255, quadwave8(x*32+y*32+slantPos)); + leds[XY(x,y)] = SectionCHSV(cycleHue, 255, quadwave8(x*32+y*32+slantPos)); } } @@ -263,7 +288,10 @@ void shadesOutline(){ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 43, 44, 67, 66, 65, 64, 63, 50, 37, 21, 22, 36, 51, 62, 61, 60, 59, 58, 57, 30, 29}; + if (!doHueSubsection) leds[OutlineTable[x]] = currentPalette[currentColor]; + else + leds[OutlineTable[x]] = SectionCHSV(currentColor * 16, 255, 255); if (erase) leds[OutlineTable[x]] = CRGB::Black; x++; @@ -298,18 +326,62 @@ void hearts() { y = 0; if (y == 0) for (x = 0; x < 6; x++) - leds[SmHeart[x]] = CRGB::Salmon; //Tried to transition from pink-ish to red. Kinda worked. + leds[SmHeart[x]] = SectionCHSV(0, 255, 255); if (y == 1) for (x = 0; x < 18; x++) - leds[MedHeart[x]] = CRGB::Tomato; + leds[MedHeart[x]] = SectionCHSV(42, 255, 255); if (y == 2) for (x = 0; x < 26; x++) - leds[LrgHeart[x]] = CRGB::Crimson; + leds[LrgHeart[x]] = SectionCHSV(84, 255, 255); if (y == 3){ for (x = 0; x < 40; x++) - leds[HugeHeart[x]] = CRGB::Red; + leds[HugeHeart[x]] = SectionCHSV(126, 255, 255); effectDelay = 450;} //set the delay slightly longer for HUGE heart. if (y == 4) FastLED.clear(); y++; } + +//Blasts a hue over all LEDs, the color when the effect ends becomes the start hue for all other effects +void pickHueStartColor() { + // startup tasks + if (effectInit == false) { + effectInit = true; + effectDelay = 15; + doHueSubsection = true; + } + fillAll(SectionCHSV(0, 255, 255)); + incrimentHueOffset(1); +} + +//Left to right rainbow, when the effect is over, the length of the hue shift is used to limit hue in all other effects +void pickHueAmount() +{ + // startup tasks + if (effectInit == false) { + effectInit = true; + //Add a delay here for a moment to verify settings + effectDelay = 300; + return; + } + effectDelay = 40;//Speed back to normal + + incrimentHueAmmount(1); + byte maxLeds = kMatrixHeight * kMatrixWidth; + //Loop left to right over each led + for (byte y = 0; y < kMatrixHeight; y++) { + for (byte x = 0; x < (kMatrixWidth - 0); x++) { + byte number = (x*kMatrixHeight) + y; + //Draw a led of the hue of the max value if the division of hue had stopped there + if ((hueAmmount) >(number * (255 / maxLeds))) + { + leds[XY(x, y)] = CHSV(((255. * number) / maxLeds) + hueOffset, 255, 255); + } + else + { + leds[XY(x, y)] = SectionCHSV(0, 0, 0); + } + } + } +} + diff --git a/utils.h b/utils.h index ecacc94..ea0c70c 100644 --- a/utils.h +++ b/utils.h @@ -25,6 +25,36 @@ void hueCycle(byte incr) { cycleHue+=incr; } +/* Instead of a perpetually incrimenting hue, override hue calculations to instead do a + * sinusodial loop back and forth over a smaller section of the scale. + * This can allow various effects, ice, hue, or even single colors. + * If the hue ammount is close to max, switch back to an incrimental mode and allow pallets + * to be used again. Continually incrimenting the offset and ammount allows the autoCycle + * mode to keep making new sections. + */ +//Keep making new effects. +byte hueOffset = 0;//The start hue for our cycle +byte hueAmmountIncrimentor = 0;//incrimentor for generating the hueAmmount +byte hueAmmount = 1;//The distance across the hue scale to allow sliding +bool doHueSubsection = false;//Switch to go back to a continuous hue slide (no more back & forth) +CHSV SectionCHSV(uint8_t h, uint8_t s, uint8_t v) +{ + //return a hue from a sinusodial wave across our current section of the hue scale + if (doHueSubsection)return CHSV((quadwave8(h) / (255. / hueAmmount)) + hueOffset, s, v); + return CHSV(h, s, v); +} +void incrimentHueOffset(uint8_t offset) +{ + hueOffset += offset; +} +void incrimentHueAmmount(uint8_t offset) +{ + hueAmmountIncrimentor += offset; + //Don't actually increase it till it loops to 0, instead make it go up, then back down. + hueAmmount = triwave8(hueAmmountIncrimentor); + doHueSubsection = hueAmmount < 230;//If the hue amount is almost a full rainbow, make it a full rainbow to allow pallet effects and others +} + // Set every LED in the array to a specified color void fillAll(CRGB fillColor) { for (byte i = 0; i < NUM_LEDS; i++) {