#include <Adafruit_NeoPixel.h>
#define PIN 2
#define NUM_LEDS 16
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  //Color table loop//
  colorTableFadeLoop();
  //Strobe loop//
 colorTableStrobe();
  //Color table blink loop//
  colorTableBlinkLoop();
  //Halloween eyes//
  setAll(0,0,0);
  for(int i = 0; i < 16; i++) {
    HalloweenEyes(random(0,255),random(0,255),random(0,255),
                  random(1,3), random(0,NUM_LEDS/2),
                  true, random(5,50), random(30,80),
                  random(100, 500));
  } 
  //Cyclone loop// 
  CylonBounce(0xff, 0, 0, 2, 40, 50);
  CylonBounce(0, 0xff, 0, 2, 40, 50); 
  CylonBounce(0, 0, 0xff, 2, 40, 50); 
  CylonBounce(0xff, 0xff, 0, 2, 40, 50); 
  CylonBounce(0, 0xff, 0xff, 2, 40, 50); 
  CylonBounce(0xff, 0, 0xff, 2, 40, 50); 
  CylonBounce(0xff, 0xff, 0xff, 2, 40, 50); 
  //Random color Cyclone loop//  
  for(int i = 0; i < 8; i++) {
    CylonBounce(random(0,255),random(0,255),random(0,255),2,40,50); 
  }
  //Twinkle LED//
  Twinkle(0xff, 0, 0, 10, 100, false);
  Twinkle(0, 0xff, 0, 10, 100, false);
  Twinkle(0, 0, 0xff, 10, 100, false);
  Twinkle(0xff, 0xff, 0, 10, 100, false);
  Twinkle(0, 0xff, 0xff, 10, 100, false);
  Twinkle(0xff, 0, 0xff, 10, 100, false);
  Twinkle(0xff, 0xff, 0xff, 10, 100, false);
  for(int i = 0; i < 8; i++) {
    TwinkleRandom(20, 100, false);
  }  
  //Random Sparkle//
   for(int i = 0; i < 10000; i++) {
     RandomSparkle(0);
   }
  //Running lights//
  RunningLights(0xff,0,0, 50); 
  RunningLights(0,0xff,0, 50); 
  RunningLights(0,0,0xff, 50); 
  RunningLights(0xff,0xff,0, 50); 
  RunningLights(0,0xff,0xff, 50); 
  RunningLights(0xff,0,0xff, 50); 
  RunningLights(0xff,0xff,0xff, 50); 
  //Wiping colors//
  colorWipe(0xff,0,0, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0,0xff,0, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0,0,0xff, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0xff,0xff,0, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0,0xff,0xff, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0xff,0,0xff, 50);
  colorWipe(0,0,0, 50);
  colorWipe(0xff,0xff,0xff, 50);
  colorWipe(0,0,0, 50);
  //Rainbow light//
  rainbowCycle(20);
  //Theatre lights//
  theaterChase(0xff,0,0,50);
  theaterChase(0,0xff,0,50);
  theaterChase(0,0,0xff,50);
  theaterChase(0xff,0xff,0,50);
  theaterChase(0,0xff,0xff,50);
  theaterChase(0xff,0,0xff,50);
  theaterChase(0xff,0xff,0xff,50);
  reverseTheaterChase(0xff,0,0,50);
  reverseTheaterChase(0,0xff,0,50);
  reverseTheaterChase(0,0,0xff,50);
  reverseTheaterChase(0xff,0xff,0,50);
  reverseTheaterChase(0,0xff,0xff,50);
  reverseTheaterChase(0xff,0,0xff,50);
  reverseTheaterChase(0xff,0xff,0xff,50);
  //Rainbow theatre light//
 theaterChaseRainbow(50);
  //Meteor rain light//
  meteorRain(0xff,0,0,10, 120, true, 50);
  meteorRain(0,0xff,0,10, 120, true, 50);
  meteorRain(0,0,0xff,10, 120, true, 50);
  meteorRain(0xff,0xff,0,10, 120, true, 50);
  meteorRain(0,0xff,0xff,10, 120, true, 50);
  meteorRain(0xff,0,0xff,10, 120, true, 50);
  meteorRain(0xff,0xff,0xff,10, 120, true, 50);
  
}


void colorTableFadeLoop() {
  for(int j = 0; j < 7; j++ ) {
    // Fade IN
    fade(j, 0, 255, 1);
    // Fade OUT
    fade(j, 255, 0, -1);
  }
}
void fade(int j, int start, int end, int step) {
  for(int k = start; k != end; k += step) {
    setColor(j, k);
    showStrip();
    delay(3);
  }
}
void setColor(int j, int k) {
  switch(j) {
    case 0: setAll(k,0,0); break;
    case 1: setAll(0,k,0); break;
    case 2: setAll(0,0,k); break;
    case 3: setAll(k,k,0); break;
    case 4: setAll(0,k,k); break;
    case 5: setAll(k,0,k); break;
    case 6: setAll(k,k,k); break;
  }
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause){
  for(int j = 0; j < StrobeCount; j++) {
    setAll(red,green,blue);
    showStrip();
    delay(FlashDelay);
    setAll(0,0,0);
    showStrip();
    delay(FlashDelay);
  }
 
 delay(EndPause);
}

