/*
    Basic Pin setup:
    ------------                                  ---u----
    ARDUINO   13|-> SCLK (pin 25)           OUT1 |1     28| OUT channel 0
              12|                           OUT2 |2     27|-> GND (VPRG)
              11|-> SIN (pin 26)            OUT3 |3     26|-> SIN (pin 11)
              10|-> BLANK (pin 23)          OUT4 |4     25|-> SCLK (pin 13)
               9|-> XLAT (pin 24)             .  |5     24|-> XLAT (pin 9)
               8|                             .  |6     23|-> BLANK (pin 10)
               7|                             .  |7     22|-> GND
               6|                             .  |8     21|-> VCC (+5V)
               5|                             .  |9     20|-> 2K Resistor -> GND
               4|                             .  |10    19|-> +5V (DCPRG)
               3|-> GSCLK (pin 18)            .  |11    18|-> GSCLK (pin 3)
               2|                             .  |12    17|-> SOUT
               1|                             .  |13    16|-> XERR
               0|                           OUT14|14    15| OUT channel 15
    ------------                                  --------

    -  Put the longer leg (anode) of the LEDs in the +5V and the shorter leg
         (cathode) in OUT(0-15).
    -  +5V from Arduino -> TLC pin 21 and 19     (VCC and DCPRG)
    -  GND from Arduino -> TLC pin 22 and 27     (GND and VPRG)
    -  digital 3        -> TLC pin 18            (GSCLK)
    -  digital 9        -> TLC pin 24            (XLAT)
    -  digital 10       -> TLC pin 23            (BLANK)
    -  digital 11       -> TLC pin 26            (SIN)
    -  digital 13       -> TLC pin 25            (SCLK)
    -  The 2K resistor between TLC pin 20 and GND will let ~20mA through each
       LED.  To be precise, it's I = 39.06 / R (in ohms).  This doesn't depend
       on the LED driving voltage.
    - (Optional): put a pull-up resistor (~10k) between +5V and BLANK so that
                  all the LEDs will turn off when the Arduino is reset.

    If you are daisy-chaining more than one TLC, connect the SOUT of the first
    TLC to the SIN of the next.  All the other pins should just be connected
    together:
        BLANK on Arduino -> BLANK of TLC1 -> BLANK of TLC2 -> ...
        XLAT on Arduino  -> XLAT of TLC1  -> XLAT of TLC2  -> ...
    The one exception is that each TLC needs it's own resistor between pin 20
    and GND.

    This library uses the PWM output ability of digital pins 3, 9, 10, and 11.
    Do not use analogWrite(...) on these pins.

    This sketch does the Knight Rider strobe across a line of LEDs.

    Alex Leone <acleone ~AT~ gmail.com>, 2009-02-03 */

// Include the library
#include <Tlc5940.h>
int thermistor = A0;
int gate = 5;
int thermistorValue = 0;
int gateValue = 0;
byte action;
int j;
int LEDs[60] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
                17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,
                33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
                49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
                
void setup() {
    // Initialize
    Serial1.begin(115200);
    randomSeed(analogRead(1));
    Tlc.init();
    Tlc.clear();
    Tlc.update();
    delay(20); 
}

