Adafruit_Learning_System_Gu.../GemmaM0_Band_Jacket/DiscoBandCamp/effects.h
2025-01-06 18:35:49 -05:00

307 lines
8.1 KiB
C

// SPDX-FileCopyrightText: 2019 Anne Barela for Adafruit Industries
//
// SPDX-License-Identifier: MIT
// Selection of effects from the FastLED library & Macetech RGB Shades
// Triple Sine Waves
void threeSine() {
static byte sineOffset = 0; // counter for current position of sine waves
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 20;
}
// Draw one frame of the animation into the LED array
for (byte x = 0; x < kMatrixWidth; x++) {
for (int y = 0; y < kMatrixHeight; y++) {
// Calculate "sine" waves with varying periods
// sin8 is used for speed; cos8, quadwave8, or triwave8 would also work here
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, 0, 0)] = CRGB(255 - sinDistanceR, 255 - sinDistanceG, 255 - sinDistanceB);
}
}
sineOffset++; // byte will wrap from 255 to 0, matching sin8 0-255 cycle
}
// Solid Colors
// Create your own!
void SolidWhite() //for the porto-potty
{
fill_solid( leds, NUM_LEDS, CRGB::White);
}
void SolidRed() //for startup, good for saving battery
{
fill_solid( leds, NUM_LEDS, CRGB::Red);
}
// RGB Plasma
void plasma() {
static byte offset = 0; // counter for radial color wave motion
static int plasVector = 0; // counter for orbiting plasma center
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 10;
}
// Calculate current center of plasma pattern (can be offscreen)
int xOffset = cos8(plasVector / 256);
int yOffset = sin8(plasVector / 256);
// Draw one frame of the animation into the LED array
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, 0, 0)] = CHSV(color, 255, 255);
}
}
offset++; // wraps at 255 for sin8
plasVector += 16; // using an int for slower orbit (wraps at 65536)
}
// Scanning pattern left/right, using global hue cycle
void rider() {
static byte riderPos = 0;
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 5;
riderPos = 0;
}
// Draw one frame of the animation into the LED array
for (byte x = 0; x < kMatrixWidth; x++) {
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);
for (byte y = 0; y < kMatrixHeight; y++) {
leds[XY(x, y, 0, 0)] = riderColor;
}
}
riderPos++; // byte wraps to 0 at 255, triwave8 is also 0-255 periodic
}
// Fills saturated colors into the array from alternating directions
void colorFill() {
static byte currentColor = 0;
static byte currentRow = 0;
static byte currentDirection = 0;
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 45;
currentColor = 0;
currentRow = 0;
currentDirection = 0;
currentPalette = RainbowColors_p;
}
// test a bitmask to fill up or down when currentDirection is 0 or 2 (0b00 or 0b10)
if (!(currentDirection & 1)) {
effectDelay = 45; // slower since vertical has fewer pixels
for (byte x = 0; x < kMatrixWidth; x++) {
byte y = currentRow;
if (currentDirection == 2) y = kMatrixHeight - 1 - currentRow;
leds[XY(x, y, 0, 0)] = currentPalette[currentColor];
}
}
// test a bitmask to fill left or right when currentDirection is 1 or 3 (0b01 or 0b11)
if (currentDirection & 1) {
effectDelay = 20; // faster since horizontal has more pixels
for (byte y = 0; y < kMatrixHeight; y++) {
byte x = currentRow;
if (currentDirection == 3) x = kMatrixWidth - 1 - currentRow;
leds[XY(x, y, 0, 0)] = currentPalette[currentColor];
}
}
currentRow++;
// detect when a fill is complete, change color and direction
if ((!(currentDirection & 1) && currentRow >= kMatrixHeight) || ((currentDirection & 1) && currentRow >= kMatrixWidth)) {
currentRow = 0;
currentColor += random8(3, 6);
if (currentColor > 15) currentColor -= 16;
currentDirection++;
if (currentDirection > 3) currentDirection = 0;
effectDelay = 300; // wait a little bit longer after completing a fill
}
}
// Random pixels scroll sideways, using current hue
#define rainDir 0
void sideRain() {
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 30;
}
scrollArray(rainDir);
byte randPixel = random8(kMatrixHeight);
for (byte y = 0; y < kMatrixHeight; y++) leds[XY((kMatrixWidth - 1) * rainDir, y, 0, 0)] = CRGB::Black;
leds[XY((kMatrixWidth - 1)*rainDir, randPixel, 0, 0)] = CHSV(cycleHue, 255, 255);
}
// CONFETTI: pixels with random locations and random colors selected from a palette
// Create your own confetti modes using the built in Palettes (see utils.h) or create your own
// Use with the fadeAll function (see .ino) to allow old pixels to decay
void confetti() {
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 10;
selectRandomPalette();
}
// scatter random colored pixels at several random coordinates
for (byte i = 0; i < 4; i++) {
leds[XY(random16(kMatrixWidth), random16(kMatrixHeight), 0, 0)] = ColorFromPalette(currentPalette, random16(255), 255); //CHSV(random16(255), 255, 255);
random16_add_entropy(1);
}
}
//Palette for myConfetti
const TProgmemPalette16 MyColors_p PROGMEM =
{
CRGB:: Crimson,
CRGB:: Maroon,
CRGB:: Red,
CRGB:: OrangeRed,
CRGB:: Crimson,
CRGB:: Maroon,
CRGB:: Red,
CRGB:: OrangeRed,
CRGB:: Crimson,
CRGB:: Maroon,
CRGB:: Red,
CRGB:: OrangeRed,
CRGB:: Crimson,
CRGB:: Maroon,
CRGB:: Red,
CRGB:: OrangeRed,
};
void myConfetti() {
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 15;
}
// scatter random colored pixels at several random coordinates
for (byte i = 0; i < 4; i++) {
leds[XY(random16(kMatrixWidth), random16(kMatrixHeight), 0, 0)] = ColorFromPalette(MyColors_p, random16(255), 255); //CHSV(random16(255), 255, 255);
random16_add_entropy(1);
}
}
// Example from the NoisePlusPalette FastLED example sketch. See utils.h
void NoisePlusPalette() {
fillnoise8();
mapNoiseToLEDsUsingPalette();
}
// Draw slanting bars scrolling across the array, using current hue
void slantBars() {
static byte slantPos = 0;
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 5;
}
for (byte x = 0; x < kMatrixWidth; x++) {
for (byte y = 0; y < kMatrixHeight; y++) {
leds[XY(x, y, 0, 0)] = CHSV(cycleHue, 255, quadwave8(x * 32 + y * 32 + slantPos));
}
}
slantPos -= 4;
}
//from Mark Kriegsman
void swirly()
{
// startup tasks
if (effectInit == false) {
effectInit = true;
effectDelay = 15;
}
// Apply some blurring to whatever's already on the matrix
// Note that we never actually clear the matrix, we just constantly
// blur it repeatedly. Since the blurring is 'lossy', there's
// an automatic trend toward black -- by design.
uint8_t blurAmount = beatsin8(2,10,255);
blur2d(leds, kMatrixWidth, kMatrixHeight, blurAmount, myXYMap);
// Use two out-of-sync sine waves
uint8_t i = beatsin8( 27, kBorderWidth, kMatrixHeight-kBorderWidth);
uint8_t j = beatsin8( 41, kBorderWidth, kMatrixWidth-kBorderWidth);
// Also calculate some reflections
uint8_t ni = (kMatrixWidth-1)-i;
uint8_t nj = (kMatrixWidth-1)-j;
// The color of each point shifts over time, each at a different speed.
uint16_t ms = millis();
leds[XY(i, j, 0, 0)] += CHSV( ms / 11, 200, 255);
leds[XY(j, i, 0, 0)] += CHSV( ms / 13, 200, 255);
leds[XY(ni,nj, 0, 0)] += CHSV( ms / 17, 200, 255);
leds[XY(nj,ni, 0, 0)] += CHSV( ms / 29, 200, 255);
leds[XY(i,nj, 0, 0)] += CHSV( ms / 37, 200, 255);
leds[XY(ni, j, 0, 0)] += CHSV( ms / 41, 200, 255);
FastLED.show();
}