//DiceRoll Arduino program 

//total Duration of loop: 660620 ms

// pwm_pins on ~3, ~5, ~6
int pwm_pin_1 = 3;
int pwm_pin_2 = 5;
int pwm_pin_3 = 6;

// inc array to inc, dec, or hold 
int inc[] = {1,-1,0};

//  OFF: 1, 
//  ON:quietTime + Pulses = 120000 + 115620 ms = 235620
//  OFF: dcRamps 
//  ON: QuietTime returns 
//  OFF: blowOUT RAMP

unsigned long setFlagTimes[] = {221960, 320000}; // off (1 ms), on (235620), off 

// event times array to hold durations: duration = rampTime + holdTime (0-->255 takes 10 seconds)


//QUIET time, in 20 second intervals for 2 minutes

unsigned long event_times_1[] = {1, // 23 step increments in 5 seconds
// len(event_times_1) = 149 (with 1)

/////////QuietTime (2 min, 120000 ms)

120000,

/////////Pulses (115 secs, 115620 ms)

10000, 180, 
10000, 180, 
8000, 180,
10000, 180, 
10000, 180,

5000, 180, 2000, 180, 3000, 180, 
5000, 180, 3000, 180, 2000, 180, 
5000, 180, 2000, 180, 3000, 180,
4000, 180, 3000, 180, 1000, 180, 2000, 180,  
4000, 180, 3000, 180, 2000, 180, 1000, 180,
//setflag on
5000, 15000,
//241960 ms

////////// dcRAMPS (turn on setFlagTime), (3.08 min, 185 secs)

10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,
//setflag off
/////quietTime returns (2 min, 120000 ms)
20000, 20000, 20000,
//20000, 20000, 20000,
//
////////////blowOut RAMP (2 min)
//
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000

}; 

unsigned long event_times_2[] = {1,


///quiet Time,
120000,
//////////pulses

10000, 180, 
10000, 180, 
2000, 180, 6000, 
1000, 180, 5000, 180, 3820, 
2000, 180, 4000, 180, 3820,

3000, 180, 2000, 180, 2000, 180, 3000,
8000, 180, 1000, 180, 1000, 180, 
4000, 180, 3000, 180, 3000, 180, 
3000, 180, 2000, 180, 2000, 180, 3000, 180, 
2000, 180, 2000, 180, 2000, 180, 4000, 180,
//swell, setflag off
5000, 15000,
//241960 ms


/////////////dc Ramps
10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,
//        
///////quiet Time returns

20000, 20000, 20000,

///////////blowOUT Ramp 
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000


}; //1, at beginning just starts the process(it's technically a time event, but just a pulse to get it going)

unsigned long event_times_3[] = {1,

///QuietTime
120000,



10000, 180, 
10000, 180,
2000, 180, 6000, 
1000, 180, 3000, 180, 5820,
5000, 180, 3000, 180, 1820, 

2000, 180, 2000, 180, 6000, 180, 
1000, 180, 4000, 180, 5000, 180, 
5000, 180, 2000, 180, 3000, 180,
2000, 180, 1000, 180, 4000, 180, 3000, 180,  
1000, 180, 2000, 180, 3000, 180, 4000, 180,
5000, 15000,
//(dur. 221960)


//////////////dcRamps
//
10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,
10000, 10000, 10000,

//////// quietTime returns 
20000, 20000, 20000,

////////////////blowout ramp
//
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000,
5000, 5000, 5000, 5000, 5000, 5000

//total duration (541960 ms) 

}; 

//target dutyCycle value for each pwm signal to goto 
byte dutyCycleTarget_1[] = 
{

///quietTime
  
  40,
  
/////////pulses
  
  42, 190, 
  42, 180, 
  42, 180,
  42, 200, 
  42, 180,

  42, 180, 42, 180, 42, 180, 
  42, 180, 42, 180, 42, 180, 
  42, 180, 42, 180, 42, 180,
  42, 180, 42, 180, 42, 180, 42, 50,  
  42, 180, 42, 180, 42, 180, 42, 50,
  //swell
  50, 220,
  
// dcRamps
//  
  40, 70, 40,
  50, 80, 50,
  60, 100, 60,
  50, 70, 50,

//////quietTime Returns 
  41, 47, 50,

/////////////blowOut
//
  48, 52, 58, 64, 68, 78, 83, 88, 94,
  99, 100, 105, 110, 115, 118, 125,
  130, 140, 150, 160, 170, 180, 
  190, 208
  
};

