to github
[svn42.git] / rf433ctl / IRremote / IRremote.cpp
diff --git a/rf433ctl/IRremote/IRremote.cpp b/rf433ctl/IRremote/IRremote.cpp
deleted file mode 100644 (file)
index b632723..0000000
+++ /dev/null
@@ -1,601 +0,0 @@
-/*\r
- * IRremote\r
- * Version 0.11 August, 2009\r
- * Copyright 2009 Ken Shirriff\r
- * For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html\r
- *\r
- * Interrupt code based on NECIRrcv by Joe Knapp\r
- * http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556\r
- * Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/\r
- */\r
-\r
-#include "IRremote.h"\r
-#include "IRremoteInt.h"\r
-\r
-// Provides ISR\r
-#include <avr/interrupt.h>\r
-\r
-volatile irparams_t irparams;\r
-\r
-// These versions of MATCH, MATCH_MARK, and MATCH_SPACE are only for debugging.\r
-// To use them, set DEBUG in IRremoteInt.h\r
-// Normally macros are used for efficiency\r
-#ifdef DEBUG\r
-int MATCH(int measured, int desired) {\r
-  Serial.print("Testing: ");\r
-  Serial.print(TICKS_LOW(desired), DEC);\r
-  Serial.print(" <= ");\r
-  Serial.print(measured, DEC);\r
-  Serial.print(" <= ");\r
-  Serial.println(TICKS_HIGH(desired), DEC);\r
-  return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);\r
-}\r
-\r
-int MATCH_MARK(int measured_ticks, int desired_us) {\r
-  Serial.print("Testing mark ");\r
-  Serial.print(measured_ticks * USECPERTICK, DEC);\r
-  Serial.print(" vs ");\r
-  Serial.print(desired_us, DEC);\r
-  Serial.print(": ");\r
-  Serial.print(TICKS_LOW(desired_us + MARK_EXCESS), DEC);\r
-  Serial.print(" <= ");\r
-  Serial.print(measured_ticks, DEC);\r
-  Serial.print(" <= ");\r
-  Serial.println(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);\r
-  return measured_ticks >= TICKS_LOW(desired_us + MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS);\r
-}\r
-\r
-int MATCH_SPACE(int measured_ticks, int desired_us) {\r
-  Serial.print("Testing space ");\r
-  Serial.print(measured_ticks * USECPERTICK, DEC);\r
-  Serial.print(" vs ");\r
-  Serial.print(desired_us, DEC);\r
-  Serial.print(": ");\r
-  Serial.print(TICKS_LOW(desired_us - MARK_EXCESS), DEC);\r
-  Serial.print(" <= ");\r
-  Serial.print(measured_ticks, DEC);\r
-  Serial.print(" <= ");\r
-  Serial.println(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);\r
-  return measured_ticks >= TICKS_LOW(desired_us - MARK_EXCESS) && measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS);\r
-}\r
-#endif\r
-\r
-void IRsend::sendNEC(unsigned long data, int nbits)\r
-{\r
-  enableIROut(38);\r
-  mark(NEC_HDR_MARK);\r
-  space(NEC_HDR_SPACE);\r
-  for (int i = 0; i < nbits; i++) {\r
-    if (data & TOPBIT) {\r
-      mark(NEC_BIT_MARK);\r
-      space(NEC_ONE_SPACE);\r
-    } \r
-    else {\r
-      mark(NEC_BIT_MARK);\r
-      space(NEC_ZERO_SPACE);\r
-    }\r
-    data <<= 1;\r
-  }\r
-  mark(NEC_BIT_MARK);\r
-  space(0);\r
-}\r
-\r
-void IRsend::sendSony(unsigned long data, int nbits) {\r
-  enableIROut(40);\r
-  mark(SONY_HDR_MARK);\r
-  space(SONY_HDR_SPACE);\r
-  data = data << (32 - nbits);\r
-  for (int i = 0; i < nbits; i++) {\r
-    if (data & TOPBIT) {\r
-      mark(SONY_ONE_MARK);\r
-      space(SONY_HDR_SPACE);\r
-    } \r
-    else {\r
-      mark(SONY_ZERO_MARK);\r
-      space(SONY_HDR_SPACE);\r
-    }\r
-    data <<= 1;\r
-  }\r
-}\r
-\r
-void IRsend::sendRaw(unsigned int buf[], int len, int hz)\r
-{\r
-  enableIROut(hz);\r
-  for (int i = 0; i < len; i++) {\r
-    if (i & 1) {\r
-      space(buf[i]);\r
-    } \r
-    else {\r
-      mark(buf[i]);\r
-    }\r
-  }\r
-  space(0); // Just to be sure\r
-}\r
-\r
-// Note: first bit must be a one (start bit)\r
-void IRsend::sendRC5(unsigned long data, int nbits)\r
-{\r
-  enableIROut(36);\r
-  data = data << (32 - nbits);\r
-  mark(RC5_T1); // First start bit\r
-  space(RC5_T1); // Second start bit\r
-  mark(RC5_T1); // Second start bit\r
-  for (int i = 0; i < nbits; i++) {\r
-    if (data & TOPBIT) {\r
-      space(RC5_T1); // 1 is space, then mark\r
-      mark(RC5_T1);\r
-    } \r
-    else {\r
-      mark(RC5_T1);\r
-      space(RC5_T1);\r
-    }\r
-    data <<= 1;\r
-  }\r
-  space(0); // Turn off at end\r
-}\r
-\r
-// Caller needs to take care of flipping the toggle bit\r
-void IRsend::sendRC6(unsigned long data, int nbits)\r
-{\r
-  enableIROut(36);\r
-  data = data << (32 - nbits);\r
-  mark(RC6_HDR_MARK);\r
-  space(RC6_HDR_SPACE);\r
-  mark(RC6_T1); // start bit\r
-  space(RC6_T1);\r
-  int t;\r
-  for (int i = 0; i < nbits; i++) {\r
-    if (i == 3) {\r
-      // double-wide trailer bit\r
-      t = 2 * RC6_T1;\r
-    } \r
-    else {\r
-      t = RC6_T1;\r
-    }\r
-    if (data & TOPBIT) {\r
-      mark(t);\r
-      space(t);\r
-    } \r
-    else {\r
-      space(t);\r
-      mark(t);\r
-    }\r
-\r
-    data <<= 1;\r
-  }\r
-  space(0); // Turn off at end\r
-}\r
-\r
-void IRsend::mark(int time) {\r
-  // Sends an IR mark for the specified number of microseconds.\r
-  // The mark output is modulated at the PWM frequency.\r
-  TCCR2A |= _BV(COM2B1); // Enable pin 3 PWM output\r
-  delayMicroseconds(time);\r
-}\r
-\r
-/* Leave pin off for time (given in microseconds) */\r
-void IRsend::space(int time) {\r
-  // Sends an IR space for the specified number of microseconds.\r
-  // A space is no output, so the PWM output is disabled.\r
-  TCCR2A &= ~(_BV(COM2B1)); // Disable pin 3 PWM output\r
-  delayMicroseconds(time);\r
-}\r
-\r
-void IRsend::enableIROut(int khz) {\r
-  // Enables IR output.  The khz value controls the modulation frequency in kilohertz.\r
-  // The IR output will be on pin 3 (OC2B).\r
-  // This routine is designed for 36-40KHz; if you use it for other values, it's up to you\r
-  // to make sure it gives reasonable results.  (Watch out for overflow / underflow / rounding.)\r
-  // TIMER2 is used in phase-correct PWM mode, with OCR2A controlling the frequency and OCR2B\r
-  // controlling the duty cycle.\r
-  // There is no prescaling, so the output frequency is 16MHz / (2 * OCR2A)\r
-  // To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.\r
-  // A few hours staring at the ATmega documentation and this will all make sense.\r
-  // See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.\r
-\r
-  \r
-  // Disable the Timer2 Interrupt (which is used for receiving IR)\r
-  TIMSK2 &= ~_BV(TOIE2); //Timer2 Overflow Interrupt\r
-  \r
-  pinMode(3, OUTPUT);\r
-  digitalWrite(3, HIGH); // When not sending PWM, we want it low (invertiert angeschlossen)\r
-  \r
-  // COM2A = 00: disconnect OC2A\r
-  // COM2B = 00: disconnect OC2B; to send signal set to 10: OC2B non-inverted\r
-  // WGM2 = 101: phase-correct PWM with OCRA as top\r
-  // CS2 = 000: no prescaling\r
-  TCCR2A = _BV(WGM20);\r
-  TCCR2B = _BV(WGM22) | _BV(CS20);\r
-\r
-  // The top value for the timer.  The modulation frequency will be SYSCLOCK / 2 / OCR2A.\r
-  OCR2A = SYSCLOCK / 2 / khz / 1000;\r
-  OCR2B = OCR2A / 4; // 33% duty cycle\r
-}\r
-\r
-IRrecv::IRrecv(int recvpin)\r
-{\r
-  irparams.recvpin = recvpin;\r
-  irparams.blinkflag = 0;\r
-}\r
-\r
-// initialization\r
-void IRrecv::enableIRIn() {\r
-  // setup pulse clock timer interrupt\r
-  TCCR2A = 0;  // normal mode\r
-\r
-  //Prescale /8 (16M/8 = 0.5 microseconds per tick)\r
-  // Therefore, the timer interval can range from 0.5 to 128 microseconds\r
-  // depending on the reset value (255 to 0)\r
-  cbi(TCCR2B,CS22);\r
-  sbi(TCCR2B,CS21);\r
-  cbi(TCCR2B,CS20);\r
-\r
-  //Timer2 Overflow Interrupt Enable\r
-  sbi(TIMSK2,TOIE2);\r
-\r
-  RESET_TIMER2;\r
-\r
-  sei();  // enable interrupts\r
-\r
-  // initialize state machine variables\r
-  irparams.rcvstate = STATE_IDLE;\r
-  irparams.rawlen = 0;\r
-\r
-\r
-  // set pin modes\r
-  pinMode(irparams.recvpin, INPUT);\r
-}\r
-\r
-// enable/disable blinking of pin 13 on IR processing\r
-void IRrecv::blink13(int blinkflag)\r
-{\r
-  irparams.blinkflag = blinkflag;\r
-  if (blinkflag)\r
-    pinMode(BLINKLED, OUTPUT);\r
-}\r
-\r
-// TIMER2 interrupt code to collect raw data.\r
-// Widths of alternating SPACE, MARK are recorded in rawbuf.\r
-// Recorded in ticks of 50 microseconds.\r
-// rawlen counts the number of entries recorded so far.\r
-// First entry is the SPACE between transmissions.\r
-// As soon as a SPACE gets long, ready is set, state switches to IDLE, timing of SPACE continues.\r
-// As soon as first MARK arrives, gap width is recorded, ready is cleared, and new logging starts\r
-ISR(TIMER2_OVF_vect)\r
-{\r
-  RESET_TIMER2;\r
-\r
-  uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);\r
-\r
-  irparams.timer++; // One more 50us tick\r
-  if (irparams.rawlen >= RAWBUF) {\r
-    // Buffer overflow\r
-    irparams.rcvstate = STATE_STOP;\r
-  }\r
-  switch(irparams.rcvstate) {\r
-  case STATE_IDLE: // In the middle of a gap\r
-    if (irdata == MARK) {\r
-      if (irparams.timer < GAP_TICKS) {\r
-        // Not big enough to be a gap.\r
-        irparams.timer = 0;\r
-      } \r
-      else {\r
-        // gap just ended, record duration and start recording transmission\r
-        irparams.rawlen = 0;\r
-        irparams.rawbuf[irparams.rawlen++] = irparams.timer;\r
-        irparams.timer = 0;\r
-        irparams.rcvstate = STATE_MARK;\r
-      }\r
-    }\r
-    break;\r
-  case STATE_MARK: // timing MARK\r
-    if (irdata == SPACE) {   // MARK ended, record time\r
-      irparams.rawbuf[irparams.rawlen++] = irparams.timer;\r
-      irparams.timer = 0;\r
-      irparams.rcvstate = STATE_SPACE;\r
-    }\r
-    break;\r
-  case STATE_SPACE: // timing SPACE\r
-    if (irdata == MARK) { // SPACE just ended, record it\r
-      irparams.rawbuf[irparams.rawlen++] = irparams.timer;\r
-      irparams.timer = 0;\r
-      irparams.rcvstate = STATE_MARK;\r
-    } \r
-    else { // SPACE\r
-      if (irparams.timer > GAP_TICKS) {\r
-        // big SPACE, indicates gap between codes\r
-        // Mark current code as ready for processing\r
-        // Switch to STOP\r
-        // Don't reset timer; keep counting space width\r
-        irparams.rcvstate = STATE_STOP;\r
-      } \r
-    }\r
-    break;\r
-  case STATE_STOP: // waiting, measuring gap\r
-    if (irdata == MARK) { // reset gap timer\r
-      irparams.timer = 0;\r
-    }\r
-    break;\r
-  }\r
-\r
-  if (irparams.blinkflag) {\r
-    if (irdata == MARK) {\r
-      PORTB |= B00100000;  // turn pin 13 LED on\r
-    } \r
-    else {\r
-      PORTB &= B11011111;  // turn pin 13 LED off\r
-    }\r
-  }\r
-}\r
-\r
-void IRrecv::resume() {\r
-  irparams.rcvstate = STATE_IDLE;\r
-  irparams.rawlen = 0;\r
-}\r
-\r
-\r
-\r
-// Decodes the received IR message\r
-// Returns 0 if no data ready, 1 if data ready.\r
-// Results of decoding are stored in results\r
-int IRrecv::decode(decode_results *results) {\r
-  results->rawbuf = irparams.rawbuf;\r
-  results->rawlen = irparams.rawlen;\r
-  if (irparams.rcvstate != STATE_STOP) {\r
-    return ERR;\r
-  }\r
-#ifdef DEBUG\r
-  Serial.println("Attempting NEC decode");\r
-#endif\r
-  if (decodeNEC(results)) {\r
-    return DECODED;\r
-  }\r
-#ifdef DEBUG\r
-  Serial.println("Attempting Sony decode");\r
-#endif\r
-  if (decodeSony(results)) {\r
-    return DECODED;\r
-  }\r
-#ifdef DEBUG\r
-  Serial.println("Attempting RC5 decode");\r
-#endif  \r
-  if (decodeRC5(results)) {\r
-    return DECODED;\r
-  }\r
-#ifdef DEBUG\r
-  Serial.println("Attempting RC6 decode");\r
-#endif \r
-  if (decodeRC6(results)) {\r
-    return DECODED;\r
-  }\r
-  if (results->rawlen >= 6) {\r
-    // Only return raw buffer if at least 6 bits\r
-    results->decode_type = UNKNOWN;\r
-    results->bits = 0;\r
-    results->value = 0;\r
-    return DECODED;\r
-  }\r
-  // Throw away and start over\r
-  resume();\r
-  return ERR;\r
-}\r
-\r
-long IRrecv::decodeNEC(decode_results *results) {\r
-  long data = 0;\r
-  int offset = 1; // Skip first space\r
-  // Initial mark\r
-  if (!MATCH_MARK(results->rawbuf[offset], NEC_HDR_MARK)) {\r
-    return ERR;\r
-  }\r
-  offset++;\r
-  // Check for repeat\r
-  if (irparams.rawlen == 4 &&\r
-    MATCH_SPACE(results->rawbuf[offset], NEC_RPT_SPACE) &&\r
-    MATCH_MARK(results->rawbuf[offset+1], NEC_BIT_MARK)) {\r
-    results->bits = 0;\r
-    results->value = REPEAT;\r
-    results->decode_type = NEC;\r
-    return DECODED;\r
-  }\r
-  if (irparams.rawlen < 2 * NEC_BITS + 4) {\r
-    return ERR;\r
-  }\r
-  // Initial space  \r
-  if (!MATCH_SPACE(results->rawbuf[offset], NEC_HDR_SPACE)) {\r
-    return ERR;\r
-  }\r
-  offset++;\r
-  for (int i = 0; i < NEC_BITS; i++) {\r
-    if (!MATCH_MARK(results->rawbuf[offset], NEC_BIT_MARK)) {\r
-      return ERR;\r
-    }\r
-    offset++;\r
-    if (MATCH_SPACE(results->rawbuf[offset], NEC_ONE_SPACE)) {\r
-      data = (data << 1) | 1;\r
-    } \r
-    else if (MATCH_SPACE(results->rawbuf[offset], NEC_ZERO_SPACE)) {\r
-      data <<= 1;\r
-    } \r
-    else {\r
-      return ERR;\r
-    }\r
-    offset++;\r
-  }\r
-  // Success\r
-  results->bits = NEC_BITS;\r
-  results->value = data;\r
-  results->decode_type = NEC;\r
-  return DECODED;\r
-}\r
-\r
-long IRrecv::decodeSony(decode_results *results) {\r
-  long data = 0;\r
-  if (irparams.rawlen < 2 * SONY_BITS + 2) {\r
-    return ERR;\r
-  }\r
-  int offset = 1; // Skip first space\r
-  // Initial mark\r
-  if (!MATCH_MARK(results->rawbuf[offset], SONY_HDR_MARK)) {\r
-    return ERR;\r
-  }\r
-  offset++;\r
-\r
-  while (offset + 1 < irparams.rawlen) {\r
-    if (!MATCH_SPACE(results->rawbuf[offset], SONY_HDR_SPACE)) {\r
-      break;\r
-    }\r
-    offset++;\r
-    if (MATCH_MARK(results->rawbuf[offset], SONY_ONE_MARK)) {\r
-      data = (data << 1) | 1;\r
-    } \r
-    else if (MATCH_MARK(results->rawbuf[offset], SONY_ZERO_MARK)) {\r
-      data <<= 1;\r
-    } \r
-    else {\r
-      return ERR;\r
-    }\r
-    offset++;\r
-  }\r
-\r
-  // Success\r
-  results->bits = (offset - 1) / 2;\r
-  if (results->bits < 12) {\r
-    results->bits = 0;\r
-    return ERR;\r
-  }\r
-  results->value = data;\r
-  results->decode_type = SONY;\r
-  return DECODED;\r
-}\r
-\r
-// Gets one undecoded level at a time from the raw buffer.\r
-// The RC5/6 decoding is easier if the data is broken into time intervals.\r
-// E.g. if the buffer has MARK for 2 time intervals and SPACE for 1,\r
-// successive calls to getRClevel will return MARK, MARK, SPACE.\r
-// offset and used are updated to keep track of the current position.\r
-// t1 is the time interval for a single bit in microseconds.\r
-// Returns -1 for error (measured time interval is not a multiple of t1).\r
-int IRrecv::getRClevel(decode_results *results, int *offset, int *used, int t1) {\r
-  if (*offset >= results->rawlen) {\r
-    // After end of recorded buffer, assume SPACE.\r
-    return SPACE;\r
-  }\r
-  int width = results->rawbuf[*offset];\r
-  int val = ((*offset) % 2) ? MARK : SPACE;\r
-  int correction = (val == MARK) ? MARK_EXCESS : - MARK_EXCESS;\r
-\r
-  int avail;\r
-  if (MATCH(width, t1 + correction)) {\r
-    avail = 1;\r
-  } \r
-  else if (MATCH(width, 2*t1 + correction)) {\r
-    avail = 2;\r
-  } \r
-  else if (MATCH(width, 3*t1 + correction)) {\r
-    avail = 3;\r
-  } \r
-  else {\r
-    return -1;\r
-  }\r
-\r
-  (*used)++;\r
-  if (*used >= avail) {\r
-    *used = 0;\r
-    (*offset)++;\r
-  }\r
-#ifdef DEBUG\r
-  if (val == MARK) {\r
-    Serial.println("MARK");\r
-  } \r
-  else {\r
-    Serial.println("SPACE");\r
-  }\r
-#endif\r
-  return val;   \r
-}\r
-\r
-long IRrecv::decodeRC5(decode_results *results) {\r
-  if (irparams.rawlen < MIN_RC5_SAMPLES + 2) {\r
-    return ERR;\r
-  }\r
-  int offset = 1; // Skip gap space\r
-  long data = 0;\r
-  int used = 0;\r
-  // Get start bits\r
-  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;\r
-  if (getRClevel(results, &offset, &used, RC5_T1) != SPACE) return ERR;\r
-  if (getRClevel(results, &offset, &used, RC5_T1) != MARK) return ERR;\r
-  int nbits;\r
-  for (nbits = 0; offset < irparams.rawlen; nbits++) {\r
-    int levelA = getRClevel(results, &offset, &used, RC5_T1); \r
-    int levelB = getRClevel(results, &offset, &used, RC5_T1);\r
-    if (levelA == SPACE && levelB == MARK) {\r
-      // 1 bit\r
-      data = (data << 1) | 1;\r
-    } \r
-    else if (levelA == MARK && levelB == SPACE) {\r
-      // zero bit\r
-      data <<= 1;\r
-    } \r
-    else {\r
-      return ERR;\r
-    } \r
-  }\r
-\r
-  // Success\r
-  results->bits = nbits;\r
-  results->value = data;\r
-  results->decode_type = RC5;\r
-  return DECODED;\r
-}\r
-\r
-long IRrecv::decodeRC6(decode_results *results) {\r
-  if (results->rawlen < MIN_RC6_SAMPLES) {\r
-    return ERR;\r
-  }\r
-  int offset = 1; // Skip first space\r
-  // Initial mark\r
-  if (!MATCH_MARK(results->rawbuf[offset], RC6_HDR_MARK)) {\r
-    return ERR;\r
-  }\r
-  offset++;\r
-  if (!MATCH_SPACE(results->rawbuf[offset], RC6_HDR_SPACE)) {\r
-    return ERR;\r
-  }\r
-  offset++;\r
-  long data = 0;\r
-  int used = 0;\r
-  // Get start bit (1)\r
-  if (getRClevel(results, &offset, &used, RC6_T1) != MARK) return ERR;\r
-  if (getRClevel(results, &offset, &used, RC6_T1) != SPACE) return ERR;\r
-  int nbits;\r
-  for (nbits = 0; offset < results->rawlen; nbits++) {\r
-    int levelA, levelB; // Next two levels\r
-    levelA = getRClevel(results, &offset, &used, RC6_T1); \r
-    if (nbits == 3) {\r
-      // T bit is double wide; make sure second half matches\r
-      if (levelA != getRClevel(results, &offset, &used, RC6_T1)) return ERR;\r
-    } \r
-    levelB = getRClevel(results, &offset, &used, RC6_T1);\r
-    if (nbits == 3) {\r
-      // T bit is double wide; make sure second half matches\r
-      if (levelB != getRClevel(results, &offset, &used, RC6_T1)) return ERR;\r
-    } \r
-    if (levelA == MARK && levelB == SPACE) { // reversed compared to RC5\r
-      // 1 bit\r
-      data = (data << 1) | 1;\r
-    } \r
-    else if (levelA == SPACE && levelB == MARK) {\r
-      // zero bit\r
-      data <<= 1;\r
-    } \r
-    else {\r
-      return ERR; // Error\r
-    } \r
-  }\r
-  // Success\r
-  results->bits = nbits;\r
-  results->value = data;\r
-  results->decode_type = RC6;\r
-  return DECODED;\r
-}\r