int b00[] = { 60, 60, 60, 60, 60,160,160,160,160,160};
int b01[] = {160, 60, 60, 60, 60, 60,160,160,160,160};
int b02[] = { 60,160, 60, 60, 60,160, 60,160,160,160};
int b03[] = { 60, 60,160, 60, 60,160,160, 60,160,160};
int b04[] = {160, 60,160, 60, 60, 60,160, 60,160,160};
int b05[] = { 60,160,160, 60, 60,160, 60, 60,160,160};
int b06[] = { 60, 60, 60,160, 60,160,160,160, 60,160};
int b07[] = {160, 60, 60,160, 60, 60,160,160, 60,160};
int b08[] = { 60,160, 60,160, 60,160, 60,160, 60,160};
int b09[] = { 60, 60,160,160, 60,160,160, 60, 60,160};
int b10[] = {160, 60,160,160, 60, 60,160, 60, 60,160};
int b11[] = { 60,160,160,160, 60,160, 60, 60, 60,160};
int b12[] = { 60, 60, 60, 60,160,160,160,160,160, 60};
int b13[] = {160, 60, 60, 60,160, 60,160,160,160, 60};
int b14[] = { 60,160, 60, 60,160,160, 60,160,160, 60};
int b15[] = { 60, 60,160, 60,160,160,160, 60,160, 60};
int b16[] = {160, 60,160, 60,160, 60,160, 60,160, 60};
int b17[] = { 60,160,160, 60,160,160, 60, 60,160, 60};
int b18[] = { 60, 60, 60,160,160,160,160,160, 60, 60};
int b19[] = {160, 60, 60,160,160, 60,160,160, 60, 60};
int b20[] = { 60,160, 60,160,160,160, 60,160, 60, 60};

// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
#define IRpin_PIN      PIND
#define IRpin          2
 
// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
 
// what our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20 
 
// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[100][2];  // pair is high and low pulse 
uint8_t currentpulse = 0; // index for pulses we're storing
 
void setup(void) {
  Serial.begin(115200);
  Serial.println("Ready to decode IR!");
}
 
int listenForIR(void) {
  currentpulse = 0;
 
  while (1) {
    uint16_t highpulse, lowpulse;  // temporary storage timing
    highpulse = lowpulse = 0; // start out with no pulse length
 
//  while (digitalRead(IRpin)) { // this is too slow!
    while (IRpin_PIN & (1 << IRpin)) {
       // pin is still HIGH
 
       // count off another few microseconds
       highpulse++;
       delayMicroseconds(RESOLUTION);
 
       // If the pulse is too long, we 'timed out' - either nothing
       // was received or the code is finished, so print what
       // we've grabbed so far, and then reset
       if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
         return currentpulse;
       }
    }
    // we didn't time out so lets stash the reading
    pulses[currentpulse][0] = highpulse;
 
    // same as above
    while (! (IRpin_PIN & _BV(IRpin))) {
       // pin is still LOW
       lowpulse++;
       delayMicroseconds(RESOLUTION);
       if ((lowpulse >= MAXPULSE)  && (currentpulse != 0)) {
         return currentpulse;
       }
    }
    pulses[currentpulse][1] = lowpulse;
 
    // we read one high-low pulse successfully, continue!
    currentpulse++;
  }
}

#define FUZZINESS 20

