/*
This program is to control multiple LEDs, to bring some fancy effects to a Imperial Raider

The core idea is:

BlinkLed 1 - 3: run a fiber optic to these leds, and connect these to the sides of the raider, to allow these lights to twinkle/fade
SolidLed1: this is for a cockpit LED, can either be a sold "on" led, or can use a flicker LED to make this animated
LaserLed1: connect fiberoptics from here to each gun, this will have a tripple fire effect on button press
FadeLed: this is for the engines, and will cause the engines to fade on and off

Use 100 (2.0v forward) - 130 (2.2v forward) ohm resistors with this setup to avoid burning out the LEDs

*/

// these constant won't change



const uint8_t blinkLed1 = 3; //set Pin D3 to "blinkLed1" (side lights 1) (PWM Pin)
const uint8_t blinkLed2 = 5; //set Pin D5 to "blinkLed2" (side lights 2) (PWM Pin)
const uint8_t blinkLed3 = 6; //set Pin D6 to "blinkLed3" (side lights 3) (PWM Pin)
const uint8_t solidLed1 = 8; //set Pin D8 to "solidLed3" (cockpit)
const uint8_t laserLed1 = 9; //Set Pin D9 to "laserLED1" (guns)  (PWM Pin)
const uint8_t throbPin1 = 10; //Set Pin D9 to "laserLED1" (guns)  (PWM Pin)
const uint8_t throbPin2 = 11; //Set Pin D9 to "laserLED1" (guns)  (PWM Pin)

//Note almoast all PWM pins are in use (3,5,6,9,10,11), Three via's are availble for engine lights, to allow up to 4 engines to be lit. Due to 40ma limit on PWM pins, i have set pin 10 and 11 to mirror each other, to maximize number of availble engine LEDs


//Brightness Variables
uint8_t brightnessLaser = constrain(brightnessLaser, 0, 255); //sets brightness of the laser to 0-255, ensuring value doesnt exceed this.
uint8_t brightnessBlinkLed1 = constrain(brightnessBlinkLed1, 0, 255); //Constrains BrightnessBlinkLed1 between 100 and 255
uint8_t brightnessBlinkLed2 = constrain(brightnessBlinkLed2, 0, 255); //Constrains BrightnessBlinkLed2 between 100 and 255
uint8_t brightnessBlinkLed3 = constrain(brightnessBlinkLed3, 0, 255); //Constrains BrightnessBlinkLed3 between 100 and 255


//fade speeds
float laserFade = 0.9; // set multiplyer for fade speed for laser Leds
uint8_t blinkFade = 5; // set fade speed for side Leds
uint8_t randomWidth = 150;//sets width of "random" function, to allow easy adjustments

//button Counter
const uint8_t  buttonPin = 2;    // the pin that the pushbutton is attached to
uint8_t buttonCounter = 0;   // counter for the number of button presses
byte buttonState = LOW;         // current state of the button
byte lastButtonState = LOW;     // previous state of the button
unsigned long nextReadMillis = 0; //used in the debounce

//LED variables used for blinking
uint8_t blinkLed1Random = 0; //Random Value for LED 1
uint8_t blinkLed2Random = 0; //Random Value for LED 2
uint8_t blinkLed3Random = 0; //Random Value for LED 3
byte blinkLed1Value = 1; //Sets if LED is increasing or decreasing
byte blinkLed2Value = 1; //Sets if LED is increasing or decreasing
byte blinkLed3Value = 1; //Sets if LED is increasing or decreasing

//debounce time
#define debounceTime 800

//this is for the sine wave generator for the engine throb
float timeStep = 0; //multiplied against the sine equation
uint8_t throb = 0; //variable written to from the sine equation, used to power engines