byte dutyCycleTarget_2[] = 
{
//quietTime
37,
  
/////////////pulses

45, 45, 
45, 45, 
45, 180, 45, 
45, 180, 45, 180, 45, 
45, 180, 45, 180, 45,

45, 180, 45, 180, 45, 180, 45,
45, 180, 45, 180, 45, 180, 
45, 180, 45, 180, 45, 180, 
45, 180, 45, 180, 45, 180, 45, 180, 
45, 180, 45, 180, 45, 180, 45, 50,
//swell
50, 220,

//45, 180, 45, 180, 45, 180, 45, 180, 45, 180, 45, 320, 180, 45, 45, 180, 180,
//45, 180, 45, 180, 45, 180,

////////////////dcRamps
//
45, 50, 90,
50, 55, 60,
120, 50, 45,
60, 120, 50,
//      
//////quietTime Returns 
//
  42, 45, 48,

//
//
///////////blowOut
//
  45,50, 55, 65, 70, 75, 80, 85, 95, 
  100, 105, 115, 125, 135, 145, 
  155, 165, 175, 185, 195, 
  205, 215, 220, 230

};

byte dutyCycleTarget_3[] = {

 60,
  
//////////
  
70, 70, 
70, 70,
70, 70, 70, 
70, 220, 70, 220, 70,
70, 220, 70, 220, 70, 

70, 220, 70, 220, 70, 220, 
70, 220, 70, 220, 70, 220, 
70, 220, 70, 220, 70, 220,
70, 220, 70, 220, 70, 220, 70, 220,  
70, 220, 70, 220, 70, 220, 70, 100,
//swell
70, 220,


///////////////////////

200, 100, 70,
80, 110, 80,
90, 200, 90,
50, 70, 50,
      
////quietTime Returns

    60, 61,70,  

      
//////////////////// blowout ramp (2 min)
  70, 75, 80, 83, 85, 90, 92, 95, 
  100, 103, 105, 108, 110, 115, 120, 125,
  130, 140, 150, 160, 170, 185, 
  195, 210

};

//counts for cycling for each current dutycycle
int count1 = 0; // for cycling through events
int count2 = 0; // for cycling through events
int count3 = 0; // for cycling through events
int countSetFlag = 0; 

// current time place holder for dutyCycles
unsigned long currentTime1;
unsigned long currentTime2; 
unsigned long currentTime3; 
unsigned long currentTimeSetFlag; 


//loopTime to update with millis()
unsigned long loopTime1;
unsigned long loopTime2; 
unsigned long loopTime3; 
unsigned long loopTimeSetFlag; 

//event always true in this case, take out...
boolean eventFlag = true;
boolean setFlag= true; 

//ints to hold target duty cycle value, for comparison 
int finalDuty1;
int finalDuty2; 
int finalDuty3; 
int finalDutySetFlag; 

//ints to hold current dutyCycle value 
int currentDuty1 = 40; // all initialized at 40 duty cycle = 1.8 V
int currentDuty2 = 40; 
int currentDuty3 = 40;

// holds the lengths of the arrays
 int sizeET1 = sizeof(event_times_1)/sizeof(unsigned long); 
 int sizeET2 = sizeof(event_times_2)/sizeof(unsigned long); 
 int sizeET3 = sizeof(event_times_3)/sizeof(unsigned long);
 int sizeFlag = sizeof(setFlagTimes)/sizeof(unsigned long); 

 int sizeDC1 = sizeof(dutyCycleTarget_1)/sizeof(unsigned long); 
 int sizeDC2 = sizeof(dutyCycleTarget_2)/sizeof(unsigned long); 
 int sizeDC3 = sizeof(dutyCycleTarget_3)/sizeof(unsigned long);


void setup() {
  Serial.begin(9600);
  
  pinMode(pwm_pin_1, OUTPUT);
  pinMode(pwm_pin_2, OUTPUT);
  pinMode(pwm_pin_3, OUTPUT);

  loopTime1 = currentTime1;//initialize loopTimes to be currentTimes
  loopTime2 = currentTime2;
  loopTime3 = currentTime3;
  loopTimeSetFlag = currentTimeSetFlag;
  
} 