void loop(void) {
  int numberpulses;
 
  numberpulses = listenForIR();
 
//  Serial.print("Heard ");
//  Serial.print(numberpulses);
//  Serial.println("-pulse long IR signal");
       if (IRcompare(numberpulses, b00)) { Serial.println("VOL-"); }
  else if (IRcompare(numberpulses, b01)) { Serial.println("PLAY/PAUSE"); }
  else if (IRcompare(numberpulses, b02)) { Serial.println("VOL+"); }
  else if (IRcompare(numberpulses, b03)) { Serial.println("SETUP"); }
  else if (IRcompare(numberpulses, b04)) { Serial.println("UP (PREV)"); }
  else if (IRcompare(numberpulses, b05)) { Serial.println("STOP/MODE"); }
  else if (IRcompare(numberpulses, b06)) { Serial.println("LEFT (CH-)"); }
  else if (IRcompare(numberpulses, b07)) { Serial.println("ENTER/SAVE"); }
  else if (IRcompare(numberpulses, b08)) { Serial.println("RIGHT (CH+)"); }
  else if (IRcompare(numberpulses, b09)) { Serial.println("0 10+"); }
  else if (IRcompare(numberpulses, b10)) { Serial.println("DOWN (NEXT)"); }
  else if (IRcompare(numberpulses, b11)) { Serial.println("CONTINUE"); }
  else if (IRcompare(numberpulses, b12)) { Serial.println("1"); }
  else if (IRcompare(numberpulses, b13)) { Serial.println("2"); }
  else if (IRcompare(numberpulses, b14)) { Serial.println("3"); }
  else if (IRcompare(numberpulses, b15)) { Serial.println("4"); }
  else if (IRcompare(numberpulses, b16)) { Serial.println("5"); }
  else if (IRcompare(numberpulses, b17)) { Serial.println("6"); }
  else if (IRcompare(numberpulses, b18)) { Serial.println("7"); }
  else if (IRcompare(numberpulses, b19)) { Serial.println("8"); }
  else if (IRcompare(numberpulses, b20)) { Serial.println("9"); }
}
boolean IRcompare(int numpulses, int Signal[]) {
int com[] = {880,430,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,60,160,60,160,60,160,60,160,60,160,60,160,60,60,60,160,60,999,60,999,60,999,60,999,60,999,60,60,60,60,60,60,60,160,60,999,60,999,60,999,60,999,60,160,60,160,60,160,60,4000,880,220,60, 0};
 
  for (int i=0; i< numpulses-1; i++) {
    int oncode = pulses[i][1] * RESOLUTION / 10;
    int offcode = pulses[i+1][0] * RESOLUTION / 10;
 
    /*
    Serial.print(oncode); // the ON signal we heard
    Serial.print(" - ");
    Serial.print(Signal[i*2 + 0]); // the ON signal we want 
    */

    // check to make sure the error is less than FUZZINESS percent
    if ( abs(oncode - com[i*2 + 0]) <= (com[i*2 + 0] * FUZZINESS / 100)) {
      //Serial.print(" (ok)");
    } else {
      //Serial.print(" (x)");
      // we didn't match perfectly, return a false match
      return false;
    }
 
    /*
    Serial.print("  \t"); // tab
    Serial.print(offcode); // the OFF signal we heard
    Serial.print(" - ");
    Serial.print(Signal[i*2 + 1]); // the OFF signal we want 
    */
 
    int iO = i*2 + 1;
    if((iO==35)||(iO==37)||(iO==39)||(iO==41)||(iO==43)||(iO==51)||(iO==53)||(iO==55)||(iO==57)||(iO==59)){
      switch(iO){
        case 35:
          iO = 0;
        break;
        case 37:
          iO = 1;
        break;
        case 39:
          iO = 2;
        break;
        case 41:
          iO = 3;
        break;
        case 43:
          iO = 4;
        break;
        case 51:
          iO = 5;
        break;
        case 53:
          iO = 6;
        break;
        case 55:
          iO = 7;
        break;
        case 57:
          iO = 8;
        break;
        case 59:
          iO = 9;
        break;
      }

      if ( abs(offcode - Signal[iO]) > (Signal[iO] * FUZZINESS / 100)) {
        return false;
      }
    } else {
      if ( abs(offcode - com[i*2 + 1]) <= (com[i*2 + 1] * FUZZINESS / 100)) {
        //Serial.print(" (ok)");
      } else {
        //Serial.print(" (x)");
        // we didn't match perfectly, return a false match
        return false;
      }
    } 
    //Serial.println();
  }
  // Everything matched!
  return true;
}
