#include <FastLED.h>
#include <SPI.h>
#include <Wire.h>
// LED strip configuration
#define NUM_LEDS 96
#define LED_PIN1 29
#define LED_PIN2 28
CRGB leds1[NUM_LEDS];
CRGB leds2[NUM_LEDS];
CRGB cpuled[1];
const int buttonUp = 2;
const int buttonDown = 3;
uint8_t gHue = 64;
int currentEffect = 0;
const int numEffects = 16;
void setup() {
Serial.begin(115200);
Serial.println("DiscoSlots");
FastLED.addLeds<WS2813, LED_PIN1, GRB>(leds1, NUM_LEDS);
FastLED.addLeds<WS2813, LED_PIN2, GRB>(leds2, NUM_LEDS);
FastLED.addLeds<WS2812, 16, GRB>(cpuled, 1);
FastLED.setBrightness(255);
pinMode(buttonUp, INPUT_PULLUP);
pinMode(buttonDown, INPUT_PULLUP);
cpuled[0]=CRGB::Red;
FastLED.show();
}
void loop() {
void (*effects[])() = {
rainbow, bpm, bouncingBalls, sinelonSmooth, colorWipe,
fire, meteorRain, pacifica, noiseSmooth, dotsSmooth,
cylon, colorWave, wave, fireIce, colorWaves, colorPulse
};
const char* effectNames[] = {
"Rainbow", "BPM", "Bouncing Balls", "Sinelon Smooth", "Color Wipe",
"Fire", "Meteor Rain", "Pacifica", "Noise Smooth", "Dots Smooth",
"Cylon", "Color Wave", "Wave", "Fire Ice", "Color Waves", "Color Pulse"
};
static unsigned long lastButtonPress = 0;
if (millis() - lastButtonPress > 200) {
if (digitalRead(buttonUp) == LOW) {
lastButtonPress = millis();
currentEffect = (currentEffect + 1) % numEffects;
Serial.println(effectNames[currentEffect]);
}
if (digitalRead(buttonDown) == LOW) {
lastButtonPress = millis();
currentEffect = (currentEffect - 1 + numEffects) % numEffects;
Serial.println(effectNames[currentEffect]);
}
if (digitalRead(buttonUp) == LOW && digitalRead(buttonDown) == LOW) {
lastButtonPress = millis();
FastLED.clear();
FastLED.show();
}
}
effects[currentEffect]();
FastLED.show();
FastLED.delay(20);
}
// Define each effect function
void rainbow() {
fill_rainbow(leds1, NUM_LEDS, gHue, 7);
fill_rainbow(leds2, NUM_LEDS, gHue + 128, 7); // Opposite color
gHue++;
}
void sinelonSmooth() {
static int pos = 0;
fadeToBlackBy(leds1, NUM_LEDS, 20);
fadeToBlackBy(leds2, NUM_LEDS, 20);
pos = beatsin16(13, 0, NUM_LEDS - 1);
leds1[pos] += CHSV(gHue, 255, 192);
leds2[NUM_LEDS - pos - 1] += CHSV(gHue + 128, 255, 192);
gHue++;
}
void bpm() {
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
leds2[NUM_LEDS-i] = ColorFromPalette(palette, gHue + 128 + (i * 2), beat - gHue + 128 + (i * 10));
}
gHue++;
}
void colorWave() {
static uint16_t startIndex = 0;
startIndex += 5;
fill_palette(leds1, NUM_LEDS, startIndex, 16, PartyColors_p, 255, LINEARBLEND);
fill_palette(leds2, NUM_LEDS, startIndex + 128, 16, PartyColors_p, 255, LINEARBLEND);
}
void wave() {
static uint8_t sineOffset = 0;
sineOffset++;
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = CHSV((sin8(i * 8 + sineOffset) - 128) / 2 + 128, 255, 255);
leds2[i] = CHSV((sin8(i * 8 + sineOffset + 128) - 128) / 2 + 128, 255, 255);
}
}
void colorPulse() {
uint8_t beat = beatsin8(30, 0, 255);
fill_solid(leds1, NUM_LEDS, CHSV(gHue, 255, beat));
fill_solid(leds2, NUM_LEDS, CHSV(gHue + 128, 255, beat));
gHue++;
}
void bouncingBalls() {
static float Gravity = -9.81;
static int StartHeight = 1;
static float ImpactVelocityStart = sqrt(-2 * Gravity * StartHeight);
static float Height[NUM_LEDS];
static float ImpactVelocity[NUM_LEDS];
static float TimeSinceLastBounce[NUM_LEDS];
static int Position[NUM_LEDS];
static long ClockTimeSinceLastBounce[NUM_LEDS];
static float Dampening[NUM_LEDS];
for (int i = 0; i < NUM_LEDS; i++) {
ClockTimeSinceLastBounce[i] = millis();
Height[i] = StartHeight;
Position[i] = 0;
ImpactVelocity[i] = ImpactVelocityStart;
TimeSinceLastBounce[i] = 0;
Dampening[i] = 0.90 - float(i) / pow(NUM_LEDS, 2);
}
for (int i = 0; i < NUM_LEDS; i++) {
TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i];
Height[i] = 0.5 * Gravity * pow(TimeSinceLastBounce[i] / 1000, 2.0) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000;
if (Height[i] < 0) {
Height[i] = 0;
ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
ClockTimeSinceLastBounce[i] = millis();
if (ImpactVelocity[i] < 0.01) {
ImpactVelocity[i] = ImpactVelocityStart;
}
}
Position[i] = round(Height[i] * (NUM_LEDS - 1) / StartHeight);
}
for (int i = 0; i < NUM_LEDS; i++) {
leds1[Position[i]] = CHSV(gHue + 64 * i / NUM_LEDS, 200, 255);
leds2[NUM_LEDS - Position[i] - 1] = CHSV(gHue + 128 + 64 * i / NUM_LEDS, 200, 255);
}
gHue++;
}
void colorWipe() {
static int pos = 0;
fill_solid(leds1, pos, CHSV(gHue, 255, 255));
fill_solid(leds2, pos, CHSV(gHue + 128, 255, 255));
pos++;
if (pos >= NUM_LEDS) pos = 0;
gHue++;
}
void fire() {
static byte heat1[NUM_LEDS];
static byte heat2[NUM_LEDS];
for (int i = 0; i < NUM_LEDS; i++) {
heat1[i] = qsub8(heat1[i], random8(0, ((55 * 10) / NUM_LEDS) + 2));
heat2[i] = qsub8(heat1[i], random8(0, ((55 * 10) / NUM_LEDS) + 2));
}
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat1[k] = (heat1[k - 1] + heat1[k - 2] + heat1[k - 2]) / 3;
heat2[k] = (heat2[k - 1] + heat2[k - 2] + heat2[k - 2]) / 3;
}
if (random8() < 120) {
int y1 = random8(7);
int y2 = random8(7);
heat1[y1] = qadd8(heat1[y1], random8(160, 255));
heat1[y2] = qadd8(heat1[y2], random8(160, 255));
}
for (int j = 0; j < NUM_LEDS; j++) {
leds1[j] = HeatColor(heat1[j]);
leds2[j] = HeatColor(heat2[j]);
}
gHue++;
}
void fireIce() {
static byte heat[NUM_LEDS];
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8(heat[i], random8(0, ((55 * 10) / NUM_LEDS) + 2));
}
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
}
if (random8() < 120) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
for (int j = 0; j < NUM_LEDS; j++) {
leds1[j] = HeatColor(heat[j]);
leds2[j] = CHSV((240 - (heat[j] / 3)), 255, heat[j]); // Cool color effect
}
gHue++;
}
void meteorRain() {
static byte meteorSize = 10;
static byte meteorTrailDecay = 64;
static boolean meteorRandomDecay = true;
static int pos = 0;
for (int j = 0; j < NUM_LEDS; j++) {
if ((!meteorRandomDecay) || (random8() > 128)) {
fadeToBlackBy(leds1, NUM_LEDS, meteorTrailDecay);
fadeToBlackBy(leds2, NUM_LEDS, meteorTrailDecay);
}
}
for (int j = 0; j < meteorSize; j++) {
if ((pos - j < NUM_LEDS) && (pos - j >= 0)) {
leds1[pos - j] = CHSV(gHue, 255, 255);
leds2[pos - j] = CHSV(gHue + 128, 255, 255);
}
}
pos++;
if (pos >= NUM_LEDS) pos = 0;
gHue++;
}
void pacifica() {
static const CRGBPalette16 pacifica_palette_1 = CRGBPalette16(CRGB::Blue, CRGB::DeepSkyBlue, CRGB::Cyan, CRGB::Aquamarine);
static const CRGBPalette16 pacifica_palette_2 = CRGBPalette16(CRGB::Aqua, CRGB::Aquamarine, CRGB::Azure, CRGB::DeepSkyBlue);
static const CRGBPalette16 pacifica_palette_3 = CRGBPalette16(CRGB::Teal, CRGB::DarkTurquoise, CRGB::DeepSkyBlue, CRGB::Blue);
static const CRGBPalette16 pacifica_palette_4 = CRGBPalette16(CRGB::DarkCyan, CRGB::MediumBlue, CRGB::Blue, CRGB::DarkBlue);
uint16_t sCIStart1 = beatsin16(6, 0, 65535);
uint16_t sCIStart2 = beatsin16(7, 0, 65535);
uint16_t sCIStart3 = beatsin16(8, 0, 65535);
uint16_t sCIStart4 = beatsin16(9, 0, 65535);
for (uint16_t i = 0; i < NUM_LEDS; i++) {
uint16_t sCI1 = sCIStart1 + i * (65536 / NUM_LEDS);
uint16_t sCI2 = sCIStart2 + i * (65536 / NUM_LEDS);
uint16_t sCI3 = sCIStart3 + i * (65536 / NUM_LEDS);
uint16_t sCI4 = sCIStart4 + i * (65536 / NUM_LEDS);
leds1[i] = ColorFromPalette(pacifica_palette_1, sCI1 >> 8, 255, LINEARBLEND);
leds1[i] += ColorFromPalette(pacifica_palette_2, sCI2 >> 8, 255, LINEARBLEND);
leds1[i] += ColorFromPalette(pacifica_palette_3, sCI3 >> 8, 255, LINEARBLEND);
leds1[i] += ColorFromPalette(pacifica_palette_4, sCI4 >> 8, 255, LINEARBLEND);
leds2[i] = ColorFromPalette(pacifica_palette_1, sCI1 >> 8, 255, LINEARBLEND);
leds2[i] += ColorFromPalette(pacifica_palette_2, sCI2 >> 8, 255, LINEARBLEND);
leds2[i] += ColorFromPalette(pacifica_palette_3, sCI3 >> 8, 255, LINEARBLEND);
leds2[i] += ColorFromPalette(pacifica_palette_4, sCI4 >> 8, 255, LINEARBLEND);
}
gHue++;
}
void noiseSmooth() {
static uint16_t x = random16();
static uint16_t y = random16();
static uint16_t z = random16();
static uint16_t scale = 30;
for (uint16_t i = 0; i < NUM_LEDS; i++) {
uint8_t noise = inoise8(x + i * scale, y, z);
leds1[i] = CHSV(noise, 255, 255);
leds2[i] = CHSV(noise + 128, 255, 255);
}
x++;
y++;
z++;
}
void dotsSmooth() {
static uint8_t startIndex = 0;
startIndex++;
fill_rainbow(leds1, NUM_LEDS, startIndex, 16);
fill_rainbow(leds2, NUM_LEDS, startIndex + 128, 16);
for (int i = 0; i < NUM_LEDS; i++) {
if (random8() < 50) {
leds1[i] = CRGB::White;
leds2[i] = CRGB::White;
}
}
gHue++;
}
void cylon() {
static uint8_t hue = 0;
for (int i = 0; i < NUM_LEDS; i++) {
leds1[i] = CHSV(hue++, 255, 255);
leds2[i] = CHSV(hue + 128, 255, 255);
FastLED.show();
fadeToBlackBy(leds1, NUM_LEDS, 20);
fadeToBlackBy(leds2, NUM_LEDS, 20);
delay(10);
}
}
void colorWaves() {
uint8_t startIndex = gHue;
fill_rainbow(leds1, NUM_LEDS, startIndex, 5);
fill_rainbow(leds2, NUM_LEDS, startIndex + 128, 5);
uint8_t wave1 = beatsin8(9, 0, NUM_LEDS - 1);
uint8_t wave2 = beatsin8(7, 0, NUM_LEDS - 1);
uint8_t wave3 = beatsin8(13, 0, NUM_LEDS - 1);
leds1[wave1] = CRGB::White;
leds2[wave2] = CRGB::White;
leds1[wave3] = CRGB::White;
leds2[wave3] = CRGB::White;
gHue++;
}