//ascii a = 97, b = 98, c = 99, f = 102, m = 109
void loop() {
  
  thermistorValue = analogRead(thermistor);
  gateValue = map(thermistorValue, 520, 600, 128, 255);
  if(gateValue<=128){gateValue = 128;}
  if(gateValue>=255){gateValue = 255;}
  analogWrite(gate,gateValue);

   
  if (Serial1.available() > 0) {
    // read the incoming byte:
    action = Serial1.read();
  }
  //player indicators
  if(action=='0'){
    Tlc.clear();
    Tlc.update();
    delay(20);
   }
  if(action=='1'){
    Tlc.set(0,1500);
    Tlc.set(16,0);
    Tlc.set(32,0);
    Tlc.set(48,0);
    Tlc.update();
    delay(20);
   }
   if(action=='2'){
    Tlc.set(0,0);
    Tlc.set(16,1500);
    Tlc.set(32,0);
    Tlc.set(48,0);
    Tlc.update();
    delay(20);
   }
   if(action=='3'){
    Tlc.set(0,0);
    Tlc.set(16,0);
    Tlc.set(32,1500);
    Tlc.set(48,0);
    Tlc.update();
    delay(20);
   }
   if(action=='4'){
    Tlc.set(0,0);
    Tlc.set(16,0);
    Tlc.set(32,0);
    Tlc.set(48,1500);
    Tlc.update();
    delay(20);
   }
   
  //LED Effects
  if(action == 'a'){
    Melee(1500);
    action = -1;
  }
  if(action == 'b'){
    Bow(1500,200);
    action = -1;
  }
  if(action == 'c'){
    delay(1000);
    Magic(1500,10);
    action = -1;
  }
  if(action == 'f'){
    delay(1300);
    Fire(1000);
    action = -1;
  }
  if(action == 'm'){
    delay(500);
    mm(2000);
    action = -1;
  }
  if(action == 'i'){
    delay(500);
    Ice(500);
    action = -1;
  }
  if(action == 'e'){
    delay(500);
    Electric(1000);
    action = -1;
  }
  if(action == 'p'){
    delay(500);
    Poison();
    action = -1;
  }
  
  
  //Clear LEDs except for player indicators
  for(j = 0; j<60; j++){
    Tlc.set(LEDs[j],0);
  }
  Tlc.update();
  delay(40);
}

void Melee(int pwm){
  int k;
  //Alternating white flashes on RGB LEDs
  //1 2 3,7  8  9, 13 14 15,20 21 22,26 27 28,33 34 35,39 40 41,45 46 47,52 53 54,58 59 60
  //4 5 6,10 11 12,17 18 19,23 24 25,29 30 31,36 37 38,42 43 44,49 50 51,55 56 57,61 62 63
  int LEDS1[18] = {1, 2, 3, 7, 8, 9, 13, 14, 15, 33, 34, 35, 39, 40, 41, 45, 46, 47};
  int LEDS2[18] = {17, 18, 19, 23, 24, 25, 29, 30, 31, 49, 50, 51, 55, 56, 57, 61, 62, 63};
  delay(400);
  
  for(k = 0; k<18; k++){
    Tlc.set(LEDS1[k],pwm/2);
  }
  Tlc.update();
  delay(300);

  for(k = 0; k<60; k++){
    Tlc.set(LEDs[k],0);
  }
  Tlc.update();
  delay(20);

  for(k = 0; k<18; k++){
    Tlc.set(LEDS2[k],pwm/2);
  }
  Tlc.update();
  delay(300);

  for(k = 0; k<60; k++){
    Tlc.set(LEDs[k],0);
  }
  Tlc.update();
  delay(20);

  for(k = 0; k<18; k++){
    Tlc.set(LEDS1[k],pwm);
  }
  Tlc.update();
  delay(300);
  

  for(k = 0; k<60; k++){
    Tlc.set(LEDs[k],0);
  }
  Tlc.update();
  delay(20);

  for(k = 0; k<18; k++){
    Tlc.set(LEDS2[k],pwm);
  }
  Tlc.update();
  delay(400);

  for(k = 0; k<60; k++){
    Tlc.set(LEDs[k],0);
  }
  Tlc.update();
  delay(20);
}

