Infrared remote library for Arduino: send and receive infrared signals with multiple protocols Port from Arduino-IRremote https://github.com/z3t0/Arduino-IRremote

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers IRremote.cpp Source File

IRremote.cpp

00001 //******************************************************************************
00002 // IRremote
00003 // Version 2.0.1 June, 2015
00004 // Copyright 2009 Ken Shirriff
00005 // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
00006 //
00007 // Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
00008 // Modified  by Mitra Ardron <mitra@mitra.biz>
00009 // Added Sanyo and Mitsubishi controllers
00010 // Modified Sony to spot the repeat codes that some Sony's send
00011 //
00012 // Interrupt code based on NECIRrcv by Joe Knapp
00013 // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
00014 // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
00015 //
00016 // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
00017 // LG added by Darryl Smith (based on the JVC protocol)
00018 // Whynter A/C ARC-110WD added by Francesco Meschia
00019 //******************************************************************************
00020 
00021 // Defining IR_GLOBAL here allows us to declare the instantiation of global variables
00022 #define IR_GLOBAL
00023 #   include "IRremote.h"
00024 #   include "IRremoteInt.h"
00025 #undef IR_GLOBAL
00026 
00027 //+=============================================================================
00028 // The match functions were (apparently) originally MACROs to improve code speed
00029 //   (although this would have bloated the code) hence the names being CAPS
00030 // A later release implemented debug output and so they needed to be converted
00031 //   to functions.
00032 // I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some
00033 //   reason, no matter what I did I could not get them to function as macros again.
00034 // I have found a *lot* of bugs in the Arduino compiler over the last few weeks,
00035 //   and I am currently assuming that one of these bugs is my problem.
00036 // I may revisit this code at a later date and look at the assembler produced
00037 //   in a hope of finding out what is going on, but for now they will remain as
00038 //   functions even in non-DEBUG mode
00039 //
00040 int  MATCH (int measured,  int desired)
00041 {
00042     DBG_PRINT("Testing: ");
00043     DBG_PRINT(TICKS_LOW(desired), DEC);
00044     DBG_PRINT(" <= ");
00045     DBG_PRINT(measured, DEC);
00046     DBG_PRINT(" <= ");
00047     DBG_PRINTLN(TICKS_HIGH(desired), DEC);
00048 
00049     return ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired)));
00050 }
00051 
00052 //+========================================================
00053 // Due to sensor lag, when received, Marks tend to be 100us too long
00054 //
00055 int  MATCH_MARK (int measured_ticks,  int desired_us)
00056 {
00057     DBG_PRINT("Testing mark ");
00058     DBG_PRINT(measured_ticks * USECPERTICK, DEC);
00059     DBG_PRINT(" vs ");
00060     DBG_PRINT(desired_us, DEC);
00061     DBG_PRINT(": ");
00062     DBG_PRINT(TICKS_LOW(desired_us + MARK_EXCESS), DEC);
00063     DBG_PRINT(" <= ");
00064     DBG_PRINT(measured_ticks, DEC);
00065     DBG_PRINT(" <= ");
00066     DBG_PRINTLN(TICKS_HIGH(desired_us + MARK_EXCESS), DEC);
00067 
00068     return ((measured_ticks >= TICKS_LOW (desired_us + MARK_EXCESS))
00069          && (measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS)));
00070 }
00071 
00072 //+========================================================
00073 // Due to sensor lag, when received, Spaces tend to be 100us too short
00074 //
00075 int  MATCH_SPACE (int measured_ticks,  int desired_us)
00076 {
00077     DBG_PRINT("Testing space ");
00078     DBG_PRINT(measured_ticks * USECPERTICK, DEC);
00079     DBG_PRINT(" vs ");
00080     DBG_PRINT(desired_us, DEC);
00081     DBG_PRINT(": ");
00082     DBG_PRINT(TICKS_LOW(desired_us - MARK_EXCESS), DEC);
00083     DBG_PRINT(" <= ");
00084     DBG_PRINT(measured_ticks, DEC);
00085     DBG_PRINT(" <= ");
00086     DBG_PRINTLN(TICKS_HIGH(desired_us - MARK_EXCESS), DEC);
00087 
00088     return ((measured_ticks >= TICKS_LOW (desired_us - MARK_EXCESS))
00089          && (measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS)));
00090 }
00091 
00092 //+=============================================================================
00093 // Interrupt Service Routine - Fires every 50uS
00094 // TIMER2 interrupt code to collect raw data.
00095 // Widths of alternating SPACE, MARK are recorded in rawbuf.
00096 // Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
00097 // 'rawlen' counts the number of entries recorded so far.
00098 // First entry is the SPACE between transmissions.
00099 // As soon as a the first [SPACE] entry gets long:
00100 //   Ready is set; State switches to IDLE; Timing of SPACE continues.
00101 // As soon as first MARK arrives:
00102 //   Gap width is recorded; Ready is cleared; New logging starts
00103 //
00104 void IRrecv::timer_isr ()
00105 {
00106     // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
00107     // digitalRead() is very slow. Optimisation is possible, but makes the code unportable
00108     uint8_t  irdata = _recvpin.read();
00109 
00110     irparams.timer++;  // One more 50uS tick
00111     if (irparams.rawlen >= RAWBUF)  irparams.rcvstate = STATE_OVERFLOW ;  // Buffer overflow
00112 
00113     switch(irparams.rcvstate) {
00114         //......................................................................
00115         case STATE_IDLE: // In the middle of a gap
00116             if (irdata == MARK) {
00117                 if (irparams.timer < GAP_TICKS)  {  // Not big enough to be a gap.
00118                     irparams.timer = 0;
00119 
00120                 } else {
00121                     // Gap just ended; Record duration; Start recording transmission
00122                     irparams.overflow                  = false;
00123                     irparams.rawlen                    = 0;
00124                     irparams.rawbuf[irparams.rawlen++] = irparams.timer;
00125                     irparams.timer                     = 0;
00126                     irparams.rcvstate                  = STATE_MARK;
00127                 }
00128             }
00129             break;
00130         //......................................................................
00131         case STATE_MARK:  // Timing Mark
00132             if (irdata == SPACE) {   // Mark ended; Record time
00133                 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
00134                 irparams.timer                     = 0;
00135                 irparams.rcvstate                  = STATE_SPACE;
00136             }
00137             break;
00138         //......................................................................
00139         case STATE_SPACE:  // Timing Space
00140             if (irdata == MARK) {  // Space just ended; Record time
00141                 irparams.rawbuf[irparams.rawlen++] = irparams.timer;
00142                 irparams.timer                     = 0;
00143                 irparams.rcvstate                  = STATE_MARK;
00144 
00145             } else if (irparams.timer > GAP_TICKS) {  // Space
00146                     // A long Space, indicates gap between codes
00147                     // Flag the current code as ready for processing
00148                     // Switch to STOP
00149                     // Don't reset timer; keep counting Space width
00150                     irparams.rcvstate = STATE_STOP;
00151             }
00152             break;
00153         //......................................................................
00154         case STATE_STOP:  // Waiting; Measuring Gap
00155             if (irdata == MARK)  irparams.timer = 0 ;  // Reset gap timer
00156             break;
00157         //......................................................................
00158         case STATE_OVERFLOW:  // Flag up a read overflow; Stop the State Machine
00159             irparams.overflow = true;
00160             irparams.rcvstate = STATE_STOP;
00161             break;
00162     }
00163 }