void colorTableStrobe() {
  // Define an array of color values
  uint8_t colors[7][3] = {
    {0xff, 0x00, 0x00},
    {0x00, 0xff, 0x00},
    {0x00, 0x00, 0xff},
    {0xff, 0xff, 0x00},
    {0x00, 0xff, 0xff},
    {0xff, 0x00, 0xff},
    {0xff, 0xff, 0xff}
  };

  // Loop through the array and call Strobe with each color
  for(int i = 0; i < sizeof(colors)/sizeof(colors[0]); i++) {
    Strobe(colors[i][0], colors[i][1], colors[i][2], 8, 50, 100);
    Strobe(colors[i][0], colors[i][1], colors[i][2], 4, 200, 100);
  }
}



void colorTableBlinkLoop() {
  // Define an array of color values
  uint8_t colors[7][3] = {
    {0xff, 0x00, 0x00},
    {0x00, 0xff, 0x00},
    {0x00, 0x00, 0xff},
    {0xff, 0xff, 0x00},
    {0x00, 0xff, 0xff},
    {0xff, 0x00, 0xff},
    {0xff, 0xff, 0xff}
  };

  // Loop through the array and call setAll with each color
  for(int i = 0; i < 7; i++) {
    setAll(colors[i][0], colors[i][1], colors[i][2]);
    delay(500);
  }
}

void HalloweenEyes(byte red, byte green, byte blue,
                   int EyeWidth, int EyeSpace,
                   boolean Fade, int Steps, int FadeDelay,
                   int EndPause){
  
 
  int i;
  int StartPoint  = random( 0, NUM_LEDS - (EyeWidth) - EyeSpace);
  int Start2ndEye = StartPoint + EyeWidth + EyeSpace;
 
  for(i = 0; i < EyeWidth; i++) {
    setPixel(StartPoint + i, red, green, blue);
    setPixel(Start2ndEye + i, red, green, blue);
  }
 
  showStrip();
 
  if(Fade==true) {
    float r, g, b;
 
    for(int j = Steps; j >= 0; j--) {
      r = j*(red/Steps);
      g = j*(green/Steps);
      b = j*(blue/Steps);
     
      for(i = 0; i < EyeWidth; i++) {
        setPixel(StartPoint + i, r, g, b);
        setPixel(Start2ndEye + i, r, g, b);
      }
     
      showStrip();
      delay(FadeDelay);
    }
  }
 
  setAll(0,0,0); // Set all black
 
  delay(EndPause);
}

void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){

  for(int i = -1; i < NUM_LEDS-EyeSize; i++) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
  for(int i = NUM_LEDS-EyeSize; i > 0; i--) {
    setAll(0,0,0);
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    }
    setPixel(i+EyeSize+1, red/10, green/10, blue/10);
    showStrip();
    delay(SpeedDelay);
  } 
  delay(ReturnDelay);
}

void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),red,green,blue);
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) {
  setAll(0,0,0);
 
  for (int i=0; i<Count; i++) {
     setPixel(random(NUM_LEDS),random(0,255),random(0,255),random(0,255));
     showStrip();
     delay(SpeedDelay);
     if(OnlyOne) {
       setAll(0,0,0);
     }
   }
 
  delay(SpeedDelay);
}

void RandomSparkle(int SpeedDelay) {
  int Pixel = random(NUM_LEDS);
  setPixel(Pixel,random(0,255),random(0,255),random(0,255));
  showStrip();
  delay(SpeedDelay);
  setPixel(Pixel,0,0,0);
}

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
  int Position=0;
 
  for(int j=0; j<NUM_LEDS*2; j++)
  {
      Position--; // = 0; //Position + Rate;
      for(int i=0; i<NUM_LEDS; i++) {
        // sine wave, 3 offset waves make a rainbow!
        //float level = sin(i+Position) * 127 + 128;
        //setPixel(i,level,0,0);
        //float level = sin(i+Position) * 127 + 128;
        setPixel(i,((sin(i+Position) * 127 + 128)/255)*red,
                   ((sin(i+Position) * 127 + 128)/255)*green,
                   ((sin(i+Position) * 127 + 128)/255)*blue);
      }
     
      showStrip();
      delay(WaveDelay);
  }
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
  for(uint16_t i=0; i<NUM_LEDS; i++) {
      setPixel(i, red, green, blue);
      showStrip();
      delay(SpeedDelay);
  }
}

