IRremote
IRremote.cpp
Go to the documentation of this file.
1 //******************************************************************************
2 // IRremote
3 // Version 2.0.1 June, 2015
4 // Copyright 2009 Ken Shirriff
5 // For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
6 //
7 // Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
8 // Modified by Mitra Ardron <mitra@mitra.biz>
9 // Added Sanyo and Mitsubishi controllers
10 // Modified Sony to spot the repeat codes that some Sony's send
11 //
12 // Interrupt code based on NECIRrcv by Joe Knapp
13 // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
14 // Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
15 //
16 // JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
17 // LG added by Darryl Smith (based on the JVC protocol)
18 // Whynter A/C ARC-110WD added by Francesco Meschia
19 //******************************************************************************
20 
21 // Defining IR_GLOBAL here allows us to declare the instantiation of global variables
22 #define IR_GLOBAL
23 #include "IRremote.h"
24 #undef IR_GLOBAL
25 
26 #ifdef HAS_AVR_INTERRUPT_H
27 #include <avr/interrupt.h>
28 #endif
29 
30 //+=============================================================================
31 // The match functions were (apparently) originally MACROs to improve code speed
32 // (although this would have bloated the code) hence the names being CAPS
33 // A later release implemented debug output and so they needed to be converted
34 // to functions.
35 // I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some
36 // reason, no matter what I did I could not get them to function as macros again.
37 // I have found a *lot* of bugs in the Arduino compiler over the last few weeks,
38 // and I am currently assuming that one of these bugs is my problem.
39 // I may revisit this code at a later date and look at the assembler produced
40 // in a hope of finding out what is going on, but for now they will remain as
41 // functions even in non-DEBUG mode
42 //
43 int MATCH(int measured, int desired) {
44  DBG_PRINT(F("Testing: "));
45  DBG_PRINT(TICKS_LOW(desired), DEC);
46  DBG_PRINT(F(" <= "));
47  DBG_PRINT(measured, DEC);
48  DBG_PRINT(F(" <= "));
49  DBG_PRINT(TICKS_HIGH(desired), DEC);
50 
51  bool passed = ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired)));
52  if (passed) {
53  DBG_PRINTLN(F("?; passed"));
54  } else {
55  DBG_PRINTLN(F("?; FAILED"));
56  }
57  return passed;
58 }
59 
60 //+========================================================
61 // Due to sensor lag, when received, Marks tend to be 100us too long
62 //
63 int MATCH_MARK(int measured_ticks, int desired_us) {
64  DBG_PRINT(F("Testing mark (actual vs desired): "));
65  DBG_PRINT(measured_ticks * USECPERTICK, DEC);
66  DBG_PRINT(F("us vs "));
67  DBG_PRINT(desired_us, DEC);
68  DBG_PRINT("us");
69  DBG_PRINT(": ");
70  DBG_PRINT(TICKS_LOW(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
71  DBG_PRINT(F(" <= "));
72  DBG_PRINT(measured_ticks * USECPERTICK, DEC);
73  DBG_PRINT(F(" <= "));
74  DBG_PRINT(TICKS_HIGH(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
75 
76  int compensated_ticks = measured_ticks - MARK_EXCESS; // compensate for marks exceeded by demodulator hardware
77  bool passed = ((compensated_ticks >= TICKS_LOW(desired_us)) && (compensated_ticks <= TICKS_HIGH(desired_us)));
78  if (passed) {
79  DBG_PRINTLN(F("?; passed"));
80  } else {
81  DBG_PRINTLN(F("?; FAILED"));
82  }
83  return passed;
84 }
85 
86 //+========================================================
87 // Due to sensor lag, when received, Spaces tend to be 100us too short
88 //
89 int MATCH_SPACE(int measured_ticks, int desired_us) {
90  DBG_PRINT(F("Testing space (actual vs desired): "));
91  DBG_PRINT(measured_ticks * USECPERTICK, DEC);
92  DBG_PRINT(F("us vs "));
93  DBG_PRINT(desired_us, DEC);
94  DBG_PRINT("us");
95  DBG_PRINT(": ");
96  DBG_PRINT(TICKS_LOW(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
97  DBG_PRINT(F(" <= "));
98  DBG_PRINT(measured_ticks * USECPERTICK, DEC);
99  DBG_PRINT(F(" <= "));
100  DBG_PRINT(TICKS_HIGH(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
101 
102  int compensated_ticks = measured_ticks + MARK_EXCESS; // compensate for marks exceeded by demodulator hardware
103  bool passed = ((compensated_ticks >= TICKS_LOW(desired_us)) && (compensated_ticks <= TICKS_HIGH(desired_us)));
104  if (passed) {
105  DBG_PRINTLN(F("?; passed"));
106  } else {
107  DBG_PRINTLN(F("?; FAILED"));
108  }
109  return passed;
110 }
111 
112 //+=============================================================================
113 // Interrupt Service Routine - Fires every 50uS
114 // TIMER2 interrupt code to collect raw data.
115 // Widths of alternating SPACE, MARK are recorded in rawbuf.
116 // Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
117 // 'rawlen' counts the number of entries recorded so far.
118 // First entry is the SPACE between transmissions.
119 // As soon as a the first [SPACE] entry gets long:
120 // Ready is set; State switches to IDLE; Timing of SPACE continues.
121 // As soon as first MARK arrives:
122 // Gap width is recorded; Ready is cleared; New logging starts
123 //
124 ISR (TIMER_INTR_NAME) {
125  TIMER_RESET;
126 
127  // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
128  // digitalRead() is very slow. Optimisation is possible, but makes the code unportable
129  uint8_t irdata = (uint8_t) digitalRead(irparams.recvpin);
130 
131  irparams.timer++; // One more 50uS tick
133  irparams.rcvstate = IR_REC_STATE_OVERFLOW; // Buffer overflow
134  }
135 
136  switch (irparams.rcvstate) {
137  //......................................................................
138  case IR_REC_STATE_IDLE: // In the middle of a gap
139  if (irdata == MARK) {
140  if (irparams.timer < GAP_TICKS) { // Not big enough to be a gap.
141  irparams.timer = 0;
142  } else {
143  // Gap just ended; Record duration; Start recording transmission
144  irparams.overflow = false;
145  irparams.rawlen = 0;
147  irparams.timer = 0;
149  }
150  }
151  break;
152  //......................................................................
153  case IR_REC_STATE_MARK: // Timing Mark
154  if (irdata == SPACE) { // Mark ended; Record time
156  irparams.timer = 0;
158  }
159  break;
160  //......................................................................
161  case IR_REC_STATE_SPACE: // Timing Space
162  if (irdata == MARK) { // Space just ended; Record time
164  irparams.timer = 0;
166 
167  } else if (irparams.timer > GAP_TICKS) { // Space
168  // A long Space, indicates gap between codes
169  // Flag the current code as ready for processing
170  // Switch to STOP
171  // Don't reset timer; keep counting Space width
173  }
174  break;
175  //......................................................................
176  case IR_REC_STATE_STOP: // Waiting; Measuring Gap
177  if (irdata == MARK) {
178  irparams.timer = 0; // Reset gap timer
179  }
180  break;
181  //......................................................................
182  case IR_REC_STATE_OVERFLOW: // Flag up a read overflow; Stop the State Machine
183  irparams.overflow = true;
185  break;
186  }
187 
188 #ifdef BLINKLED
189  // If requested, flash LED while receiving IR data
190  if (irparams.blinkflag) {
191  if (irdata == MARK) {
192  if (irparams.blinkpin) {
193  digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on
194  } else {
195  BLINKLED_ON(); // if no user defined LED pin, turn default LED pin for the hardware on
196  }
197  } else {
198  if (irparams.blinkpin) {
199  digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on
200  } else {
201  BLINKLED_OFF(); // if no user defined LED pin, turn default LED pin for the hardware on
202  }
203  }
204  }
205 #endif // BLINKLED
206 }
irparams_t::overflow
uint8_t overflow
Raw buffer overflow occurred.
Definition: IRremoteInt.h:48
irparams_t::timer
unsigned int timer
State timer, counts 50uS ticks.
Definition: IRremoteInt.h:46
BLINKLED_OFF
#define BLINKLED_OFF()
Board dependent macro to turn BLINKLED off.
Definition: IRremoteBoardDefs.h:84
BLINKLED_ON
#define BLINKLED_ON()
Board dependent macro to turn BLINKLED on.
Definition: IRremoteBoardDefs.h:79
MARK_EXCESS
#define MARK_EXCESS
When received, marks tend to be too long and spaces tend to be too short.
Definition: IRremoteInt.h:92
DBG_PRINTLN
#define DBG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremote.h:155
TICKS_LOW
#define TICKS_LOW(us)
Definition: IRremoteInt.h:113
irparams_t::recvpin
uint8_t recvpin
Pin connected to IR data from detector.
Definition: IRremoteInt.h:42
DBG_PRINT
#define DBG_PRINT(...)
If DEBUG, print the arguments, otherwise do nothing.
Definition: IRremote.h:151
MATCH_SPACE
int MATCH_SPACE(int measured_ticks, int desired_us)
Definition: IRremote.cpp:89
MATCH
int MATCH(int measured, int desired)
Definition: IRremote.cpp:43
irparams_t::rcvstate
uint8_t rcvstate
State Machine state.
Definition: IRremoteInt.h:41
irparams
volatile irparams_t irparams
Allow all parts of the code access to the ISR data NB.
USECPERTICK
#define USECPERTICK
Definition: IRremoteBoardDefs.h:166
IR_REC_STATE_STOP
#define IR_REC_STATE_STOP
Definition: IRremoteInt.h:55
IR_REC_STATE_MARK
#define IR_REC_STATE_MARK
Definition: IRremoteInt.h:53
ISR
ISR(TIMER_INTR_NAME)
Definition: IRremote.cpp:124
GAP_TICKS
#define GAP_TICKS
Minimum gap between IR transmissions, in USECPERTICK.
Definition: IRremoteInt.h:108
IR_REC_STATE_OVERFLOW
#define IR_REC_STATE_OVERFLOW
Definition: IRremoteInt.h:56
TICKS_HIGH
#define TICKS_HIGH(us)
Definition: IRremoteInt.h:114
irparams_t::blinkpin
uint8_t blinkpin
Definition: IRremoteInt.h:43
IRremote.h
Public API to the library.
SPACE
#define SPACE
Sensor output for a space ("gap")
Definition: IRremoteInt.h:124
MATCH_MARK
int MATCH_MARK(int measured_ticks, int desired_us)
Definition: IRremote.cpp:63
irparams_t::rawbuf
unsigned int rawbuf[RAW_BUFFER_LENGTH]
raw data
Definition: IRremoteInt.h:47
RAW_BUFFER_LENGTH
#define RAW_BUFFER_LENGTH
Maximum length of raw duration buffer. Must be odd.
Definition: IRremoteInt.h:33
irparams_t::blinkflag
uint8_t blinkflag
true -> enable blinking of pin on IR processing
Definition: IRremoteInt.h:44
IR_REC_STATE_SPACE
#define IR_REC_STATE_SPACE
Definition: IRremoteInt.h:54
MARK
#define MARK
Sensor output for a mark ("flash")
Definition: IRremoteInt.h:123
irparams_t::rawlen
unsigned int rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:45
IR_REC_STATE_IDLE
#define IR_REC_STATE_IDLE
Definition: IRremoteInt.h:52