//Note this code is for lighting up 3 different colored LED strips.
//Connect the Blue strip to pin 7, Green strip to pin 6, and the RED strip to pin 5

//clipping indicator variables
boolean clipping = 0;

//data storage variables
byte newData = 0;
byte prevData = 0;
unsigned int time = 0;//keeps time and sends vales to store in timer[] occasionally
int timer[10];//sstorage for timing of events
int slope[10];//storage fro slope of events
unsigned int totalTimer;//used to calculate period
unsigned int period;//storage for period of wave
byte index = 0;//current storage index
float frequency;//storage for frequency calculations
int maxSlope = 0;//used to calculate max slope as trigger point
int newSlope;//storage for incoming slope data

//variables for decided whether you have a match
byte noMatch = 0;//counts how many non-matches you've received to reset variables if it's been too long
byte slopeTol = 25;//slope tolerance- adjust this if you need
int timerTol = 10;//timer tolerance- adjust this if you need


void setup(){

  //added code for LED outputs
  //should make pins 2-7 of port D outputs.
  DDRD = DDRD | B11111100;
  
  Serial.begin(9600);
  
  pinMode(13,OUTPUT);//led indicator pin
  pinMode(12,OUTPUT);//output pin
  
  cli();//diable interrupts
  
  //set up continuous sampling of analog pin 0 at 38.5kHz
 
  //clear ADCSRA and ADCSRB registers
  ADCSRA = 0;
  ADCSRB = 0;
  
  ADMUX |= (1 << REFS0); //set reference voltage
  ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
  
  ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
  ADCSRA |= (1 << ADATE); //enabble auto trigger
  ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
  ADCSRA |= (1 << ADEN); //enable ADC
  ADCSRA |= (1 << ADSC); //start ADC measurements
  
  sei();//enable interrupts
}

ISR(ADC_vect) {//when new ADC value ready
  
  PORTB &= B11101111;//set pin 12 low
  prevData = newData;//store previous value
  newData = ADCH;//get value from A0
  if (prevData < 127 && newData >=127){//if increasing and crossing midpoint
    newSlope = newData - prevData;//calculate slope
    if (abs(newSlope-maxSlope)<slopeTol){//if slopes are ==
      //record new data and reset time
      slope[index] = newSlope;
      timer[index] = time;
      time = 0;
      if (index == 0){//new max slope just reset
        PORTB |= B00010000;//set pin 12 high
        noMatch = 0;
        index++;//increment index
      }
      else if (abs(timer[0]-timer[index])<timerTol && abs(slope[0]-newSlope)<slopeTol){//if timer duration and slopes match
        //sum timer values
        totalTimer = 0;
        for (byte i=0;i<index;i++){
          totalTimer+=timer[i];
        }
        period = totalTimer;//set period
        //reset new zero index values to compare with
        timer[0] = timer[index];
        slope[0] = slope[index];
        index = 1;//set index to 1
        PORTB |= B00010000;//set pin 12 high
        noMatch = 0;
      }
      else{//crossing midpoint but not match
        index++;//increment index
        if (index > 9){
          reset();
        }
      }
    }
    else if (newSlope>maxSlope){//if new slope is much larger than max slope
      maxSlope = newSlope;
      time = 0;//reset clock
      noMatch = 0;
      index = 0;//reset index
    }
    else{//slope not steep enough
      noMatch++;//increment no match counter
      if (noMatch>9){
        reset();
      }
    }
  }
    
  if (newData == 0 || newData == 1023){//if clipping
    PORTB |= B00100000;//set pin 13 high- turn on clipping indicator led
    clipping = 1;//currently clipping
  }
  
  time++;//increment timer at rate of 38.5kHz
}

void reset(){//clea out some variables
  index = 0;//reset index
  noMatch = 0;//reset match couner
  maxSlope = 0;//reset slope
}


void checkClipping(){//manage clipping indicator LED
  if (clipping){//if currently clipping
    PORTB &= B11011111;//turn off clipping indicator led
    clipping = 0;
  }
}


void loop(){
  
  checkClipping();
  
  frequency = 38462/float(period);//calculate frequency timer rate/period

      //may want to move comment these out and uncomment the ones in
      //the if statement.
      //Serial.print(frequency);
      //Serial.println(" hz");
  
  //print results
  if( (frequency>60) && (frequency<400))
  {   
      Serial.print(frequency);
      Serial.println(" hz");

      //if statements to activate the correct port connected to LED's based on the string played
      //For string E4, activates pins 7 & 5 --> should be purple color
      if( (frequency>324) && (frequency<340) ) 
      {   PORTD = B10100000;}
      
      //For string B3, activates pin 7 --> should be blue color
      else if( (frequency<253) && (frequency>237) )
      {   PORTD = B10000000;}
  
      //For string G3, activates pins 7 & 6 --> should make a light blue color.
      else if( (frequency<208) && (frequency>192) )
      {   PORTD = B11000000; }
  
      //For string D3, activates pin 6 --> should make a green color
      else if( (frequency<155) && (frequency>139) )
      {   PORTD = B01000000;}
  
      //For string A2, activates pins 6 & 5 --> should make a yellow color
      else if( (frequency<114) && (frequency>98) )
      {   PORTD = B01100000;}
  
      //For string E2, activates pin 5 --> should make a red color.
      else if( (frequency<90) && (frequency>74) )
      {   PORTD = B00100000;}
      else
      {   PORTD &= B11111111;}
  }
  
  delay(1000);//feel free to remove this if you want
  
  //do other stuff here
}