void loop(){ 
  
  // set currentTime to be millis(), timer since program started
  currentTime1 = millis();
  currentTime2 = millis(); 
  currentTime3 = millis(); 
  currentTimeSetFlag = millis();  
 
      unsigned long interval1 = event_times_1[count1];
      unsigned long interval2 = event_times_2[count2];
      unsigned long interval3 = event_times_3[count3];      
      unsigned long intervalSetFlag  = setFlagTimes[countSetFlag];       
 
  // if event_time is past, then flag eventFlag and randomly select 
  // finalDuty cycle from 44 -255
  if(currentTime1 >= (loopTime1 + interval1)){ //pick random event duration to start ramps
     // eventFlag = true;
       Serial.print("event_times: "); Serial.print(event_times_1[count1]); Serial.print(" "); Serial.print("count: "); Serial.print(count1); Serial.print(" "); Serial.print("finalDuty: "); Serial.println(dutyCycleTarget_1[count1]); Serial.println(" ");        
      loopTime1 = currentTime1; //updates loopTime to = currenttime 
      finalDuty1 = dutyCycleTarget_1[count1]; //cycle through dctargets;
      count1++;
      //length of array - 1
      if (count1 > sizeET1-1) {
        count1 = 0; 
      } 
   }
 
 if(currentTime2 >= (loopTime2 + interval2)){ //pick random event duration to start ramps
      eventFlag = true;
      
      loopTime2 = currentTime2; //updates loopTime
      finalDuty2 = dutyCycleTarget_2[count2]; //cycle through dctargets;
      count2++;
      
      if(count2 > sizeET2-1) {
        count2 = 0; 
      } //reset count after array is iterated through
           
  }
// 
 if(currentTime3 >= (loopTime3 + interval3)){ //pick random event duration to start ramps
      eventFlag = true;
      
      loopTime3 = currentTime3; //updates loopTime
      finalDuty3 = dutyCycleTarget_3[count3]; //cycle through dctargets;
      count3++;
      
      if(count3 > sizeET3 - 1) {
        count3 = 0; 
      } //reset count after array is iterated through

  }

if(currentTimeSetFlag >= (loopTimeSetFlag + intervalSetFlag)){ //pick random event duration to start ramps

      loopTimeSetFlag = currentTimeSetFlag; //updates loopTime
      finalDutySetFlag = setFlagTimes[countSetFlag]; //cycle through dctargets;
      countSetFlag++;
      setFlag = !setFlag; // flip flop logic 
      
      if(countSetFlag > sizeFlag - 1) { //whatever length of countSetFlagTimes is 
        countSetFlag = 0; 
      } //reset count after array is iterated through

  }       
    incrementer1(eventFlag, finalDuty1, pwm_pin_1);
    incrementer2(eventFlag, finalDuty2, pwm_pin_2);
    incrementer3(eventFlag, finalDuty3, pwm_pin_3);
    //if we want ramps from (255-40)*x = 215*x = 10000
    Serial.println(" "); 
    delay(80); 

}





/////////////////functions///////////////////////

//function to increment, decrement or hold-steady the dutyCycle of the pwm 
int incrementer1 (boolean event, int finalDuty, int pwm_pin) { 

  if (setFlag == false){
    if (finalDuty > currentDuty1){ 
      currentDuty1 = inc[0] + currentDuty1;
      analogWrite(pwm_pin, currentDuty1);
      Serial.print(currentDuty1); Serial.print("    ");    
    }
    if (finalDuty < currentDuty1){
      currentDuty1 = inc[1] + currentDuty1;
      analogWrite(pwm_pin, currentDuty1);
      Serial.print(currentDuty1); Serial.print("    ");     
 
    } 
    if (finalDuty == currentDuty1){
      analogWrite(pwm_pin, finalDuty); 
      Serial.print(finalDuty); Serial.print("    ");
    }
    if (event == false) {
      analogWrite(pwm_pin, finalDuty); 
      Serial.println(finalDuty); Serial.print("    "); 
    } 
  }else {
    analogWrite(pwm_pin, finalDuty); 
    Serial.print(" "); Serial.print(finalDuty); 
  }
}

//
int incrementer2 (boolean event, int finalDuty, int pwm_pin) { 

  if (setFlag == false){
    if (finalDuty > currentDuty2){ 
      currentDuty2 = inc[0] + currentDuty2;
      analogWrite(pwm_pin, currentDuty2);
      Serial.print(currentDuty2); Serial.print("    ");    
    }
    if (finalDuty < currentDuty2){
      currentDuty2 = inc[1] + currentDuty2;
      analogWrite(pwm_pin, currentDuty2);
      Serial.print(currentDuty2); Serial.print("    ");     
 
    } 
    if (finalDuty == currentDuty2){
      analogWrite(pwm_pin, finalDuty); 
      Serial.print(finalDuty); Serial.print("    ");
    }
    if (event == false) {
      analogWrite(pwm_pin, finalDuty); 
      Serial.println(finalDuty); Serial.print("    "); 
    } 
  }else {
    analogWrite(pwm_pin, finalDuty); 
    Serial.print("   "); Serial.print(finalDuty); 
  }
}

int incrementer3 (boolean event, int finalDuty, int pwm_pin) { 

  if (setFlag == false){
    if (finalDuty > currentDuty3){ 
      currentDuty3 = inc[0] + currentDuty3;
      analogWrite(pwm_pin, currentDuty3);
      Serial.print(currentDuty3); Serial.print("    ");    
    }
    if (finalDuty < currentDuty3){
      currentDuty3 = inc[1] + currentDuty3;
      analogWrite(pwm_pin, currentDuty3);
      Serial.print(currentDuty3); Serial.print("    ");     
 
    } 
    if (finalDuty == currentDuty3){
      analogWrite(pwm_pin, finalDuty); 
      Serial.print(finalDuty); Serial.print("    ");
    }
    if (event == false) {
      analogWrite(pwm_pin, finalDuty); 
      Serial.println(finalDuty); Serial.print("    "); 
    } 
  }else {
    analogWrite(pwm_pin, finalDuty); 
    Serial.print("      "); Serial.print(finalDuty);
  } 
}