/*
  You will need to connect 5V/Gnd from the Arduino (USB power seems to be sufficient).
  
  For the data pins, please pay attention to the arrow printed on the strip. You will need to connect to
  the end that is the begining of the arrows (data connection)--->
  
  If you have a 4-pin connection:
  Blue = 5V
  Red = SDI
  Green = CKI
  Black = GND
 */

int SDI = 3; //Red wire (not the red 5V wire!)
int CKI = 2; //Green wire
int ledPin = 63; //On board LED

#define STRIP_LENGTH 64 //32 LEDs on this strip
long strip_colors[STRIP_LENGTH];

void setup() {
  pinMode(SDI, OUTPUT);
  pinMode(CKI, OUTPUT);
  pinMode(ledPin, OUTPUT);
  
  //Clear out the array
  for(int x = 0 ; x < STRIP_LENGTH ; x++)
    strip_colors[x] = 0;
   post_frame(); //Push the current color frame to the strip
  delay(1000);
}

void loop() {
  while(1){ //Do nothing
  int j = random(0,6);
  if (j==0) {
     simple0();
  }
  if (j==1) {
     simple1();
  }
  if (j==2) {
     simple2();
  }
  if (j==3) {
     simple3();
  }
  if (j>=4) {
    simple4();
  }
 }
}

void simple0(void){
 for(int num2=0;num2<63;num2++) {
   strip_colors[62] = 0x00C8FF;
         
   for(int i=62; i>num2; i--) 
   {
     strip_colors[i-1] = strip_colors[i];
     strip_colors[i]=0; 
     for(int j=0;j<num2;j++) {
       strip_colors[j] = 0x00C8FF;
     } 
     post_frame(); //Push the current color frame to the strip
    delayMicroseconds(500);
   }
  }

for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
}

void simple1(void){
  for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0xFF0000;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0xFFFF00;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0x00FF00;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
    
for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0x00FFFF;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0x0000FF;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
 
for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
}

void simple2(void){
 strip_colors[0] = 0xFF0000;
 for(int num2=0;num2<62;num2++) {
   strip_colors[num2+1] = strip_colors[num2];
   strip_colors[num2] = 0;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }

  strip_colors[62] = 0x0000FF;
  for(int num2=62;num2>0;num2--) {
   strip_colors[num2-1] = strip_colors[num2];
    strip_colors[num2] = 0;
    post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }

}

void simple3(void){
for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0xFF0000;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0xFFFF00;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0x00FF00;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
    
for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0x00FFFF;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
  
for(int num2=0;num2<63;num2++) {
   strip_colors[num2] = 0x0000FF;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }

for(int num2=62;num2>=0;num2--) {
   strip_colors[num2] = 0;
     post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
}

void simple4(void){
for(int num2=0;num2<500;num2++) {
  int i = random(0,62);
  int j = random(0,5);
  if (j==0) {
   strip_colors[i] = 0x0000FF;
  }
  if (j==1) {
   strip_colors[i] = 0x00FFFF;
  }
  if (j==2) {
   strip_colors[i] = 0x00FF00;
  }
  if (j==3) {
   strip_colors[i] = 0xFFFF00;
  }
  if (j==4) {
   strip_colors[i] = 0xFF0000;
  }
    post_frame(); //Push the current color frame to the strip
    delay(2);                  // wait for a second
  }
}

//Throws random colors down the strip array
void addRandom(void) {
  int x;
  
  //First, shuffle all the current colors down one spot on the strip
  for(x = (STRIP_LENGTH - 1) ; x > 0 ; x--)
    strip_colors[x] = strip_colors[x - 1];
    
  //Now form a new RGB color
  long new_color = 0;
  for(x = 0 ; x < 3 ; x++){
    new_color <<= 8;
    new_color |= random(0xFF); //Give me a number from 0 to 0xFF
    //new_color &= 0xFFFFF0; //Force the random number to just the upper brightness levels. It sort of works.
  }
  
  strip_colors[0] = new_color; //Add the new random color to the strip
}

//Takes the current strip color array and pushes it out
void post_frame (void) {

  for(int LED_number = 0 ; LED_number < STRIP_LENGTH ; LED_number++) {
    long this_led_color = strip_colors[LED_number]; //24 bits of color data

    for(byte color_bit = 23 ; color_bit != 255 ; color_bit--) {
      //Feed color bit 23 first (red data MSB)
      
      digitalWrite(CKI, LOW); //Only change data when clock is low
      
      long mask = 1L << color_bit;
      //The 1'L' forces the 1 to start as a 32 bit number, otherwise it defaults to 16-bit.
      
      if(this_led_color & mask) 
        digitalWrite(SDI, HIGH);
      else
        digitalWrite(SDI, LOW);
      delay(5);
      digitalWrite(CKI, HIGH); //Data is latched when clock goes high
    }
  }

  //Pull clock low to put strip into reset/post mode
  digitalWrite(CKI, LOW);
  delayMicroseconds(500); //Wait for 500us to go into reset
}
