#include

#ifdef __AVR__

 #include // Required for 16 MHz Adafruit Trinket

#endif

#define PIXEL_PIN    D7

#define BUTTON_PIN   D5

#define PIXEL_COUNT  10

Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

bool modeChanged = false;

int mode = 0; // 0 for flame, 1 for rainbow, 2-8 for solid colors, 9 for off

unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled

unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {

  Serial.begin(9600);

  strip.begin();

  strip.show();

  pinMode(BUTTON_PIN, INPUT_PULLUP);

}

void loop() {

  int reading = digitalRead(BUTTON_PIN);

  // Check button state and debounce

  if (reading == LOW) {

    if ((millis() - lastDebounceTime) > debounceDelay) {

      if (!modeChanged) {

        mode++;

        modeChanged = true;

        if (mode > 9) { // Update the maximum mode number

          mode = 0;

        }

        Serial.print("Mode changed to: ");

        Serial.println(mode);

      }

      lastDebounceTime = millis(); // Reset the debouncing timer

    }

  } else {

    modeChanged = false; // Reset mode changed flag when button is not pressed

  }

  switch (mode) {

    case 0:

      Serial.println("Fire");

      fireAnimation(75);

      break;

    case 1:

      Serial.println("Rainbow");

      rainbowAnimation();

      break;

    default:

      if (mode >= 2 && mode <= 8) {

        Serial.println("Colors");

        solidColor(mode - 2);

      } else if (mode == 9) {

        Serial.println("Off");

        turnOffLights();

      }

      break;

  }

}

void fireAnimation(int wait) {

  // First loop: Set the initial color for each LED

  for (int i = 0; i < strip.numPixels(); i++) {

    int r = random(150, 255); // More red for a fiery color

    int g = random(0, 85);    // Random amount of green to vary between red and yellow

    int b = 0;                // No blue component for fire

    strip.setPixelColor(i, r, g, b);

  }

  // Second loop: Apply the flicker effect

  for (int i = 0; i < strip.numPixels(); i++) {

    uint32_t color = strip.getPixelColor(i);

    int r = (color >> 16) & 0xFF;

    int g = (color >> 8) & 0xFF;

    // Random flicker effect

    int flicker = random(0, 150);

    r = max(0, r - flicker);

    g = max(0, g - flicker);

    strip.setPixelColor(i, r, g, 0);

  }

  strip.show();

  delay(wait);

}

void rainbowAnimation() {

  static unsigned long lastUpdate = 0; // Last update time

  static uint16_t j = 0; // Position in color wheel

  // Update only if the appropriate interval has passed

  if (millis() - lastUpdate > 20) {

    for (int i = 0; i < strip.numPixels(); i++) {

      strip.setPixelColor(i, Wheel((i + j) & 255));

    }

    strip.show();

    j = (j + 1) % 256; // Move to the next position in the color wheel

    lastUpdate = millis(); // Update the last update time

  }

}

// Input a value 0 to 255 to get a color value.

// The colors are a transition r - g - b - back to r.

uint32_t Wheel(byte WheelPos) {

  WheelPos = 255 - WheelPos;

  if(WheelPos < 85) {

    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);

  }

  if(WheelPos < 170) {

    WheelPos -= 85;

    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);

  }

  WheelPos -= 170;

  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);

}

void solidColor(int color) {

  uint32_t col;

  switch(color) {

    case 0: col = strip.Color(255, 0, 0); break; // Red

    case 1: col = strip.Color(255, 165, 0); break; // Orange

    case 2: col = strip.Color(255, 255, 0); break; // Yellow

    case 3: col = strip.Color(0, 255, 0); break; // Green

    case 4: col = strip.Color(0, 0, 255); break; // Blue

    case 5: col = strip.Color(75, 0, 130); break; // Indigo

    case 6: col = strip.Color(238, 130, 238); break; // Violet

    default: col = strip.Color(0, 0, 0); break; // Off

  }

  for(int i = 0; i < strip.numPixels(); i++) {

    strip.setPixelColor(i, col);

  }

  strip.show();

}

void turnOffLights() {

  for(int i = 0; i < strip.numPixels(); i++) {

    strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off this LED

  }

  strip.show();

}