void setup() {

   //Serial.begin(115200);//used for debugging, comment out
    // LED setup
    pinMode(solidLed1, OUTPUT); //pin "solidLed1" is output
    pinMode(laserLed1, OUTPUT); //pin "laserLed1" is output
    
    randomSeed(analogRead(0)); //makes the Random() function truly random
    
    //Button Setup
      // initialize the button pin as a input:
    pinMode(buttonPin, INPUT);

  
    pinMode(blinkLed1, OUTPUT); //pin "blinkLed1" is output
    pinMode(blinkLed2, OUTPUT); //pin "blinkLed2" is output
    pinMode(blinkLed3, OUTPUT); //pin "blinkLed3" is output

    
    //randomSeed(analogRead(0)); //makes the Random() function truly random
    randomSeed(analogRead(0));

    //this is for the sine wave engine throb
    pinMode(10, OUTPUT);
    pinMode(11, OUTPUT);
    
  }

  void loop() {
        
//This is for the "firing laser" effect, and the always LED for the cockpit      
    //Pin 9 
    ///sets cockpit LED to on. Use a flickering LED here
    digitalWrite(solidLed1, HIGH); //Turns on solid LED
    
    unsigned long newMillis = millis();
    
    //Sets turbloaser control here. The following code was copied
    //button debounce counter
    if (newMillis >= nextReadMillis) {

    // compare the buttonState to its previous state
    
    
    buttonState = digitalRead(buttonPin);
    if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (buttonState == HIGH) {
      // if the current state is HIGH then the button went from off to on:
      nextReadMillis = newMillis + debounceTime;
      buttonCounter++;
            
    } 

    lastButtonState = buttonState; // save the current state as the last state, for next time through the loop
    

    }
    }
 

    //laser firing
    //Intetion is three salvos, each time with the brightness fading
    if (buttonCounter == 0){
    brightnessLaser = (0);
    }

    else if (buttonCounter > 0 && buttonCounter <= 9){
    brightnessLaser = (255);
    buttonCounter++;

   }

    else if (buttonCounter >9 && buttonCounter <= 29){
    brightnessLaser = brightnessLaser * laserFade;
    buttonCounter++;
   }

    else if (buttonCounter > 29 && buttonCounter <= 39){
    brightnessLaser = (255);
    buttonCounter++;
   }

    else if (buttonCounter >39 && buttonCounter <= 59){
    brightnessLaser = brightnessLaser * laserFade;
    buttonCounter++;
    }

    else if (buttonCounter > 59 && buttonCounter <= 69){
    brightnessLaser = (255);
    buttonCounter++;
    }

    else if (buttonCounter > 69 && buttonCounter <= 89){
    brightnessLaser = brightnessLaser * laserFade;
    buttonCounter++;
    }

    // This loops the LEDs after the full "animation"
    if (buttonCounter > 89){
    brightnessLaser = (0);
    buttonCounter = (0);

  }
 
    analogWrite(laserLed1, brightnessLaser);
    //Serial.println(brightnessLaser);



//This is for the "twinkle side lights"


    
    //Side LEDs Fade
    analogWrite(blinkLed1, brightnessBlinkLed1);
    analogWrite(blinkLed2, brightnessBlinkLed2);
    analogWrite(blinkLed3, brightnessBlinkLed3);
    
    // Sets three leds to flicker randomly. frequency can be modified here. Logic is it randomizes
    // a number between 0 and 99. 99 makes LED increase, 0 makes it decrease. should flicker LED's once every 3 seconds
   
    blinkLed1Random = random(randomWidth); //Sets blinkLed1Random to a value between 0 & 199
    blinkLed2Random = random(randomWidth); //Sets blinkLed1Random to a value between 0 & 199
    blinkLed3Random = random(randomWidth); //Sets blinkLed1Random to a value between 0 & 199

    

    //This sets whether each LED is increasing or decreasing in brightness
    
    if (blinkLed1Random == 0){
        blinkLed1Value = LOW;
    }

    else if (blinkLed1Random >= 148){
      blinkLed1Value = HIGH;
    }

     if (blinkLed2Random == 0){
        blinkLed2Value = LOW;
    }

    else if (blinkLed2Random >= 148){
      blinkLed2Value = HIGH;
    }

     if (blinkLed3Random == 0){
        blinkLed3Value = LOW;
    }

    else if (blinkLed3Random >= 148){
      blinkLed3Value = HIGH;
    }
    
    


// This code increases and decreases the brightness for each LED independantly
   //LED 1
    if (blinkLed1Value == HIGH && brightnessBlinkLed1 <250){
      brightnessBlinkLed1 = brightnessBlinkLed1 + blinkFade;
    }

    else if (blinkLed1Value == LOW && brightnessBlinkLed1 >100){
      brightnessBlinkLed1 = brightnessBlinkLed1 - blinkFade;
    }
    
    else if (blinkLed1Value == LOW && brightnessBlinkLed1 <=100){
      brightnessBlinkLed1 = 0;
    }

  //LED 2
        if (blinkLed2Value == HIGH && brightnessBlinkLed2 <250){
      brightnessBlinkLed2 = brightnessBlinkLed2 + blinkFade;
    }

    else if (blinkLed2Value == LOW && brightnessBlinkLed2 >100){
      brightnessBlinkLed2 = brightnessBlinkLed2 - blinkFade;
    }
    
    else if (blinkLed2Value == LOW && brightnessBlinkLed2 <=100){
      brightnessBlinkLed2 = 0;
    }

  //LED 3
        if (blinkLed3Value == HIGH && brightnessBlinkLed3 <250){
      brightnessBlinkLed3 = brightnessBlinkLed3 + blinkFade;
    }

    else if (blinkLed3Value == LOW && brightnessBlinkLed3 >100){
      brightnessBlinkLed3 = brightnessBlinkLed3 - blinkFade;
    }
    
    else if (blinkLed3Value == LOW && brightnessBlinkLed3 <=100){
      brightnessBlinkLed3 = 0;
 }



//This is for the sine wave engine throb.

    throb = 127 * sin( 2 * 3.14 * timeStep) + 127; //sine equation, sine * Tau + 127 to avoid negitive numbers
    timeStep = timeStep + 0.01; //used to determine how quickly engines throb, default 0.01 for 3 second pulse.
     analogWrite(throbPin1, throb); //writes throb to engines
     analogWrite(throbPin2, throb); //writes throb to engines
   
    
    
    delay(30); // 30ms cycle
}