void rainbowCycle(int SpeedDelay) {
  byte *c;
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< NUM_LEDS; i++) {
      c=Wheel(((i * 256 / NUM_LEDS) + j) & 255);
      setPixel(i, *c, *(c+1), *(c+2));
    }
    showStrip();
    delay(SpeedDelay);
  }
}

byte * Wheel(byte WheelPos) {
  static byte c[3];
 
  if(WheelPos < 85) {
   c[0]=WheelPos * 3;
   c[1]=255 - WheelPos * 3;
   c[2]=0;
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   c[0]=255 - WheelPos * 3;
   c[1]=0;
   c[2]=WheelPos * 3;
  } else {
   WheelPos -= 170;
   c[0]=0;
   c[1]=WheelPos * 3;
   c[2]=255 - WheelPos * 3;
  }

  return c;
}

void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, red, green, blue);    //turn every third pixel on
      }
      showStrip();
     
      delay(SpeedDelay);
     
      for (int i=0; i < NUM_LEDS; i=i+3) {
        setPixel(i+q, 0,0,0);        //turn every third pixel off
      }
    }
  }
}

void reverseTheaterChase(byte red, byte green, byte blue, int SpeedDelay) {
  for (int j=0; j<10; j++) {  //do 10 cycles of chasing
    for (int q=0; q < 3; q++) {
      for (int i=NUM_LEDS-1; i >= 0; i=i-3) {
        setPixel(i-q, red, green, blue);    //turn every third pixel on
      }
      showStrip();
     
      delay(SpeedDelay);
     
      for (int i=NUM_LEDS-1; i >= 0; i=i-3) {
        setPixel(i-q, 0,0,0);        //turn every third pixel off
      }
    }
  }
}

void theaterChaseRainbow(int SpeedDelay) {
  byte *c;
 
  for (int j=0; j < 256; j=j+2) {     // cycle all 256 colors in the wheel
    for (int q=0; q < 3; q++) {
        for (int i=0; i < NUM_LEDS; i=i+3) {
          c = Wheel( (i+j) % 255);
          setPixel(i+q, *c, *(c+1), *(c+2));    //turn every third pixel on
        }
        showStrip();
       
        delay(SpeedDelay);
       
        for (int i=0; i < NUM_LEDS; i=i+3) {
          setPixel(i+q, 0,0,0);        //turn every third pixel off
        }
    }
  }
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) {  
  setAll(0,0,0);
 
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {
   
   
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );        
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      }
    }
   
    showStrip();
    delay(SpeedDelay);
  }
}

void fadeToBlack(int ledNo, byte fadeValue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
    // NeoPixel
    uint32_t oldColor;
    uint8_t r, g, b;
    int value;
   
    oldColor = strip.getPixelColor(ledNo);
    r = (oldColor & 0x00ff0000UL) >> 16;
    g = (oldColor & 0x0000ff00UL) >> 8;
    b = (oldColor & 0x000000ffUL);

    r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
    g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
    b=(b<=10)? 0 : (int) b-(b*fadeValue/256);
   
    strip.setPixelColor(ledNo, r,g,b);
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[ledNo].fadeToBlackBy( fadeValue );
 #endif  
}

void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}

void setPixel(int Pixel, byte red, byte green, byte blue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.setPixelColor(Pixel, strip.Color(red, green, blue));
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[Pixel].r = red;
   leds[Pixel].g = green;
   leds[Pixel].b = blue;
 #endif
}

void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
rgb1:VDD
rgb1:DOUT
rgb1:VSS
rgb1:DIN
rgb2:VDD
rgb2:DOUT
rgb2:VSS
rgb2:DIN
rgb3:VDD
rgb3:DOUT
rgb3:VSS
rgb3:DIN
rgb4:VDD
rgb4:DOUT
rgb4:VSS
rgb4:DIN
rgb5:VDD
rgb5:DOUT
rgb5:VSS
rgb5:DIN
rgb6:VDD
rgb6:DOUT
rgb6:VSS
rgb6:DIN
rgb7:VDD
rgb7:DOUT
rgb7:VSS
rgb7:DIN
rgb8:VDD
rgb8:DOUT
rgb8:VSS
rgb8:DIN
rgb9:VDD
rgb9:DOUT
rgb9:VSS
rgb9:DIN
rgb10:VDD
rgb10:DOUT
rgb10:VSS
rgb10:DIN
rgb11:VDD
rgb11:DOUT
rgb11:VSS
rgb11:DIN
rgb12:VDD
rgb12:DOUT
rgb12:VSS
rgb12:DIN
rgb13:VDD
rgb13:DOUT
rgb13:VSS
rgb13:DIN
rgb14:VDD
rgb14:DOUT
rgb14:VSS
rgb14:DIN
rgb15:VDD
rgb15:DOUT
rgb15:VSS
rgb15:DIN
rgb16:VDD
rgb16:DOUT
rgb16:VSS
rgb16:DIN
ring1:GND
ring1:VCC
ring1:DIN
ring1:DOUT