PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

IRremote.cpp 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  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. // Defining IR_GLOBAL here allows us to declare the instantiation of global variables
  21. #define IR_GLOBAL
  22. # include "IRremote.h"
  23. # include "IRremoteInt.h"
  24. #undef IR_GLOBAL
  25. #ifndef IR_TIMER_USE_ESP32
  26. #include <avr/interrupt.h>
  27. #endif
  28. //+=============================================================================
  29. // The match functions were (apparently) originally MACROs to improve code speed
  30. // (although this would have bloated the code) hence the names being CAPS
  31. // A later release implemented debug output and so they needed to be converted
  32. // to functions.
  33. // I tried to implement a dual-compile mode (DEBUG/non-DEBUG) but for some
  34. // reason, no matter what I did I could not get them to function as macros again.
  35. // I have found a *lot* of bugs in the Arduino compiler over the last few weeks,
  36. // and I am currently assuming that one of these bugs is my problem.
  37. // I may revisit this code at a later date and look at the assembler produced
  38. // in a hope of finding out what is going on, but for now they will remain as
  39. // functions even in non-DEBUG mode
  40. //
  41. int MATCH (int measured, int desired)
  42. {
  43. DBG_PRINT(F("Testing: "));
  44. DBG_PRINT(TICKS_LOW(desired), DEC);
  45. DBG_PRINT(F(" <= "));
  46. DBG_PRINT(measured, DEC);
  47. DBG_PRINT(F(" <= "));
  48. DBG_PRINT(TICKS_HIGH(desired), DEC);
  49. bool passed = ((measured >= TICKS_LOW(desired)) && (measured <= TICKS_HIGH(desired)));
  50. if (passed) {
  51. DBG_PRINTLN(F("?; passed"));
  52. } else {
  53. DBG_PRINTLN(F("?; FAILED"));
  54. }
  55. return passed;
  56. }
  57. //+========================================================
  58. // Due to sensor lag, when received, Marks tend to be 100us too long
  59. //
  60. int MATCH_MARK (int measured_ticks, int desired_us)
  61. {
  62. DBG_PRINT(F("Testing mark (actual vs desired): "));
  63. DBG_PRINT(measured_ticks * USECPERTICK, DEC);
  64. DBG_PRINT(F("us vs "));
  65. DBG_PRINT(desired_us, DEC);
  66. DBG_PRINT("us");
  67. DBG_PRINT(": ");
  68. DBG_PRINT(TICKS_LOW(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
  69. DBG_PRINT(F(" <= "));
  70. DBG_PRINT(measured_ticks * USECPERTICK, DEC);
  71. DBG_PRINT(F(" <= "));
  72. DBG_PRINT(TICKS_HIGH(desired_us + MARK_EXCESS) * USECPERTICK, DEC);
  73. bool passed = ((measured_ticks >= TICKS_LOW (desired_us + MARK_EXCESS))
  74. && (measured_ticks <= TICKS_HIGH(desired_us + MARK_EXCESS)));
  75. if (passed) {
  76. DBG_PRINTLN(F("?; passed"));
  77. } else {
  78. DBG_PRINTLN(F("?; FAILED"));
  79. }
  80. return passed;
  81. }
  82. //+========================================================
  83. // Due to sensor lag, when received, Spaces tend to be 100us too short
  84. //
  85. int MATCH_SPACE (int measured_ticks, int desired_us)
  86. {
  87. DBG_PRINT(F("Testing space (actual vs desired): "));
  88. DBG_PRINT(measured_ticks * USECPERTICK, DEC);
  89. DBG_PRINT(F("us vs "));
  90. DBG_PRINT(desired_us, DEC);
  91. DBG_PRINT("us");
  92. DBG_PRINT(": ");
  93. DBG_PRINT(TICKS_LOW(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
  94. DBG_PRINT(F(" <= "));
  95. DBG_PRINT(measured_ticks * USECPERTICK, DEC);
  96. DBG_PRINT(F(" <= "));
  97. DBG_PRINT(TICKS_HIGH(desired_us - MARK_EXCESS) * USECPERTICK, DEC);
  98. bool passed = ((measured_ticks >= TICKS_LOW (desired_us - MARK_EXCESS))
  99. && (measured_ticks <= TICKS_HIGH(desired_us - MARK_EXCESS)));
  100. if (passed) {
  101. DBG_PRINTLN(F("?; passed"));
  102. } else {
  103. DBG_PRINTLN(F("?; FAILED"));
  104. }
  105. return passed;
  106. }
  107. //+=============================================================================
  108. // Interrupt Service Routine - Fires every 50uS
  109. // TIMER2 interrupt code to collect raw data.
  110. // Widths of alternating SPACE, MARK are recorded in rawbuf.
  111. // Recorded in ticks of 50uS [microseconds, 0.000050 seconds]
  112. // 'rawlen' counts the number of entries recorded so far.
  113. // First entry is the SPACE between transmissions.
  114. // As soon as a the first [SPACE] entry gets long:
  115. // Ready is set; State switches to IDLE; Timing of SPACE continues.
  116. // As soon as first MARK arrives:
  117. // Gap width is recorded; Ready is cleared; New logging starts
  118. //
  119. #ifdef IR_TIMER_USE_ESP32
  120. void IRTimer()
  121. #else
  122. ISR (TIMER_INTR_NAME)
  123. #endif
  124. {
  125. TIMER_RESET;
  126. // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
  127. // digitalRead() is very slow. Optimisation is possible, but makes the code unportable
  128. uint8_t irdata = (uint8_t)digitalRead(irparams.recvpin);
  129. irparams.timer++; // One more 50uS tick
  130. if (irparams.rawlen >= RAWBUF) irparams.rcvstate = STATE_OVERFLOW ; // Buffer overflow
  131. switch(irparams.rcvstate) {
  132. //......................................................................
  133. case STATE_IDLE: // In the middle of a gap
  134. if (irdata == MARK) {
  135. if (irparams.timer < GAP_TICKS) { // Not big enough to be a gap.
  136. irparams.timer = 0;
  137. } else {
  138. // Gap just ended; Record duration; Start recording transmission
  139. irparams.overflow = false;
  140. irparams.rawlen = 0;
  141. irparams.rawbuf[irparams.rawlen++] = irparams.timer;
  142. irparams.timer = 0;
  143. irparams.rcvstate = STATE_MARK;
  144. }
  145. }
  146. break;
  147. //......................................................................
  148. case STATE_MARK: // Timing Mark
  149. if (irdata == SPACE) { // Mark ended; Record time
  150. irparams.rawbuf[irparams.rawlen++] = irparams.timer;
  151. irparams.timer = 0;
  152. irparams.rcvstate = STATE_SPACE;
  153. }
  154. break;
  155. //......................................................................
  156. case STATE_SPACE: // Timing Space
  157. if (irdata == MARK) { // Space just ended; Record time
  158. irparams.rawbuf[irparams.rawlen++] = irparams.timer;
  159. irparams.timer = 0;
  160. irparams.rcvstate = STATE_MARK;
  161. } else if (irparams.timer > GAP_TICKS) { // Space
  162. // A long Space, indicates gap between codes
  163. // Flag the current code as ready for processing
  164. // Switch to STOP
  165. // Don't reset timer; keep counting Space width
  166. irparams.rcvstate = STATE_STOP;
  167. }
  168. break;
  169. //......................................................................
  170. case STATE_STOP: // Waiting; Measuring Gap
  171. if (irdata == MARK) irparams.timer = 0 ; // Reset gap timer
  172. break;
  173. //......................................................................
  174. case STATE_OVERFLOW: // Flag up a read overflow; Stop the State Machine
  175. irparams.overflow = true;
  176. irparams.rcvstate = STATE_STOP;
  177. break;
  178. }
  179. // If requested, flash LED while receiving IR data
  180. if (irparams.blinkflag) {
  181. if (irdata == MARK)
  182. if (irparams.blinkpin) digitalWrite(irparams.blinkpin, HIGH); // Turn user defined pin LED on
  183. else BLINKLED_ON() ; // if no user defined LED pin, turn default LED pin for the hardware on
  184. else if (irparams.blinkpin) digitalWrite(irparams.blinkpin, LOW); // Turn user defined pin LED on
  185. else BLINKLED_OFF() ; // if no user defined LED pin, turn default LED pin for the hardware on
  186. }
  187. }