//(max pwm, increment(for adjusting speed))
//Magic: fade blue LEDs in and out.
void Magic(int pwm, int inc){
//Fade to max
    int level;
    for(level = 0; level < (pwm/2); level = level + inc){
      
      //Chip 1
      for (int i = 3; i < 16; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 2
      for (int i = 19; i < 32; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 3
      for (int i = 35; i < 48; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 4
      for (int i = 51; i < 64; i=i+3) {
          Tlc.set(i, level);
      }
      //Send out the data
      Tlc.update();
      //adjust speed
      delay(10);
    }
        for(level = (pwm/2); level < pwm; level = level + (inc*2)){
      
      //Chip 1
      for (int i = 3; i < 16; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 2
      for (int i = 19; i < 32; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 3
      for (int i = 35; i < 48; i=i+3) {
          Tlc.set(i, level);
      }
      //Chip 4
      for (int i = 51; i < 64; i=i+3) {
          Tlc.set(i, level);
      }
      //Send out the data
      Tlc.update();
      //adjust speed
      delay(10);
    }
    //Fade to 0
    for(level = pwm; level>=0;level=level-(inc*2)){
      //chip 1
      for (int i = 3; i < 16; i=i+3) {
          Tlc.set(i, level);
      }
      //chip 2
      for (int i = 19; i < 32; i=i+3) {
          Tlc.set(i, level);
      }
      //chip 3
      for (int i = 35; i < 48; i=i+3) {
          Tlc.set(i, level);
      }
      //chip 4
      for (int i = 51; i < 64; i=i+3) {
          Tlc.set(i, level);
      }
      Tlc.update();
      //Send out the data
      delay(10);
      //adjust speed
    }
}

void Bow(int pwm,int wait){
  //Bow Draw
  //Green
  //18 <- 21 <- 24 -> 27 ->30
  //50 <- 53 <- 56 -> 59 -> 62
  Tlc.set(24,pwm);
  Tlc.set(56,pwm);
  Tlc.update();
  delay(wait);
  Tlc.set(21,pwm);
  Tlc.set(27,pwm);
  Tlc.set(53,pwm);
  Tlc.set(59,pwm);
  Tlc.update();
  delay(wait);
  Tlc.set(18,pwm);
  Tlc.set(30,pwm);
  Tlc.set(50,pwm);
  Tlc.set(62,pwm);
  Tlc.update();
  delay(wait);
  
  //Yellow
  //10,11 <- 13,14  33,34 ->36,37
  //42,43 <- 45,46 1,2 -> 4,5
  Tlc.set(13,pwm);
  Tlc.set(14,pwm);
  Tlc.set(33,pwm);
  Tlc.set(34,pwm);
  Tlc.set(1,pwm);
  Tlc.set(2,pwm);
  Tlc.set(45,pwm);
  Tlc.set(46,pwm);
  Tlc.update();
  delay(wait);
  Tlc.set(10,pwm);
  Tlc.set(11,pwm);
  Tlc.set(36,pwm);
  Tlc.set(37,pwm);
  Tlc.set(4,pwm);
  Tlc.set(5,pwm);
  Tlc.set(42,pwm);
  Tlc.set(43,pwm);
  Tlc.set(7,pwm);
  Tlc.set(39,pwm);
  Tlc.update();
  delay(wait*6);
  
  //Bow Fire
  Tlc.set(7,0);
  Tlc.set(39,0);
  Tlc.update();
  delay(wait/5);
  
  Tlc.set(10,0);
  Tlc.set(11,0);
  Tlc.set(36,0);
  Tlc.set(37,0);
  Tlc.set(4,0);
  Tlc.set(5,0);
  Tlc.set(42,0);
  Tlc.set(43,0);
  Tlc.update();
  delay(wait/5);
  
  Tlc.set(13,0);
  Tlc.set(14,0);
  Tlc.set(33,0);
  Tlc.set(34,0);
  Tlc.set(1,0);
  Tlc.set(2,0);
  Tlc.set(45,0);
  Tlc.set(46,0);
  Tlc.update();
  delay(wait/5);

  Tlc.set(18,0);
  Tlc.set(30,0);
  Tlc.set(50,0);
  Tlc.set(62,0);
  Tlc.update();
  delay(wait/5);
  Tlc.set(21,0);
  Tlc.set(27,0);
  Tlc.set(53,0);
  Tlc.set(59,0);
  Tlc.update();
  delay(wait/5);
  Tlc.set(24,0);
  Tlc.set(56,0);
  Tlc.update();
}

void Fire(int pwm){
  int i,k,brightness;
  unsigned long red,yellow;
  int redLEDs[12] = {1,7,13,17,23,29,33,39,45,49,55,61};
  int greenLEDs[12] = {2,8,14,18,24,30,34,40,46,50,56,62};
  for(k = 0; k<137; k++){
  brightness = random(120);
  red = (random(120)+135)*pwm/255;
  yellow = ((random(120)/2)*pwm)/255;
  for(i=0;i<12;i++){
    Tlc.set(redLEDs[i],red);
    Tlc.set(greenLEDs[i],yellow);
  }
  Tlc.update();
  delay(25);
  }
}

void mm(int pwm){
  int i,k;
  int red1[10]={1,4,7,10,13,17,20,23,26,29};
  int blue1[10]={3,6,9,12,15,19,22,25,28,31};
  int red2[10]={61,58,55,52,49,45,42,39,36,33};
  int blue2[10]={63,60,57,54,51,47,44,41,38,35};
  for(i=0;i<10;i++){
    Tlc.set(red1[i],pwm);
    Tlc.set(blue1[i],pwm);
    Tlc.update();
    delay(40);
    Tlc.set(red1[i],0);
    Tlc.set(blue1[i],0);
  }
  delay(80);
  for(i=0;i<10;i++){
    Tlc.set(red2[i],pwm);
    Tlc.set(blue2[i],pwm);
    Tlc.update();
    delay(40);
    Tlc.set(red2[i],0);
    Tlc.set(blue2[i],0);
  }
  delay(80);
  for(i=0;i<10;i++){
    Tlc.set(red1[i],pwm);
    Tlc.set(blue1[i],pwm);
    Tlc.update();
    delay(40);
    Tlc.set(red1[i],0);
    Tlc.set(blue1[i],0);
  }
    delay(80);
  for(i=0;i<10;i++){
    Tlc.set(red2[i],pwm);
    Tlc.set(blue2[i],pwm);
    Tlc.update();
    delay(40);
    Tlc.set(red2[i],0);
    Tlc.set(blue2[i],0);
  }
}

void Ice(int pwm){
  int level;
  int norepeat = -1;
  int sparkle = 3*random(8);
  int blueLEDs[12] = {3,9,15,19,25,31,35,41,47,51,57,63};
  int whiteLEDs[24] = {4,5,6,10,11,12,20,21,22,26,27,28,36,37,38,42,43,44,52,53,54,58,59,60};
  //pwm = 500, sparkle = 1000
  for(level = 0; level<pwm; level=level+10){
  for(int i = 0; i< 12; i++){Tlc.set(blueLEDs[i],level);}

  if((level%30)==0){
  while(sparkle == norepeat){  
  sparkle = 3*random(8);
  }
  norepeat = sparkle;
  Tlc.set(whiteLEDs[sparkle],level*2);
  Tlc.set(whiteLEDs[sparkle+1],level*2);
  Tlc.set(whiteLEDs[sparkle+2],level*2);
  }
  Tlc.update();
  delay(40);
  Tlc.set(whiteLEDs[sparkle],0);
  Tlc.set(whiteLEDs[sparkle+1],0);
  Tlc.set(whiteLEDs[sparkle+2],0);
  }
  for(level = pwm; level>=0; level=level-10){
  for(int i = 0; i< 12; i++){Tlc.set(blueLEDs[i],level);}
  
  if((level%30)==0){
  while(sparkle == norepeat){  
  sparkle = 3*random(8);
  }
  norepeat = sparkle;
  Tlc.set(whiteLEDs[sparkle],level*2);
  Tlc.set(whiteLEDs[sparkle+1],level*2);
  Tlc.set(whiteLEDs[sparkle+2],level*2);
  }
  Tlc.update();
  delay(40);
  Tlc.set(whiteLEDs[sparkle],0);
  Tlc.set(whiteLEDs[sparkle+1],0);
  Tlc.set(whiteLEDs[sparkle+2],0);
  }
}

void Electric(int pwm){
  int level;
  int norepeat = -1;
  int sparkle = 3*random(8);
  int yellowLEDs[16] = {1,2,7,8,17,18,23,24,33,34,39,40,49,50,55,56};
  int whiteLEDs[24] = {4,5,6,10,11,12,20,21,22,26,27,28,36,37,38,42,43,44,52,53,54,58,59,60};
  //pwm = 500, sparkle = 1000
  for(level = 0; level<pwm; level=level+10){
  for(int i = 0; i< 16; i++){Tlc.set(yellowLEDs[i],pwm);}
  if((level%20)==0){
  while(sparkle == norepeat){  
  sparkle = 3*random(8);
  }
  norepeat = sparkle;
  Tlc.set(whiteLEDs[sparkle],pwm*2);
  Tlc.set(whiteLEDs[sparkle+1],pwm*2);
  Tlc.set(whiteLEDs[sparkle+2],pwm*2);
  }
  Tlc.update();
  delay(28);
  Tlc.set(whiteLEDs[sparkle],0);
  Tlc.set(whiteLEDs[sparkle+1],0);
  Tlc.set(whiteLEDs[sparkle+2],0);
  }
}
void Poison(){
  int level;
  int x = 0;
  int y1 = 7;
  int y2 = 17;
  //moving green Leds fade in. start at center of left and right sides. stop at center of top and bottom sides.
  int greenLEDs[20] = {2,5,8,11,14,18,21,24,27,30,34,37,40,43,46,50,53,56,59,62};
  while(x<7){
  
  for(level = 20; level <= 1200; level = level + 20){
  if(x<6){
    Tlc.set(greenLEDs[(y1-x)%20],level);
    Tlc.set(greenLEDs[(y1+x)%20],level);
    Tlc.set(greenLEDs[(y2-x)%20],level);
    Tlc.set(greenLEDs[(y2+x)%20],level);
    if(x>=2){
      Tlc.set(greenLEDs[(y1-x+2)%20],0);
      Tlc.set(greenLEDs[(y1+x-2)%20],0);
      Tlc.set(greenLEDs[(y2-x+2)%20],0);
      Tlc.set(greenLEDs[(y2+x-2)%20],0);
    }
  }
  if(x>=6){
    Tlc.set(greenLEDs[2],level);
    Tlc.set(greenLEDs[12],level);
    Tlc.set(greenLEDs[1],0);
    Tlc.set(greenLEDs[11],0);
    Tlc.set(greenLEDs[3],0);
    Tlc.set(greenLEDs[13],0);
  }
  Tlc.update();
  delay(22);
  if((level%400) == 0){
  x++;
  }
  }

  for(level = 1580; level >= 0; level = level - 20){
  if(x<6){
    Tlc.set(greenLEDs[(y1-x)%20],level);
    Tlc.set(greenLEDs[(y1+x)%20],level);
    Tlc.set(greenLEDs[(y2-x)%20],level);
    Tlc.set(greenLEDs[(y2+x)%20],level);
    if(x>=2){
      Tlc.set(greenLEDs[(y1-x+2)%20],0);
      Tlc.set(greenLEDs[(y1+x-2)%20],0);
      Tlc.set(greenLEDs[(y2-x+2)%20],0);
      Tlc.set(greenLEDs[(y2+x-2)%20],0);
    }
  }
  if(x>=6){
    Tlc.set(greenLEDs[2],level);
    Tlc.set(greenLEDs[12],level);
    Tlc.set(greenLEDs[1],0);
    Tlc.set(greenLEDs[11],0);
    Tlc.set(greenLEDs[3],0);
    Tlc.set(greenLEDs[13],0);
  }
  Tlc.update();
  delay(22);
  if((level%400) == 0){
  x++;
  }
  }
  
  }
  }

//0  1   2   3
//0 400 800 1200
//
