IRremote
IRReceive.hpp
Go to the documentation of this file.
1 /*
2  * IRReceive.hpp
3  * This file is exclusively included by IRremote.h to enable easy configuration of library switches
4  *
5  * Contains all IRrecv class functions as well as other receiver related functions.
6  *
7  * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
8  *
9  ************************************************************************************
10  * MIT License
11  *
12  * Copyright (c) 2009-2026 Ken Shirriff, Rafi Khan, Armin Joachimsmeyer
13  *
14  * Permission is hereby granted, free of charge, to any person obtaining a copy
15  * of this software and associated documentation files (the "Software"), to deal
16  * in the Software without restriction, including without limitation the rights
17  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18  * copies of the Software, and to permit persons to whom the Software is furnished
19  * to do so, subject to the following conditions:
20  *
21  * The above copyright notice and this permission notice shall be included in all
22  * copies or substantial portions of the Software.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
25  * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
26  * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27  * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
28  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
29  * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30  *
31  ************************************************************************************
32  */
33 #ifndef _IR_RECEIVE_HPP
34 #define _IR_RECEIVE_HPP
35 
36 // This block must be located after the includes of other *.hpp files
37 //#define LOCAL_DEBUG // This enables debug output only for this file - only for development
38 #include "LocalDebugLevelStart.h"
39 /*
40  * Low level hardware timing measurement
41  */
42 //#define _IR_MEASURE_TIMING // for ISR
43 //#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
44 //
45 #if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
46 #define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
47 #endif
48 
49 unsigned long sMicrosAtLastStopTimer = 0; // Used to adjust TickCounterForISR with uncounted ticks between stopTimer() and restartTimer()
50 
58 
64  setReceivePin(0);
65 }
66 
67 IRrecv::IRrecv(uint_fast8_t aReceivePin) {
68  setReceivePin(aReceivePin);
69 }
70 
76 IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
77  setReceivePin(aReceivePin);
78 #if defined(LED_RECEIVE_FEEDBACK_CODE)
79  setLEDFeedbackPin(aFeedbackLEDPin);
80 #else
81  (void) aFeedbackLEDPin;
82 #endif
83 }
84 
85 /**********************************************************************************************************************
86  * Interrupt Service Routine - Called every 50 us
87  *
88  * Duration in ticks of 50 us of alternating SPACE, MARK are recorded in irparams.rawbuf array.
89  * 'rawlen' counts the number of entries recorded so far.
90  * First entry is the SPACE between transmissions.
91  *
92  * As soon as one SPACE entry gets longer than RECORD_GAP_TICKS, state switches to STOP (frame received). Timing of SPACE continues.
93  * A call of resume() switches from STOP to IDLE.
94  * As soon as first MARK arrives in IDLE, gap width is recorded and new logging starts.
95  *
96  * With digitalRead and Feedback LED
97  * 15 pushs, 1 in, 1 eor before start of code = 2 us @16MHz + * 7.2 us computation time (6us idle time) + * pop + reti = 2.25 us @16MHz => 10.3 to 11.5 us @16MHz
98  * With portInputRegister and mask and Feedback LED code commented
99  * 9 pushs, 1 in, 1 eor before start of code = 1.25 us @16MHz + * 2.25 us computation time + * pop + reti = 1.5 us @16MHz => 5 us @16MHz
100  * => Minimal CPU frequency is 4 MHz
101  *
102  **********************************************************************************************************************/
103 #if defined(ESP8266) || defined(ESP32)
104 #pragma GCC diagnostic push
105 #pragma GCC diagnostic ignored "-Wvolatile"
106 IRAM_ATTR
107 #endif
108 
110 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
111  digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
112 #endif
113 // 7 - 8.5 us for ISR body (without pushes and pops) for ATmega328 @16MHz
114 
115 #if defined(TIMER_REQUIRES_RESET_INTR_PENDING)
116  timerResetInterruptPending(); // reset TickCounterForISR interrupt flag if required (currently only for Teensy and ATmega4809)
117 #endif
118 
119 // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
120 #if defined(__AVR__)
121  uint8_t tIRInputLevel = *irparams.IRReceivePinPortInputRegister & irparams.IRReceivePinMask;
122 #else
123  uint_fast8_t tIRInputLevel = (uint_fast8_t) digitalReadFast(irparams.IRReceivePin);
124 #endif
125 
126  uint_fast16_t tTickCounterForISR = irparams.TickCounterForISR;
127  /*
128  * Increase TickCounter and clip it at maximum 0xFFFF / 3.2 seconds at 50 us ticks
129  */
130  if (irparams.TickCounterForISR < UINT16_MAX) {
131  tTickCounterForISR++; // One more 50uS tick
132  irparams.TickCounterForISR = tTickCounterForISR;
133  }
134 
135  /*
136  * Due to a ESP32 compiler bug https://github.com/espressif/esp-idf/issues/1552 no switch statements are possible for ESP32
137  * So we change the code to if / else if
138  */
139 // switch (irparams.StateForISR) {
140 //
141  uint_fast8_t tStateForISR = irparams.StateForISR;
142  if (tStateForISR == IR_REC_STATE_IDLE) {
143  /*
144  * Here we are just resumed and wait for start bit. But in real time we may be in the middle of an ongoing transmission!
145  */
146  if (tIRInputLevel == INPUT_MARK) {
147  // Check if we are not in the middle of an ongoing transmission by checking the minimum length of leading space
148  if (tTickCounterForISR > RECORD_GAP_TICKS) {
149 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
150 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
151 #endif
152  /*
153  * Big gap between two transmissions just ended; Record gap duration + start recording transmission
154  * Initialize all state machine variables
155  */
156  irparams.OverflowFlag = false;
157  // irparams.rawbuf[0] = irparams.TickCounterForISR;
158  // Usage of initialGapTicks enables usage of 8 bit buffer instead of 16 bit since 4.4,
159  // because the big gap value is not stored in this buffer any more
160  irparams.initialGapTicks = tTickCounterForISR;
161  irparams.rawlen = 1;
163  } // otherwise stay in idle state
164  irparams.TickCounterForISR = 0; // reset counter in both cases
165  }
166 
167  } else if (tStateForISR == IR_REC_STATE_MARK) {
168  // Timing mark here, rawlen is even
169  if (tIRInputLevel != INPUT_MARK) {
170  /*
171  * Mark ended here. Record mark time in rawbuf array
172  */
173 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
174 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
175 #endif
176 #if !defined(USE_16_BIT_TIMING_BUFFER)
177  // Clip timings > 12750 us (255 * 50) to 12750
178  if (tTickCounterForISR > UINT8_MAX) {
179  tTickCounterForISR = UINT8_MAX;
180  }
181 #endif
182  irparams.rawbuf[irparams.rawlen++] = tTickCounterForISR; // record mark
184  irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-)
185  }
186 
187  } else if (tStateForISR == IR_REC_STATE_SPACE) {
188  /*
189  * Timing space here, rawlen is odd
190  * Check for timeout or overflow
191  */
192  if (tTickCounterForISR > RECORD_GAP_TICKS || irparams.rawlen >= RAW_BUFFER_LENGTH - 1) {
194  // Flag up a read OverflowFlag; Stop the state machine
195  irparams.OverflowFlag = true;
196  }
197  /*
198  * Overflow or maximum space duration reached here.
199  * Current code is ready for processing!
200  * We received a long space, which indicates gap between codes.
201  * Switch to IR_REC_STATE_STOP
202  * Don't reset TickCounterForISR; keep counting width of next leading space
203  */
204  /*
205  * These 2 variables allow to call resume() directly after decode.
206  * After resume(), irparams.initialGapTicks and irparams.rawlen are
207  * the first variables, which are overwritten by the next received frame.
208  * since 4.3.0.
209  * For backward compatibility, there are the same 2 statements in decode() if IrReceiver is not used.
210  */
213 
214  irparams.StateForISR = IR_REC_STATE_STOP; // This signals the decode(), that a complete frame was received
215 #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
216  /*
217  * Call callback if registered (not nullptr)
218  */
219  if (irparams.ReceiveCompleteCallbackFunction != nullptr) {
220 #if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) && !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled
221  interrupts(); // To enable the receiving for the other instances while in callback
222 #endif
224  }
225 #endif
226  } else if (tIRInputLevel == INPUT_MARK) {
227  /*
228  * Space ended here.
229  */
230 
231 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
232 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
233 #endif
234 #if !defined(USE_16_BIT_TIMING_BUFFER)
235  // Clip timings > 12750 us (255 * 50) to 12750
236  if (tTickCounterForISR > UINT8_MAX) {
237  tTickCounterForISR = UINT8_MAX;
238  }
239 #endif
240  irparams.rawbuf[irparams.rawlen++] = tTickCounterForISR; // record space
243  }
244  } else if (tStateForISR == IR_REC_STATE_STOP) {
245  /*
246  * Complete command received
247  * stay here until resume() is called, which switches state to IR_REC_STATE_IDLE
248  */
249 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
250 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
251 #endif
252  if (tIRInputLevel == INPUT_MARK) {
253  // Reset gap TickCounterForISR, to prepare for detection if we are in the middle of a transmission after call of resume()
255  }
256  }
257 
258 #if defined(LED_RECEIVE_FEEDBACK_CODE)
260  setFeedbackLED(tIRInputLevel == INPUT_MARK);
261  }
262 #endif
263 
264 #ifdef _IR_MEASURE_TIMING
265  digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
266 #endif
267 
268 }
269 /*
270  * The handler which directly calls the interrupt handler function of the IRrecv object.
271  * This must be a separate function, because we need this static function in IRTimer.hpp.
272  * Doing it this way, we are able to modify the body of this function to support more than 2 IRrecv instances for receiving
273  */
274 #if defined(ESP8266) || defined(ESP32)
275 IRAM_ATTR
276 #endif
279 #if defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES)
280  // Quick and dirty solution by used defined extension
281  UserIRReceiveTimerInterruptHandler();
282 #endif
283 }
284 
285 /**********************************************************************************************************************
286  * Interrupt Service Routine - Called every 50 us
287  * This in turn calls calls the static interrupt handler function, which in turn calls the interrupt handler function of the IRrecv object
288  */
289 #if defined(TIMER_INTR_NAME) || defined(ISR)
290 # if defined(TIMER_INTR_NAME)
291 ISR (TIMER_INTR_NAME) // for ISR definitions
292 # elif defined(ISR)
293 ISR()
294 // for functions definitions which are called by separate (board specific) ISR
295 # endif
296 {
298 }
299 #endif
300 
301 /**********************************************************************************************************************
302  * Stream like API
303  **********************************************************************************************************************/
304 
311 void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
312 
313  setReceivePin(aReceivePin);
314 #if defined(LED_RECEIVE_FEEDBACK_CODE)
315  setLEDFeedback(aEnableLEDFeedback);
316  setLEDFeedbackPin(aFeedbackLEDPin);
317 #else
318  (void) aEnableLEDFeedback;
319  (void) aFeedbackLEDPin;
320 #endif
321 
322 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
323  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
324 #endif
325  start();
326 }
327 
331 void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) {
332  irparams.IRReceivePin = aReceivePinNumber;
333 #if defined(__AVR__)
334 # if defined(__digitalPinToBit)
335  if (__builtin_constant_p(aReceivePinNumber)) {
336  irparams.IRReceivePinMask = 1UL << (__digitalPinToBit(aReceivePinNumber));
337  } else {
338  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
339  }
340 # else
341  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
342 # endif
343 # if defined(__digitalPinToPINReg)
344  /*
345  * This code is 54 bytes smaller, if aReceivePinNumber is a constant :-), but 38 byte longer if it is not constant (,which is not likely).
346  */
347  if (__builtin_constant_p(aReceivePinNumber)) {
348  irparams.IRReceivePinPortInputRegister = __digitalPinToPINReg(aReceivePinNumber);
349  } else {
350  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
351  }
352 # else
353  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
354 # endif
355 #endif
356  // Seems to be at least required by ESP32
357  // Set pin mode once. pinModeFast makes no difference if used, but saves 224 if not referenced :-(
358  if (__builtin_constant_p(aReceivePinNumber)) {
359  pinModeFast(aReceivePinNumber, INPUT);
360  } else {
361  pinModeFast(aReceivePinNumber, INPUT);
362  }
363 }
364 
365 #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
366 
369 void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) {
370  irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction;
371 }
372 #endif
373 
380 
381  // Setup for cyclic 50 us interrupt
382  timerConfigForReceive(); // no interrupts enabled here!
383 
384  // Initialize state machine state
385  resume();
386 
387  // Timer interrupt is enabled after state machine reset
388  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
389 #ifdef _IR_MEASURE_TIMING
390  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
391 #endif
392 }
393 
394 /*
395  * Restarts timer interrupts, adjusts TickCounterForISR for correct gap value after stopTimer(). Does not call resume()!
396  */
398  // Setup for cyclic 50 us interrupt
399  timerConfigForReceive(); // no interrupts enabled here!
400  // Timer interrupt is enabled after state machine reset
401  if (sMicrosAtLastStopTimer != 0) {
402  irparams.TickCounterForISR += (micros() - sMicrosAtLastStopTimer) / MICROS_PER_TICK; // adjust TickCounterForISR for correct gap value, which is used for repeat detection
404  }
405  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
406 #ifdef _IR_MEASURE_TIMING
407  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
408 #endif
409 }
414  start();
415 }
416 
427 void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) {
428  irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
429  timerConfigForReceive(); // no interrupts enabled here!
430  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
431 #ifdef _IR_MEASURE_TIMING
432  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
433 #endif
434 }
439 void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
440  irparams.TickCounterForISR += aTicksToAddToGapCounter;
441  timerConfigForReceive(); // no interrupts enabled here!
442  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
443 #ifdef _IR_MEASURE_TIMING
444  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
445 #endif
446 }
447 #if defined(ESP8266) || defined(ESP32)
448 #pragma GCC diagnostic push
449 #endif
450 
455 #if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
456  start();
457 #endif
458 }
459 
463 void IRrecv::stop() {
465 }
466 
467 /*
468  * Stores microseconds of stop, to adjust TickCounterForISR in restartTimer()
469  */
472  sMicrosAtLastStopTimer = micros();
473 }
478  stop();
479 }
483 void IRrecv::end() {
484  stop();
485 }
486 
492  // This check allows to call resume at arbitrary places or more than once
495  }
496 }
497 
503 
504  if (irparams.OverflowFlag) {
506 
507  DEBUG_PRINT(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of "));
509  DEBUG_PRINTLN(F(" with #define RAW_BUFFER_LENGTH=<biggerValue>"));
510 
511  } else {
513  // save last protocol, command and address for repeat handling (where they are compared or copied back :-))
514  lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC, Samsung and LG), so we must keep the original one
517 
518  }
524 }
525 
531 }
532 
538 }
539 
545  return nullptr;
546  }
547  if (decode()) {
548  return &decodedIRData;
549  } else {
550  return nullptr;
551  }
552 }
553 
562  return false;
563  }
564 
565  /*
566  * Support for old examples, which do not use the default IrReceiver instance
567  */
568  if (this != &IrReceiver) {
571  }
572 
573  initDecodedIRData(); // sets IRDATA_FLAGS_WAS_OVERFLOW
574 
576  /*
577  * Set OverflowFlag flag and return true here, to let the loop call resume or print raw data.
578  */
580  return true;
581  }
582 
583 #if defined(DECODE_NEC) || defined(DECODE_ONKYO)
584  TRACE_PRINTLN(F("Attempting NEC/Onkyo decode"));
585  if (decodeNEC()) {
586  return true;
587  }
588 #endif
589 
590 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
591  TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode"));
592  if (decodeKaseikyo()) {
593  return true;
594  }
595 #endif
596 
597 #if defined(DECODE_DENON)
598  TRACE_PRINTLN(F("Attempting Denon/Sharp decode"));
599  if (decodeDenon()) {
600  return true;
601  }
602 #endif
603 
604 #if defined(DECODE_SONY)
605  TRACE_PRINTLN(F("Attempting Sony decode"));
606  if (decodeSony()) {
607  return true;
608  }
609 #endif
610 
611 #if defined(DECODE_RC5) || defined(DECODE_MARANTZ)
612 # if defined(DECODE_RC5) && !defined(DECODE_MARANTZ)
613  TRACE_PRINTLN(F("Attempting RC5 decode"));
614 # elif !defined(DECODE_RC5) && defined(DECODE_MARANTZ)
615  TRACE_PRINTLN(F("Attempting Marantz decode"));
616 # else
617  TRACE_PRINTLN(F("Attempting RC5 and Marantz decode"));
618 # endif
619  if (decodeRC5()) {
620  return true;
621  }
622 #endif
623 
624 #if defined(DECODE_RC6)
625  TRACE_PRINTLN(F("Attempting RC6 decode"));
626  if (decodeRC6()) {
627  return true;
628  }
629 #endif
630 
631 #if defined(DECODE_LG)
632  TRACE_PRINTLN(F("Attempting LG decode"));
633  if (decodeLG()) {
634  return true;
635  }
636 #endif
637 
638 #if defined(DECODE_JVC)
639  TRACE_PRINTLN(F("Attempting JVC decode"));
640  if (decodeJVC()) {
641  return true;
642  }
643 #endif
644 
645 #if defined(DECODE_SAMSUNG)
646  TRACE_PRINTLN(F("Attempting Samsung decode"));
647  if (decodeSamsung()) {
648  return true;
649  }
650 #endif
651  /*
652  * Start of the exotic protocols
653  */
654 
655 #if defined(DECODE_BEO)
656  TRACE_PRINTLN(F("Attempting Bang & Olufsen decode"));
657  if (decodeBangOlufsen()) {
658  return true;
659  }
660 #endif
661 
662 #if defined(DECODE_FAST)
663  TRACE_PRINTLN(F("Attempting FAST decode"));
664  if (decodeFAST()) {
665  return true;
666  }
667 #endif
668 
669 #if defined(DECODE_WHYNTER)
670  TRACE_PRINTLN(F("Attempting Whynter decode"));
671  if (decodeWhynter()) {
672  return true;
673  }
674 #endif
675 
676 #if defined(DECODE_LEGO_PF)
677  TRACE_PRINTLN(F("Attempting Lego Power Functions"));
678  if (decodeLegoPowerFunctions()) {
679  return true;
680  }
681 #endif
682 
683 #if defined(DECODE_BOSEWAVE)
684  TRACE_PRINTLN(F("Attempting Bosewave decode"));
685  if (decodeBoseWave()) {
686  return true;
687  }
688 #endif
689 
690 #if defined(DECODE_MAGIQUEST)
691  TRACE_PRINTLN(F("Attempting MagiQuest decode"));
692  if (decodeMagiQuest()) {
693  return true;
694  }
695 #endif
696 
697 #if defined(DECODE_OPENLASIR)
698  TRACE_PRINTLN(F("Attempting OpenLASIR decode"));
699  if (decodeOpenLASIR()) {
700  return true;
701  }
702 #endif
703 
704  /*
705  * Try the universal decoder for pulse distance protocols
706  */
707 #if defined(DECODE_DISTANCE_WIDTH)
708  TRACE_PRINTLN(F("Attempting universal Distance Width decode"));
709  if (decodeDistanceWidth()) {
710  return true;
711  }
712 #endif
713 
714  /*
715  * Last resort is the universal hash decode which always return true
716  */
717 #if defined(DECODE_HASH)
718  TRACE_PRINTLN(F("Hash decode"));
719  // decodeHash returns a hash on any input.
720  // Thus, it needs to be last in the list.
721  // If you add any decodes, add them before this.
722  if (decodeHash()) {
723  return true;
724  }
725 #endif
726 
727  /*
728  * Return true here, to let the loop decide to call resume or to print raw data.
729  */
730  return true;
731 }
732 
733 /**********************************************************************************************************************
734  * Common decode functions
735  **********************************************************************************************************************/
755 void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMicros,
756  bool aIsPulseWidthProtocol, bool aMSBfirst) {
757 
758  DEBUG_PRINT(F("aOneMicros="));
759  DEBUG_PRINT(aOneMicros);
760  DEBUG_PRINT(F(", 0.75*aOneMicros="));
761  DEBUG_PRINT((aOneMicros * 3) / 4);
762  DEBUG_PRINT(F(", MARK_EXCESS_MICROS=" STR(MARK_EXCESS_MICROS) " isPulseWidthProtocol="));
763  DEBUG_PRINT(aIsPulseWidthProtocol);
764  DEBUG_PRINTLN();
765 
766  IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
767  IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first
768  auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
769 
770  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
771 
772  bool tBitValue;
773  uint16_t tCurrentTicks;
774  if (aIsPulseWidthProtocol) {
775  /*
776  * PULSE_WIDTH here.
777  * !!!We only check variable length mark indicating a 1 or 0!!!
778  */
779  tCurrentTicks = *tRawBufPointer++;
780  tBitValue = matchMark(tCurrentTicks, aOneMicros); // Check for variable length mark indicating a 1 or 0
781  tRawBufPointer++;
782  } else {
783  /*
784  * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
785  * !!!We only check variable length space indicating a 1 or 0!!!
786  */
787  tRawBufPointer++;
788  tCurrentTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
789  tBitValue = matchSpace(tCurrentTicks, aOneMicros); // Check for variable length space indicating a 1 or 0
790  }
791 
792  if (aMSBfirst) {
793  tDecodedData <<= 1;
794  }
795 
796  if (tBitValue) {
797  // It's a 1 -> set the bit
798  if (aMSBfirst) {
799  tDecodedData |= 1;
800  } else {
801  tDecodedData |= tMask;
802  }
803  TRACE_PRINT(tCurrentTicks);
804  TRACE_PRINTLN(F(" => 1"));
805  } else {
806  // do not set the bit
807  TRACE_PRINT(tCurrentTicks);
808  TRACE_PRINTLN(F(" => 0"));
809  }
810  tMask <<= 1;
811  }
812  decodedIRData.decodedRawData = tDecodedData;
813 }
814 
833 void IRrecv::decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset,
834  uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst) {
835 
836  DEBUG_PRINT(F("OneThresholdMicros="));
837  DEBUG_PRINT(aOneThresholdMicros);
838  DEBUG_PRINT(F(" isPulseWidthProtocol="));
839  DEBUG_PRINT(aIsPulseWidthProtocol);
840  DEBUG_PRINTLN();
841 
842  IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
843  IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first
844  auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
845 
846  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
847 
848  if (!aIsPulseWidthProtocol) {
849  tRawBufPointer++;
850  }
851  uint16_t tCurrentMicros = *tRawBufPointer * MICROS_PER_TICK;
852  bool tBitValue = tCurrentMicros > aOneThresholdMicros; // Check for variable length timing indicating a 1 or 0
853  tRawBufPointer++;
854 
855  if (aIsPulseWidthProtocol) {
856  tRawBufPointer++;
857  }
858 
859  if (aMSBfirst) {
860  tDecodedData <<= 1;
861  }
862 
863  if (tBitValue) {
864  // It's a 1 -> set the bit
865  if (aMSBfirst) {
866  tDecodedData |= 1;
867  } else {
868  tDecodedData |= tMask;
869  }
870  TRACE_PRINT(tCurrentMicros);
871  TRACE_PRINTLN(F(" => 1"));
872  } else {
873  // do not set the bit
874  TRACE_PRINT(tCurrentMicros);
875  TRACE_PRINTLN(F(" => 0"));
876  }
877  tMask <<= 1;
878  }
879  decodedIRData.decodedRawData = tDecodedData;
880 }
881 
885 void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
886  uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) {
887 
888  auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
889 
890  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we check aOneSpaceMicros -> pulse distance protocol
891 
892  IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
893  IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first
894 
895  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
896  // get one mark and space pair
897  unsigned int tMarkTicks;
898  unsigned int tSpaceTicks;
899  bool tBitValue;
900 
901  if (isPulseDistanceProtocol) {
902  /*
903  * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
904  * !!!We only check variable length space indicating a 1 or 0!!!
905  */
906  tRawBufPointer++;
907  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
908  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
909 
910  } else {
911  /*
912  * PULSE_WIDTH here.
913  * !!!We only check variable length mark indicating a 1 or 0!!!
914  */
915  tMarkTicks = *tRawBufPointer++;
916  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
917  tRawBufPointer++;
918  }
919 
920  if (aMSBfirst) {
921  tDecodedData <<= 1;
922  }
923 
924  if (tBitValue) {
925  // It's a 1 -> set the bit
926  if (aMSBfirst) {
927  tDecodedData |= 1;
928  } else {
929  tDecodedData |= tMask;
930  }
931  TRACE_PRINTLN(F("=> 1"));
932  } else {
933  // do not set the bit
934  TRACE_PRINTLN(F("=> 0"));
935  }
936  tMask <<= 1;
937  }
938  decodedIRData.decodedRawData = tDecodedData;
939 }
940 
941 /*
942  * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter
943  */
944 void IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
945  uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
946 
947  (void) aZeroSpaceMicros;
948  decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aOneMarkMicros, aZeroMarkMicros, aOneSpaceMicros, aMSBfirst);
949 }
950 
951 /*
952  * Only sensible for development or very exotic requirements. - Not used yet
953  * Check for additional required characteristics of timing like length of mark for a constant mark protocol,
954  * where space length determines the bit value. Requires up to 194 additional bytes of program memory.
955  *
956  * @param aZeroMarkMicros For strict checks
957  * @param aZeroSpaceMicros For strict checks
958  * @return true if decoding successful
959  *
960  */
961 bool IRrecv::decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
962  uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
963 
964  auto *tRawBufPointer = &irparams.rawbuf[aStartOffset];
965 
966  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
967 
968  IRDecodedRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
969  IRDecodedRawDataType tMask = 1UL; // Mask is only used for LSB first
970 
971  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
972  // get one mark and space pair
973  unsigned int tMarkTicks;
974  unsigned int tSpaceTicks;
975  bool tBitValue;
976 
977  if (isPulseDistanceProtocol) {
978  /*
979  * PULSE_DISTANCE here (aOneMarkMicros == aZeroMarkMicros)
980  * We additionally check constant mark duration and in case of zero the zero space duration.
981  */
982  tMarkTicks = *tRawBufPointer++;
983  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
984  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
985 
986  // Check for constant mark duration
987  if (!matchMark(tMarkTicks, aOneMarkMicros)) {
988  DEBUG_PRINT(F("Mark="));
989  DEBUG_PRINT(tMarkTicks * MICROS_PER_TICK);
990  DEBUG_PRINT(F(" is not "));
991  DEBUG_PRINT(aOneMarkMicros);
992  DEBUG_PRINT(F(". Index="));
993  DEBUG_PRINT(aNumberOfBits - i);
994  DEBUG_PRINT(' ');
995  return false;
996  }
997 
998  // in case of 0, check for zero space duration
999  if (!tBitValue && !matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
1000  DEBUG_PRINT(F("Space="));
1001  DEBUG_PRINT(tSpaceTicks * MICROS_PER_TICK);
1002  DEBUG_PRINT(F(" is not "));
1003  DEBUG_PRINT(aZeroSpaceMicros);
1004  DEBUG_PRINT(F(". Index="));
1005  DEBUG_PRINT(aNumberOfBits - i);
1006  DEBUG_PRINT(' ');
1007  return false;
1008  }
1009 
1010  } else {
1011  /*
1012  * PULSE_WIDTH -including PULSE_DISTANCE_WIDTH- here.
1013  * We additionally check two space durations and in case of zero the zero mark duration.
1014  */
1015  tMarkTicks = *tRawBufPointer++;
1016  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
1017  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
1018 
1019  // Check for space length, which is not constant in case of PULSE_DISTANCE_WIDTH
1020  if ((tBitValue && !matchSpace(tSpaceTicks, aOneSpaceMicros))
1021  || ((!tBitValue && !matchSpace(tSpaceTicks, aZeroSpaceMicros)))) {
1022  DEBUG_PRINT(F("Space="));
1023  DEBUG_PRINT(tSpaceTicks * MICROS_PER_TICK);
1024  DEBUG_PRINT(F(" is not "));
1025  DEBUG_PRINT(aOneSpaceMicros);
1026  DEBUG_PRINT(F(" or "));
1027  DEBUG_PRINT(aZeroSpaceMicros);
1028  DEBUG_PRINT(F(". Index="));
1029  DEBUG_PRINT(aNumberOfBits - i);
1030  DEBUG_PRINT(' ');
1031  return false;
1032  }
1033  if (!tBitValue && !matchMark(tMarkTicks, aZeroMarkMicros)) {
1034  DEBUG_PRINT(F("Mark="));
1035  DEBUG_PRINT(tMarkTicks * MICROS_PER_TICK);
1036  DEBUG_PRINT(F(" is not "));
1037  DEBUG_PRINT(aZeroMarkMicros);
1038  DEBUG_PRINT(F(". Index="));
1039  DEBUG_PRINT(aNumberOfBits - i);
1040  DEBUG_PRINT(' ');
1041  return false;
1042  }
1043  }
1044 
1045  if (aMSBfirst) {
1046  tDecodedData <<= 1;
1047  }
1048 
1049  if (tBitValue) {
1050  // It's a 1 -> set the bit
1051  if (aMSBfirst) {
1052  tDecodedData |= 1;
1053  } else {
1054  tDecodedData |= tMask;
1055  }
1056  TRACE_PRINTLN(F("=> 1"));
1057  } else {
1058  // do not set the bit
1059  TRACE_PRINTLN(F("=> 0"));
1060  }
1061  tMask <<= 1;
1062  }
1063  decodedIRData.decodedRawData = tDecodedData;
1064  return true;
1065 }
1066 
1071 #if defined(USE_STRICT_DECODER)
1072 bool
1073 #else
1074 void
1075 #endif
1076 IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
1077  IRRawlenType aStartOffset) {
1078 
1079 #if defined(USE_STRICT_DECODER)
1080  return decodeStrictPulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
1081  aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
1082  aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
1083 
1084 #else
1085  bool tIsPulseWidthProtocol = aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK;
1086  uint16_t tThresholdMicros;
1087 
1088 # if defined(USE_THRESHOLD_DECODER)
1089  if (tIsPulseWidthProtocol) {
1090  // we check the length of marks here
1091  tThresholdMicros = ((aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros
1092  + aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros) / 2) - MARK_EXCESS_MICROS;// MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
1093  } else {
1094  // we check the length of spaces here
1095  tThresholdMicros = ((aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros
1096  + aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros) / 2) + MARK_EXCESS_MICROS;// MARK_EXCESS_MICROS is 0 here if not explicitly specified by user
1097  }
1098  return decodeWithThresholdPulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros,
1099  aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
1100 # else
1101  if (tIsPulseWidthProtocol) {
1102  tThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros;
1103  } else {
1104  tThresholdMicros = aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros;
1105  }
1106  decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, tThresholdMicros,
1107  aProtocolConstants->Flags & PROTOCOL_IS_PULSE_WIDTH_MASK, (aProtocolConstants->Flags & PROTOCOL_IS_MSB_MASK));
1108 # endif
1109 #endif
1110 }
1111 
1113  uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset) {
1114 
1115  PulseDistanceWidthProtocolConstants tTemporaryPulseDistanceWidthProtocolConstants;
1116  memcpy_P(&tTemporaryPulseDistanceWidthProtocolConstants, aProtocolConstantsPGM,
1117  sizeof(tTemporaryPulseDistanceWidthProtocolConstants));
1118 
1119  decodePulseDistanceWidthData(&tTemporaryPulseDistanceWidthProtocolConstants, aNumberOfBits, aStartOffset);
1120 }
1121 
1122 /**********************************************************************************************************************
1123  * Internal Hash decode function
1124  **********************************************************************************************************************/
1125 #define FNV_PRIME_32 16777619
1126 #define FNV_BASIS_32 2166136261
1128 
1133 uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
1134  if (newval * 10 < oldval * 8) {
1135  return 0;
1136  }
1137  if (oldval * 10 < newval * 8) {
1138  return 2;
1139  }
1140  return 1;
1141 }
1142 
1161  unsigned long hash = FNV_BASIS_32; // the result is the same no matter if we use a long or unsigned long variable
1162 
1163 // Require at least 6 samples to prevent triggering on noise
1164  if (decodedIRData.rawlen < 6) {
1165  DEBUG_PRINT(F("HASH: Data length="));
1167  DEBUG_PRINTLN(F(" is less than 6"));
1168  return false;
1169  }
1170  for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) {
1171  // Compare mark with mark and space with space
1172  uint_fast8_t value = compare(irparams.rawbuf[i], irparams.rawbuf[i + 2]);
1173  // Add value into the hash - (0 if rawbuf[i + 2] is more than 20 % shorter, 1 if rawbuf[i + 2] is equal, and 2 if rawbuf[i + 2] is longer than rawbuf[i])
1174  hash = (hash * FNV_PRIME_32) ^ value;
1175  }
1176 
1180 
1181  return true;
1182 }
1183 
1185  unsigned long hash = FNV_BASIS_32;
1186 
1187 // Require at least 6 samples to prevent triggering on noise
1188  if (aResults->rawlen < 6) {
1189  return false;
1190  }
1191 
1192  for (uint8_t i = 3; i < aResults->rawlen; i++) {
1193  uint_fast8_t value = compare(aResults->rawbuf[i - 2], aResults->rawbuf[i]);
1194  // Add value into the hash
1195  hash = (hash * FNV_PRIME_32) ^ value;
1196  }
1197 
1198  aResults->value = hash;
1199  aResults->bits = 32;
1200  aResults->decode_type = UNKNOWN;
1202 
1203  return true;
1204 }
1205 
1206 /**********************************************************************************************************************
1207  * Match functions
1208  **********************************************************************************************************************/
1209 
1210 /*
1211  * returns true if values do match
1212  */
1214 // Check header "mark" and "space"
1215  if (!matchMark(irparams.rawbuf[1], aProtocolConstants->DistanceWidthTimingInfo.HeaderMarkMicros)) {
1216  TRACE_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex));
1217  TRACE_PRINTLN(F(": Header mark length is wrong"));
1218  return false;
1219  }
1220  if (!matchSpace(irparams.rawbuf[2], aProtocolConstants->DistanceWidthTimingInfo.HeaderSpaceMicros)) {
1221  TRACE_PRINT(::getProtocolString(aProtocolConstants->ProtocolIndex));
1222  TRACE_PRINTLN(F(": Header space length is wrong"));
1223  return false;
1224  }
1225  return true;
1226 }
1227 
1229 // Check header "mark" and "space"
1230  if (!matchMark(irparams.rawbuf[1], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderMarkMicros))) {
1231  TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex)));
1232  TRACE_PRINTLN(F(": Header mark length is wrong"));
1233  return false;
1234  }
1235  if (!matchSpace(irparams.rawbuf[2], pgm_read_word(&aProtocolConstantsPGM->DistanceWidthTimingInfo.HeaderSpaceMicros))) {
1236  TRACE_PRINT(::getProtocolString((decode_type_t) pgm_read_byte(&aProtocolConstantsPGM->ProtocolIndex)));
1237  TRACE_PRINTLN(F(": Header space length is wrong"));
1238  return false;
1239  }
1240  return true;
1241 }
1242 
1243 /*
1244  * Does not check for same address and command, because it is almost not possible to press 2 different buttons on the remote within around 100 ms.
1245  * And if really required, it can be enabled here, or done manually in user program.
1246  * And we have still no RC6 toggle bit check for detecting a second press on the same button.
1247  */
1248 void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks) {
1249  if (decodedIRData.initialGapTicks < aMaximumRepeatSpaceTicks
1250 #if defined(ENABLE_COMPLETE_REPEAT_CHECK)
1251 // Check also for same command and address values to detect a repeat. Not sensible for standard protocols, because it is almost not possible to press 2 different buttons on the remote within around 100 ms
1252  && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 44 bytes program space */
1253 #endif
1254  ) {
1256  }
1257 }
1258 
1264 bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1265  uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK);
1266  uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4;
1267 
1268  TRACE_PRINT(F("Testing (actual vs desired): "));
1269  TRACE_PRINT(tMeasuredMicros);
1270  TRACE_PRINT(F("us vs "));
1271  TRACE_PRINT(aMatchValueMicros);
1272  TRACE_PRINT(F("us: "));
1273  TRACE_PRINT(tMatchValueMicrosQuarter * 3); // rounded value because we divide first
1274  TRACE_PRINT(F(" <= "));
1275  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1276  TRACE_PRINT(F(" <= "));
1277  TRACE_PRINT(tMatchValueMicrosQuarter * 5);
1278 
1279  bool passed = (tMeasuredMicros >= (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5));
1280 #if defined(LOCAL_TRACE)
1281  if (passed) {
1282  Serial.println(F(" => passed"));
1283  } else {
1284  Serial.println(F(" => FAILED"));
1285  }
1286 #endif
1287  return passed;
1288 }
1289 
1294 bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros, int16_t aCompensationMicrosForTicks) {
1295  uint16_t tMeasuredMicros = (aMeasuredTicks * MICROS_PER_TICK) + aCompensationMicrosForTicks;
1296  uint16_t tMatchValueMicrosQuarter = aMatchValueMicros / 4;
1297 
1298  TRACE_PRINT(F("Testing (actual vs desired): "));
1299  TRACE_PRINT(tMeasuredMicros);
1300  TRACE_PRINT(F("us vs "));
1301  TRACE_PRINT(aMatchValueMicros);
1302  TRACE_PRINT(F("us: "));
1303  TRACE_PRINT(tMatchValueMicrosQuarter * 3); // rounded value because we divide first
1304  TRACE_PRINT(F(" < "));
1305  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1306  TRACE_PRINT(F(" <= "));
1307  TRACE_PRINT(tMatchValueMicrosQuarter * 5);
1308 
1309  bool passed = (tMeasuredMicros > (tMatchValueMicrosQuarter * 3) && tMeasuredMicros <= (tMatchValueMicrosQuarter * 5));
1310 #if defined(LOCAL_TRACE)
1311  if (passed) {
1312  Serial.println(F(" => passed"));
1313  } else {
1314  Serial.println(F(" => FAILED"));
1315  }
1316 #endif
1317  return passed;
1318 }
1319 bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
1320  return matchTicks(measured_ticks, desired_us);
1321 }
1322 
1327 bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1328 #if (MARK_EXCESS_MICROS == 0)
1329  return matchTicks(aMeasuredTicks, aMatchValueMicros);
1330 #else
1331 
1332 # if !defined(USE_OLD_MATCH_FUNCTIONS)
1333  return matchTicks(aMeasuredTicks, aMatchValueMicros, -MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors
1334 # endif
1335 
1336  // old version here
1337  aMatchValueMicros += MARK_EXCESS_MICROS;
1338 
1339  TRACE_PRINT(F("Testing mark (actual vs desired): "));
1340  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1341  TRACE_PRINT(F("us vs "));
1342  TRACE_PRINT(aMatchValueMicros);
1343  TRACE_PRINT(F("us: "));
1344 // TRACE_PRINT(F("TICKS_LOW="));
1345 // TRACE_PRINT(TICKS_LOW(aMatchValueMicros));
1346 // TRACE_PRINT(F(" "));
1347  TRACE_PRINT(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK);
1348  TRACE_PRINT(F(" <= "));
1349  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1350  TRACE_PRINT(F(" <= "));
1351  TRACE_PRINT(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK);
1352 
1353  // compensate for marks exceeded by demodulator hardware
1354  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros))
1355  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
1356 # if defined(LOCAL_TRACE)
1357  if (passed) {
1358  Serial.println(F(" => passed"));
1359  } else {
1360  Serial.println(F(" => FAILED"));
1361  }
1362 # endif
1363  return passed;
1364 #endif
1365 }
1366 
1367 bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
1368  return matchMark(measured_ticks, desired_us);
1369 }
1370 
1375 bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1376 #if (MARK_EXCESS_MICROS == 0)
1377  return matchTicks(aMeasuredTicks, aMatchValueMicros);
1378 #else
1379 # if !defined(USE_OLD_MATCH_FUNCTIONS)
1380  return matchTicks(aMeasuredTicks, aMatchValueMicros, MARK_EXCESS_MICROS); // New handling of MARK_EXCESS_MICROS without strange rounding errors
1381 # endif
1382  // old version here
1383  aMatchValueMicros -= MARK_EXCESS_MICROS;
1384 
1385  TRACE_PRINT(F("Testing space (actual vs desired): "));
1386  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1387  TRACE_PRINT(F("us vs "));
1388  TRACE_PRINT(aMatchValueMicros);
1389  TRACE_PRINT(F("us: "));
1390  TRACE_PRINT(F("LOW="));
1391  TRACE_PRINT(TICKS_LOW(aMatchValueMicros));
1392  TRACE_PRINT(F(" "));
1393  TRACE_PRINT(TICKS_LOW(aMatchValueMicros) * MICROS_PER_TICK);
1394  TRACE_PRINT(F(" <= "));
1395  TRACE_PRINT(aMeasuredTicks * MICROS_PER_TICK);
1396  TRACE_PRINT(F(" <= "));
1397  TRACE_PRINT(TICKS_HIGH(aMatchValueMicros) * MICROS_PER_TICK);
1398 
1399  // compensate for spaces shortened by demodulator hardware
1400  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros))
1401  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
1402 # if defined(LOCAL_TRACE)
1403  if (passed) {
1404  Serial.println(F(" => passed"));
1405  } else {
1406  Serial.println(F(" => FAILED"));
1407  }
1408 # endif
1409  return passed;
1410 #endif
1411 }
1412 
1413 bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) {
1414  return matchSpace(measured_ticks, desired_us);
1415 }
1416 
1421  return MARK_EXCESS_MICROS;
1422 }
1423 
1429 bool IRrecv::checkForRecordGapsMicros(Print *aSerial) {
1430  /*
1431  * Check if protocol is not detected and detected space between two transmissions
1432  * is smaller than known value for protocols (Sony with around 24 ms)
1433  */
1436  aSerial->println();
1437  aSerial->print(F("Space of "));
1438  aSerial->print(decodedIRData.initialGapTicks * MICROS_PER_TICK);
1439  aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of "));
1440  aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD);
1441  aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC5 etc.."));
1442  aSerial->println(F("But it can be OK for some yet unsupported protocols, and especially for repeats."));
1443  aSerial->println(F("If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h."));
1444  aSerial->println();
1445  return true;
1446  }
1447  return false;
1448 }
1449 
1450 /**********************************************************************************************************************
1451  * Print functions
1452  * Since a library should not allocate the "Serial" object, all functions require a pointer to a Print object.
1453  **********************************************************************************************************************/
1454 void IRrecv::printActiveIRProtocols(Print *aSerial) {
1455 // call no class function with same name
1456  ::printActiveIRProtocols(aSerial);
1457 }
1458 /*
1459  * Prints a list of enabled protocols for this application.
1460  * @param aSerial pointer to serial used for printing. Use "&Serial".
1461  */
1462 void printActiveIRProtocols(Print *aSerial) {
1463 #if defined(DECODE_ONKYO)
1464  aSerial->print(F("Onkyo, "));
1465 #elif defined(DECODE_NEC)
1466  aSerial->print(F("NEC/NEC2/Onkyo/Apple, "));
1467 #endif
1468 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
1469  aSerial->print(F("Panasonic/Kaseikyo, "));
1470 #endif
1471 #if defined(DECODE_DENON)
1472  aSerial->print(F("Denon/Sharp, "));
1473 #endif
1474 #if defined(DECODE_SONY)
1475  aSerial->print(F("Sony, "));
1476 #endif
1477 #if defined(DECODE_RC5)
1478  aSerial->print(F("RC5, "));
1479 #endif
1480 #if defined(DECODE_RC6)
1481  aSerial->print(F("RC6, "));
1482 #endif
1483 #if defined(DECODE_LG)
1484  aSerial->print(F("LG, "));
1485 #endif
1486 #if defined(DECODE_JVC)
1487  aSerial->print(F("JVC, "));
1488 #endif
1489 #if defined(DECODE_SAMSUNG)
1490  aSerial->print(F("Samsung, "));
1491 #endif
1492  /*
1493  * Start of the exotic protocols
1494  */
1495 #if defined(DECODE_BEO)
1496  aSerial->print(F("Bang & Olufsen, "));
1497 #endif
1498 #if defined(DECODE_FAST)
1499  aSerial->print(F("FAST, "));
1500 #endif
1501 #if defined(DECODE_WHYNTER)
1502  aSerial->print(F("Whynter, "));
1503 #endif
1504 #if defined(DECODE_LEGO_PF)
1505  aSerial->print(F("Lego Power Functions, "));
1506 #endif
1507 #if defined(DECODE_BOSEWAVE)
1508  aSerial->print(F("Bosewave, "));
1509 #endif
1510 #if defined(DECODE_MAGIQUEST)
1511  aSerial->print(F("MagiQuest, "));
1512 #endif
1513 #if defined(DECODE_OPENLASIR)
1514  aSerial->print(F("OpenLASIR, "));
1515 #endif
1516 #if defined(DECODE_DISTANCE_WIDTH)
1517  aSerial->print(F("Universal Pulse Distance Width, "));
1518 #endif
1519 #if defined(DECODE_HASH)
1520  aSerial->print(F("Hash "));
1521 #endif
1522 #if defined(NO_DECODER) // for sending raw only
1523  (void)aSerial; // to avoid compiler warnings
1524 #endif
1525 }
1526 
1541 bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
1542  // DEPRECATED
1543  (void) aPrintRepeatGap;
1544  return printIRResultShort(aSerial, aCheckForRecordGapsMicros);
1545 }
1546 bool IRrecv::printIRResultShort(Print *aSerial, bool aCheckForRecordGapsMicros) {
1547 
1548  uint8_t tFlags = decodedIRData.flags;
1549  if (tFlags & IRDATA_FLAGS_WAS_OVERFLOW) {
1550  aSerial->println(F("Overflow"));
1551  } else {
1552  aSerial->print(F("Protocol="));
1553  aSerial->print(getProtocolString());
1554  if (decodedIRData.protocol == UNKNOWN) {
1555 #if defined(DECODE_HASH)
1556  aSerial->print(F(" Hash=0x"));
1557 #if (__INT_WIDTH__ < 32)
1558  aSerial->print(decodedIRData.decodedRawData, HEX);
1559 #else
1560  PrintULL::print(aSerial,decodedIRData.decodedRawData, HEX);
1561 #endif
1562 
1563 #endif
1564 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1565  aSerial->print(' ');
1566  aSerial->print((decodedIRData.rawlen + 1) / 2);
1567  aSerial->println(F(" bits (incl. gap and start) received"));
1568 #endif
1569  } else {
1570 #if defined(DECODE_DISTANCE_WIDTH)
1572 #endif
1573  /*
1574  * New decoders have address and command
1575  */
1576  aSerial->print(F(" Address=0x"));
1577  aSerial->print(decodedIRData.address, HEX);
1578 
1579  aSerial->print(F(", Command=0x"));
1580  aSerial->print(decodedIRData.command, HEX);
1581 
1582  if (tFlags & IRDATA_FLAGS_EXTRA_INFO) {
1583  aSerial->print(F(", Extra=0x"));
1584  aSerial->print(decodedIRData.extra, HEX);
1585  }
1586 
1587  if (tFlags & IRDATA_FLAGS_PARITY_FAILED) {
1588  aSerial->print(F(", Parity fail"));
1589  }
1590 
1591  if (tFlags & IRDATA_FLAGS_TOGGLE_BIT) {
1592  aSerial->print(F(", Toggle=1"));
1593  }
1594 #if defined(DECODE_DISTANCE_WIDTH)
1595  }
1596 #endif
1597 
1598  /*
1599  * Print raw data, numberOfBits and MSB or LSB
1600  */
1601  if (!(tFlags & IRDATA_FLAGS_IS_REPEAT) || decodedIRData.decodedRawData != 0) {
1602  aSerial->print(F(", Raw-Data=0x"));
1603 #if (__INT_WIDTH__ < 32)
1604  aSerial->print(decodedIRData.decodedRawData, HEX);
1605 #else
1606  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1607 #endif
1608  aSerial->print(F(", "));
1609 
1610  /*
1611  * Print number of bits processed
1612  */
1613  aSerial->print(decodedIRData.numberOfBits);
1614  aSerial->print(F(" bits,"));
1615 
1616  if (tFlags & IRDATA_FLAGS_IS_MSB_FIRST) {
1617  aSerial->print(F(" MSB first"));
1618  } else {
1619  aSerial->print(F(" LSB first"));
1620  }
1621  }
1622 
1623  /*
1624  * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
1625  */
1627  aSerial->print(F(", "));
1628  if (tFlags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
1629  aSerial->print(F("Auto-"));
1630  }
1631  aSerial->print(F("Repeat"));
1632  }
1633 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1634  aSerial->print(F(", Gap="));
1635  aSerial->print((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK);
1636  aSerial->print(F("us"));
1637 
1638  /*
1639  * Print complete duration of IR frame
1640  */
1641  uint16_t tSumOfDurationTicks = 0;
1642  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
1643  tSumOfDurationTicks += irparams.rawbuf[i];
1644  }
1645  aSerial->print(F(", Duration="));
1646  aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
1647  aSerial->println(F("us"));
1648 #else
1649  aSerial->println();
1650 #endif
1651  }
1652  }
1653 
1654 // call no class function with same name
1655  if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) {
1656  return checkForRecordGapsMicros(aSerial);
1657  }
1658  return false;
1659 }
1660 
1661 /*
1662  * Only used in example ReceiveAndSend.cpp
1663  */
1664 void printIRDataShort(Print *aSerial, IRData *aIRDataPtr) {
1665 
1666  aSerial->print(F("Protocol="));
1667  aSerial->print(getProtocolString(aIRDataPtr->protocol));
1668 #if defined(DECODE_DISTANCE_WIDTH)
1669  if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
1670 #endif
1671  /*
1672  * New decoders have address and command
1673  */
1674  aSerial->print(F(" Address=0x"));
1675  aSerial->print(aIRDataPtr->address, HEX);
1676 
1677  aSerial->print(F(" Command=0x"));
1678  aSerial->print(aIRDataPtr->command, HEX);
1679 
1680 #if defined(DECODE_DISTANCE_WIDTH)
1681  }
1682 #endif
1683 
1684  /*
1685  * Print number of bits
1686  */
1687  aSerial->print(' ');
1688  aSerial->print(aIRDataPtr->numberOfBits, DEC);
1689  aSerial->print(F(" bits"));
1690 
1691  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
1692  aSerial->print(F(" MSB first"));
1693  } else {
1694  aSerial->print(F(" LSB first"));
1695  }
1696 
1697  /*
1698  * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
1699  */
1701  aSerial->print(' ');
1702  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
1703  aSerial->print(F("Auto-"));
1704  }
1705  aSerial->print(F("Repeat"));
1706  }
1707  aSerial->println();
1708 }
1709 
1719 void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap) {
1720  // DEPRECATED
1721 
1722  (void) aPrintRepeatGap;
1723  printIRDataShort(aSerial, aIRDataPtr);
1724 }
1725 void printIRResultShort(Print *aSerial, IRData *aIRDataPtr) {
1726  // DEPRECATED
1727 
1728  if (aIRDataPtr->flags & IRDATA_FLAGS_WAS_OVERFLOW) {
1729  aSerial->println(F("Overflow"));
1730  return;
1731  }
1732  aSerial->print(F("Protocol="));
1733  aSerial->print(getProtocolString(aIRDataPtr->protocol));
1734  if (aIRDataPtr->protocol == UNKNOWN) {
1735 #if defined(DECODE_HASH)
1736  aSerial->print(F(" Hash=0x"));
1737 #if (__INT_WIDTH__ < 32)
1738  aSerial->print(aIRDataPtr->decodedRawData, HEX);
1739 #else
1740  PrintULL::print(aSerial,aIRDataPtr->decodedRawData, HEX);
1741 #endif
1742 
1743 #endif
1744 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1745  aSerial->print(' ');
1746  aSerial->print((aIRDataPtr->rawlen + 1) / 2, DEC);
1747  aSerial->println(F(" bits (incl. gap and start) received"));
1748 #endif
1749  } else {
1750 #if defined(DECODE_DISTANCE_WIDTH)
1751  if (aIRDataPtr->protocol != PULSE_DISTANCE && aIRDataPtr->protocol != PULSE_WIDTH) {
1752 #endif
1753  /*
1754  * New decoders have address and command
1755  */
1756  aSerial->print(F(" Address=0x"));
1757  aSerial->print(aIRDataPtr->address, HEX);
1758 
1759  aSerial->print(F(" Command=0x"));
1760  aSerial->print(aIRDataPtr->command, HEX);
1761 
1762  if (aIRDataPtr->flags & IRDATA_FLAGS_EXTRA_INFO) {
1763  aSerial->print(F(" Extra=0x"));
1764  aSerial->print(aIRDataPtr->extra, HEX);
1765  }
1766 
1767  if (aIRDataPtr->flags & IRDATA_FLAGS_PARITY_FAILED) {
1768  aSerial->print(F(" Parity fail"));
1769  }
1770 
1771  if (aIRDataPtr->flags & IRDATA_FLAGS_TOGGLE_BIT) {
1772  aSerial->print(F(" Toggle=1"));
1773  }
1774 #if defined(DECODE_DISTANCE_WIDTH)
1775  }
1776 #endif
1777 
1778  /*
1779  * Print raw data
1780  */
1781  if (!(aIRDataPtr->flags & IRDATA_FLAGS_IS_REPEAT) || aIRDataPtr->decodedRawData != 0) {
1782  aSerial->print(F(" Raw-Data=0x"));
1783 #if (__INT_WIDTH__ < 32)
1784  aSerial->print(aIRDataPtr->decodedRawData, HEX);
1785 #else
1786  PrintULL::print(aSerial, aIRDataPtr->decodedRawData, HEX);
1787 #endif
1788  /*
1789  * Print number of bits processed
1790  */
1791  aSerial->print(' ');
1792  aSerial->print(aIRDataPtr->numberOfBits, DEC);
1793  aSerial->print(F(" bits"));
1794 
1795  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_MSB_FIRST) {
1796  aSerial->print(F(" MSB first"));
1797  } else {
1798  aSerial->print(F(" LSB first"));
1799  }
1800  }
1801 
1802  /*
1803  * Print gap and duration, in order to be able to compute the repeat period of the protocol by adding the next gap time
1804  */
1806  aSerial->print(' ');
1807  if (aIRDataPtr->flags & IRDATA_FLAGS_IS_AUTO_REPEAT) {
1808  aSerial->print(F("Auto-"));
1809  }
1810  aSerial->print(F("Repeat"));
1811  }
1812 #if !defined(DISABLE_CODE_FOR_RECEIVER)
1813  aSerial->print(F(" Gap="));
1814  aSerial->print((uint32_t) aIRDataPtr->initialGapTicks * MICROS_PER_TICK);
1815  aSerial->println(F("us"));
1816 #else
1817  aSerial->println();
1818 #endif
1819  }
1820 }
1821 
1822 void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo) {
1823  aSerial->print(aDistanceWidthTimingInfo->HeaderMarkMicros);
1824  aSerial->print(F(", "));
1825  aSerial->print(aDistanceWidthTimingInfo->HeaderSpaceMicros);
1826  aSerial->print(F(", "));
1827  aSerial->print(aDistanceWidthTimingInfo->OneMarkMicros);
1828  aSerial->print(F(", "));
1829  aSerial->print(aDistanceWidthTimingInfo->OneSpaceMicros);
1830  aSerial->print(F(", "));
1831  aSerial->print(aDistanceWidthTimingInfo->ZeroMarkMicros);
1832  aSerial->print(F(", "));
1833  aSerial->print(aDistanceWidthTimingInfo->ZeroSpaceMicros);
1834 }
1835 
1836 /*
1837  * Get maximum of mark ticks in rawDataPtr.
1838  * Skip leading start and trailing stop bit.
1839  */
1841  uint8_t tMaximumTick = 0;
1842  for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1843  auto tTick = irparams.rawbuf[i];
1844  if (tMaximumTick < tTick) {
1845  tMaximumTick = tTick;
1846  }
1847  }
1848  return tMaximumTick;
1849 }
1851  uint8_t tMaximumTick = 0;
1852  for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1853  auto tTick = irparams.rawbuf[i];
1854  if (tMaximumTick < tTick) {
1855  tMaximumTick = tTick;
1856  }
1857  }
1858  return tMaximumTick;
1859 }
1860 
1861 /*
1862  * The optimizing compiler internally generates this function, if getMaximumMarkTicksFromRawData() and getMaximumSpaceTicksFromRawData() is used.
1863  */
1864 uint8_t IRrecv::getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark) {
1865  uint8_t tMaximumTick = 0;
1866  IRRawlenType i;
1867  if (aSearchSpaceInsteadOfMark) {
1868  i = 4;
1869  } else {
1870  i = 3;
1871  }
1872  for (; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1873  auto tTick = irparams.rawbuf[i];
1874  if (tMaximumTick < tTick) {
1875  tMaximumTick = tTick;
1876  }
1877  }
1878  return tMaximumTick;
1879 }
1880 
1882  uint16_t tSumOfDurationTicks = 0;
1883 
1884  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
1885  tSumOfDurationTicks += irparams.rawbuf[i];
1886  }
1887  return (uint32_t) tSumOfDurationTicks * MICROS_PER_TICK;
1888 }
1889 
1890 // @formatter:off
1891 
1892 void printNumberOfRepeats(Print *aSerial) {
1893  aSerial->print(F(", <numberOfRepeats>"));
1894 }
1895 
1904 void IRrecv::printIRSendUsage(Print *aSerial) {
1907 
1908  /*
1909  * Generating the string:
1910  * Send on a 8 bit platform with:
1911  * uint32_t tRawData[]={0x87654321, 0xAFEDCBA9, 0x5A};
1912  * IrSender.send
1913  * or
1914  * Send on a 8 bit platform with: IrSender.send
1915  * or
1916  * Send with: IrSender.send
1917  */
1918 #if defined(DECODE_DISTANCE_WIDTH)
1919  uint_fast8_t tNumberOfArrayData = 0;
1921 # if __INT_WIDTH__ < 32
1922  aSerial->print(F("Send on a 8 bit platform with: "));
1923  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1;
1924  if(tNumberOfArrayData > 1) {
1925  aSerial->println();
1926  aSerial->print(F(" uint32_t tRawData[]={0x"));
1927  for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
1928  aSerial->print(decodedIRData.decodedRawDataArray[i], HEX);
1929 # else
1930  aSerial->print(F("Send on a 32 bit platform with: "));
1931  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1;
1932  if(tNumberOfArrayData > 1) {
1933  aSerial->println();
1934  aSerial->print(F(" uint64_t tRawData[]={0x"));
1935  for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
1936  PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX);
1937 # endif
1938  if (i != tNumberOfArrayData - 1) {
1939  aSerial->print(F(", 0x"));
1940  }
1941  }
1942  aSerial->println(F("};"));
1943  aSerial->print(F(" "));
1944  }
1945  } else { // if (decodedIRData.protocol == PULSE_DISTANCE || decodedIRData.protocol == PULSE_WIDTH)
1946  aSerial->print(F("Send with: "));
1947  }
1948  if (decodedIRData.protocol == UNKNOWN){
1949  aSerial->println();
1950  aSerial->print(F(" "));
1951  printIRResultAsCArray(&Serial);
1952  aSerial->print(F(" "));
1953  }
1954  aSerial->print(F("IrSender.send"));
1955 
1956 #else
1957  aSerial->print(F("Send with: IrSender.send"));
1958 #endif // #if defined(DECODE_DISTANCE_WIDTH)
1959 
1960  /*
1961  * Generating the string:
1962  * Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, <RepeatPeriodMillis>, <numberOfRepeats>
1963  * or
1964  * PulseDistanceWidth(38, 550, 1250, 500, 1250, 1300, 400, 0x3D9EAC, 23, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
1965  * or
1966  * PulseDistanceWidthFromArray(38, 8900, 4350, 600, 1650, 600, 550, &tRawData[0], 72, PROTOCOL_IS_LSB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>);
1967  * or
1968  * <Protocol_Name>(0x<Address>, 0x<Command>, <numberOfRepeats>);
1969  */
1970  if (decodedIRData.protocol == UNKNOWN){
1971  aSerial->print(F("Raw(rawIRTimings, sizeof(rawIRTimings) / sizeof(rawIRTimings[0]), 38, <RepeatPeriodMillis>"));
1972  printNumberOfRepeats(aSerial);
1973  }
1974 #if defined(DECODE_DISTANCE_WIDTH)
1976  /*
1977  * Pulse distance or pulse width here
1978  */
1979  aSerial->print(F("PulseDistanceWidth"));
1980  if(tNumberOfArrayData > 1) {
1981  aSerial->print(F("FromArray(38, "));
1982  } else {
1983  aSerial->print(F("(38, "));
1984  }
1985  printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo);
1986 
1987  if(tNumberOfArrayData > 1) {
1988  aSerial->print(F(", &tRawData[0], "));
1989  } else {
1990  aSerial->print(F(", 0x"));
1991 # if (__INT_WIDTH__ < 32)
1992  aSerial->print(decodedIRData.decodedRawData, HEX);
1993 # else
1994  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1995 # endif
1996  aSerial->print(F(", "));
1997  }
1998  aSerial->print(decodedIRData.numberOfBits); // aNumberOfBits
1999  aSerial->print(F(", PROTOCOL_IS_"));
2000 
2002  aSerial->print('M');
2003  } else {
2004  aSerial->print('L');
2005  }
2006  aSerial->print(F("SB_FIRST, <RepeatPeriodMillis>"));
2007  printNumberOfRepeats(aSerial);
2008 
2009  }
2010 #endif // defined(DECODE_DISTANCE_WIDTH)
2011  else {
2012  /*
2013  * Regular protocols here
2014  */
2015  aSerial->print(getProtocolString());
2016  aSerial->print(F("(0x"));
2017 #if defined(DECODE_MAGIQUEST)
2018  if (decodedIRData.protocol == MAGIQUEST) {
2019 # if (__INT_WIDTH__ < 32)
2020  aSerial->print(decodedIRData.decodedRawData, HEX);
2021 # else
2022  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
2023 # endif
2024  } else {
2025  aSerial->print(decodedIRData.address, HEX);
2026  }
2027 #else
2028  /*
2029  * New decoders have address and command
2030  */
2031  aSerial->print(decodedIRData.address, HEX);
2032 #endif
2033 
2034  aSerial->print(F(", 0x"));
2035  aSerial->print(decodedIRData.command, HEX);
2036  if (decodedIRData.protocol == SONY) {
2037  printNumberOfRepeats(aSerial);
2038  aSerial->print(F(", "));
2039  aSerial->print(decodedIRData.numberOfBits);
2040  } else {
2041  printNumberOfRepeats(aSerial);
2042 
2043  }
2044  }
2045 
2046 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO) || defined(DECODE_RC6) || defined(DECODE_MARANTZ)
2048  // Vendor code, Customer or MarantzExtension parameter, which is after numberOfRepeats parameter
2049  aSerial->print(F(", 0x"));
2050  aSerial->print(decodedIRData.extra, HEX);
2051  }
2052 #endif
2053  aSerial->print(F(");"));
2054  aSerial->println();
2055  }
2056 }
2057 
2058 // @formatter:on
2065 void IRrecv::printIRResultMinimal(Print *aSerial) {
2066  aSerial->print(F("P="));
2067  aSerial->print(decodedIRData.protocol);
2068  if (decodedIRData.protocol == UNKNOWN) {
2069 #if defined(DECODE_HASH)
2070  aSerial->print(F(" #=0x"));
2071 # if (__INT_WIDTH__ < 32)
2072  aSerial->print(decodedIRData.decodedRawData, HEX);
2073 # else
2074  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
2075 # endif
2076 #endif
2077  aSerial->print(' ');
2078  aSerial->print((decodedIRData.rawlen + 1) / 2);
2079  aSerial->println(F(" bits received"));
2080  } else {
2081  /*
2082  * New decoders have address and command
2083  */
2084  aSerial->print(F(" A=0x"));
2085  aSerial->print(decodedIRData.address, HEX);
2086 
2087  aSerial->print(F(" C=0x"));
2088  aSerial->print(decodedIRData.command, HEX);
2089 
2090  aSerial->print(F(" Raw=0x"));
2091 #if (__INT_WIDTH__ < 32)
2092  aSerial->print(decodedIRData.decodedRawData, HEX);
2093 #else
2094  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
2095 #endif
2096 
2098  aSerial->print(F(" R"));
2099  }
2100  }
2101 }
2102 
2103 /*
2104  * Not used yet
2105  */
2106 void IRrecv::printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
2107  uint16_t tSumOfDurationTicks = 0;
2108  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
2109  tSumOfDurationTicks += irparams.rawbuf[i];
2110  }
2111  aSerial->print(F("Duration="));
2112  if (aOutputMicrosecondsInsteadOfTicks) {
2113  aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
2114  aSerial->println(F("us"));
2115 
2116  } else {
2117  aSerial->print(tSumOfDurationTicks);
2118  aSerial->println(F(" ticks"));
2119  }
2120 }
2121 
2128 void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
2129 
2130 // Print Raw data
2131  aSerial->print(F("rawIRTimings["));
2132  aSerial->print(decodedIRData.rawlen);
2133  aSerial->println(F("]: "));
2134 
2135  /*
2136  * Print initial gap
2137  */
2138  aSerial->print(F(" -"));
2139  if (aOutputMicrosecondsInsteadOfTicks) {
2140  aSerial->println((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK);
2141  } else {
2142  aSerial->println(decodedIRData.initialGapTicks);
2143  }
2144 
2145 // Newline is printed every 8. value, if tCounterForNewline % 8 == 0
2146  uint_fast8_t tCounterForNewline = 6; // first newline is after the 2 values of the start bit
2147 
2148 // check if we have a protocol with no or 8 start bits
2149 #if defined(DECODE_DENON) || defined(DECODE_MAGIQUEST)
2150  if (
2151 # if defined(DECODE_DENON)
2153 # endif
2154 # if defined(DECODE_MAGIQUEST)
2156 # endif
2157  false) {
2158  tCounterForNewline = 0; // no or 8 start bits
2159  }
2160 #endif
2161 
2162  uint32_t tDuration;
2163  uint16_t tSumOfDurationTicks = 0;
2164  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
2165  auto tCurrentTicks = irparams.rawbuf[i];
2166  if (aOutputMicrosecondsInsteadOfTicks) {
2167  tDuration = tCurrentTicks * MICROS_PER_TICK;
2168  } else {
2169  tDuration = tCurrentTicks;
2170  }
2171  tSumOfDurationTicks += tCurrentTicks; // compute length of protocol frame
2172 
2173  if (!(i & 1)) { // even
2174  aSerial->print('-');
2175  } else { // odd
2176  aSerial->print(F(" +"));
2177  }
2178 
2179  // padding only for big values
2180  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 1000) {
2181  aSerial->print(' ');
2182  }
2183  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 100) {
2184  aSerial->print(' ');
2185  }
2186  if (tDuration < 10) {
2187  aSerial->print(' ');
2188  }
2189  aSerial->print(tDuration);
2190 
2191  if ((i & 1) && (i + 1) < decodedIRData.rawlen) {
2192  aSerial->print(','); //',' not required for last one
2193  }
2194 
2195  tCounterForNewline++;
2196  if ((tCounterForNewline % 8) == 0) {
2197  aSerial->println();
2198  }
2199  }
2200 
2201  aSerial->println();
2202  aSerial->print(F("Duration="));
2203  if (aOutputMicrosecondsInsteadOfTicks) {
2204  aSerial->print((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK);
2205  aSerial->println(F("us"));
2206 
2207  } else {
2208  aSerial->print(tSumOfDurationTicks);
2209  aSerial->println(F(" ticks"));
2210  }
2211  aSerial->println();
2212 
2213 }
2214 
2227 void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
2228  printIRResultAsCArray(aSerial, aOutputMicrosecondsInsteadOfTicks, true);
2229 }
2230 void IRrecv::printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks, bool aDoCompensate) {
2231 // Start declaration
2232  if (aOutputMicrosecondsInsteadOfTicks) {
2233  aSerial->print(F("uint16_t rawIRTimings[")); // variable type, array name
2234  } else {
2235  aSerial->print(F("uint8_t rawTicks[")); // variable type, array name
2236  }
2237 
2238  aSerial->print(decodedIRData.rawlen - 1); // array size
2239  aSerial->print(F("] = {")); // Start declaration
2240 
2241 // Dump data
2242  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
2243  uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; // no problem to use 50 instead of 50L here!
2244 
2245  if (aDoCompensate) {
2246  if (i & 1) {
2247  // Mark
2248  tDuration -= MARK_EXCESS_MICROS;
2249  } else {
2250  tDuration += MARK_EXCESS_MICROS;
2251  }
2252  }
2253 
2254  if (aOutputMicrosecondsInsteadOfTicks) {
2255  aSerial->print(tDuration);
2256  } else {
2257  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
2258  /*
2259  * Clip to 8 bit value
2260  */
2261  tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks;
2262  aSerial->print(tTicks);
2263  }
2264  if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one
2265  if (!(i & 1)) aSerial->print(' ');
2266  }
2267 
2268 // End declaration
2269  aSerial->print(F("};")); //
2270 
2271 // Comment
2272  aSerial->print(F(" // "));
2273  printIRResultShort(aSerial);
2274 }
2275 
2285 
2286 // Store data, skip leading space#
2287  IRRawlenType i;
2288  for (i = 1; i < decodedIRData.rawlen; i++) {
2289  uint32_t tDuration = irparams.rawbuf[i] * MICROS_PER_TICK; // no problem to use 50 instead of 50L here!
2290  if (i & 1) {
2291  // Mark
2292  tDuration -= MARK_EXCESS_MICROS;
2293  } else {
2294  tDuration += MARK_EXCESS_MICROS;
2295  }
2296 
2297  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
2298  *aArrayPtr = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; // we store it in an 8 bit array
2299  aArrayPtr++;
2300  }
2301 }
2302 
2311 // Now dump "known" codes
2312  if (decodedIRData.protocol != UNKNOWN) {
2313 
2314  /*
2315  * New decoders have address and command
2316  */
2317  aSerial->print(F("uint16_t"));
2318  aSerial->print(F(" address = 0x"));
2319  aSerial->print(decodedIRData.address, HEX);
2320  aSerial->println(';');
2321 
2322  aSerial->print(F("uint16_t"));
2323  aSerial->print(F(" command = 0x"));
2324  aSerial->print(decodedIRData.command, HEX);
2325  aSerial->println(';');
2326 
2327  // All protocols have raw data
2328 #if __INT_WIDTH__ < 32
2329  aSerial->print(F("uint32_t rawIRTimings = 0x"));
2330 #else
2331  aSerial->print(F("uint64_t rawIRTimings = 0x"));
2332 #endif
2333 #if (__INT_WIDTH__ < 32)
2334  aSerial->print(decodedIRData.decodedRawData, HEX);
2335 #else
2336  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
2337 #endif
2338  aSerial->println(';');
2339  }
2340 }
2341 
2342 #if defined(__AVR__)
2343 const __FlashStringHelper* IRrecv::getProtocolString() {
2344 // call no class function with same name
2346 }
2347 #else
2349  // call no class function with same name
2351 }
2352 #endif
2353 
2354 /**********************************************************************************************************************
2355  * The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials
2356  * This function calls the old MSB first decoders and fills only the 3 variables:
2357  * aResults->value
2358  * aResults->bits
2359  * aResults->decode_type
2360  **********************************************************************************************************************/
2362 
2364  return false;
2365  }
2366 
2367 // copy for usage by legacy programs
2368  aResults->rawbuf[0] = irparams.initialGapTicks;
2369  for (int i = 1; i < RAW_BUFFER_LENGTH; ++i) {
2370  aResults->rawbuf[i] = irparams.rawbuf[i]; // copy 8 bit array into a 16 bit array
2371  }
2372  aResults->rawlen = irparams.rawlen;
2373  if (irparams.OverflowFlag) {
2374  // Copy overflow flag to decodedIRData.flags
2375  irparams.OverflowFlag = false;
2376  irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call
2377  DEBUG_PRINTLN(F("Overflow happened"));
2378  }
2379  aResults->overflow = irparams.OverflowFlag;
2380  aResults->value = 0;
2381 
2383 
2384 #if defined(DECODE_NEC)
2385  DEBUG_PRINTLN(F("Attempting old NEC decode"));
2386  if (decodeNECMSB(aResults)) {
2387  return true;
2388  }
2389 #endif
2390 
2391 #if defined(DECODE_SONY)
2392  DEBUG_PRINTLN(F("Attempting old Sony decode"));
2393  if (decodeSonyMSB(aResults)) {
2394  return true;
2395  }
2396 #endif
2397 
2398 #if defined(DECODE_RC5)
2399  DEBUG_PRINTLN(F("Attempting RC5 decode"));
2400  if (decodeRC5()) {
2401  aResults->bits = decodedIRData.numberOfBits;
2402  aResults->value = decodedIRData.decodedRawData;
2403  aResults->decode_type = RC5;
2404 
2405  return true;
2406  }
2407 #endif
2408 
2409 #if defined(DECODE_RC6)
2410  DEBUG_PRINTLN(F("Attempting RC6 decode"));
2411  if (decodeRC6()) {
2412  aResults->bits = decodedIRData.numberOfBits;
2413  aResults->value = decodedIRData.decodedRawData;
2414  aResults->decode_type = RC6;
2415  return true;
2416  }
2417 #endif
2418 
2419 // Removed bool IRrecv::decodePanasonicMSB(decode_results *aResults) since implementations was wrong (wrong length), and nobody recognized it
2420 
2421 #if defined(DECODE_LG)
2422  DEBUG_PRINTLN(F("Attempting old LG decode"));
2423  if (decodeLGMSB(aResults)) {return true;}
2424 #endif
2425 
2426 #if defined(DECODE_JVC)
2427  DEBUG_PRINTLN(F("Attempting old JVC decode"));
2428  if (decodeJVCMSB(aResults)) {
2429  return true;
2430  }
2431 #endif
2432 
2433 #if defined(DECODE_SAMSUNG)
2434  DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
2435  if (decodeSAMSUNG(aResults)) {
2436  return true;
2437  }
2438 #endif
2439 
2440 #if defined(DECODE_DENON)
2441  DEBUG_PRINTLN(F("Attempting old Denon decode"));
2442  if (decodeDenonOld(aResults)) {
2443  return true;
2444  }
2445 #endif
2446 
2447 // decodeHash returns a hash on any input.
2448 // Thus, it needs to be last in the list.
2449 // If you add any decodes, add them before this.
2450  if (decodeHashOld(aResults)) {
2451  return true;
2452  }
2453 // Throw away and start over
2454  resume();
2455  return false;
2456 }
2457 
2459 #if defined(_IR_MEASURE_TIMING)
2460 #undef _IR_MEASURE_TIMING
2461 #endif
2462 #include "LocalDebugLevelEnd.h"
2463 
2464 #endif // _IR_RECEIVE_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRremoteInt.h:164
timerConfigForReceive
void timerConfigForReceive()
Configures the timer to be able to generate the receive sample interrupt, which consumes a small amou...
Definition: IRTimer.hpp:112
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:133
IRrecv::decodeHash
bool decodeHash()
Decodes an arbitrary IR code to a 32-bit value.
Definition: IRReceive.hpp:1160
decode_results
Results returned from old decoders !!!deprecated!!!
Definition: IRremoteInt.h:193
digitalReadFast
#define digitalReadFast
Definition: digitalWriteFast.h:399
DistanceWidthTimingInfoStruct::HeaderMarkMicros
uint16_t HeaderMarkMicros
Definition: IRProtocol.h:113
decode_results::rawbuf
uint16_t * rawbuf
Definition: IRremoteInt.h:204
IRrecv::decodePulseDistanceWidthData
void decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset=3)
Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
Definition: IRReceive.hpp:1076
setLEDFeedbackPin
void setLEDFeedbackPin(uint8_t aFeedbackLEDPin)
Definition: IRFeedbackLED.hpp:54
setFeedbackLED
void setFeedbackLED(bool aSwitchLedOn)
Flash LED while receiving or sending IR data.
Definition: IRFeedbackLED.hpp:96
IRrecv::stop
void stop()
Disables the timer for IR reception.
Definition: IRReceive.hpp:463
IRrecv::lastDecodedProtocol
decode_type_t lastDecodedProtocol
Definition: IRremoteInt.h:404
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRremoteInt.h:173
DEBUG_PRINT
#define DEBUG_PRINT(...)
Definition: LocalDebugLevelStart.h:79
IRrecv::printDistanceWidthTimingInfo
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo)
Definition: IRReceive.hpp:1822
RECORD_GAP_TICKS
#define RECORD_GAP_TICKS
Definition: IRremote.hpp:127
IRrecv::disableIRIn
void disableIRIn()
Alias for stop().
Definition: IRReceive.hpp:477
IRrecv::decodePulseDistanceWidthData_P
void decodePulseDistanceWidthData_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset=3)
Definition: IRReceive.hpp:1112
IRRawlenType
unsigned int IRRawlenType
Definition: IRremoteInt.h:88
IRrecv::checkHeader_P
bool checkHeader_P(PulseDistanceWidthProtocolConstants const *aProtocolConstantsPGM)
Definition: IRReceive.hpp:1228
IRrecv::enableIRIn
void enableIRIn()
Alias for start().
Definition: IRReceive.hpp:413
MARK_EXCESS_MICROS
#define MARK_EXCESS_MICROS
MARK_EXCESS_MICROS is subtracted from all marks and added to all spaces before decoding,...
Definition: IRremote.hpp:111
pinModeFast
#define pinModeFast
Definition: digitalWriteFast.h:383
IRrecv::checkForRecordGapsMicros
bool checkForRecordGapsMicros(Print *aSerial)
Checks if protocol is not detected and detected space between two transmissions is smaller than known...
Definition: IRReceive.hpp:1429
TRACE_PRINTLN
#define TRACE_PRINTLN(...)
Definition: LocalDebugLevelStart.h:70
digitalWriteFast
#define digitalWriteFast
Definition: digitalWriteFast.h:347
TRACE_PRINT
#define TRACE_PRINT(...)
Definition: LocalDebugLevelStart.h:69
IRrecv::registerReceiveCompleteCallback
void registerReceiveCompleteCallback(void(*aReceiveCompleteCallbackFunction)(void))
Sets the function to call if a complete protocol frame has arrived.
Definition: IRReceive.hpp:369
IRrecv
Definition: IRremoteInt.h:213
DECODE_MAGIQUEST
#define DECODE_MAGIQUEST
Definition: IRProtocol.h:72
printNumberOfRepeats
void printNumberOfRepeats(Print *aSerial)
Definition: IRReceive.hpp:1892
IRrecv::decodeDistanceWidth
bool decodeDistanceWidth()
Definition: ir_DistanceWidthProtocol.hpp:206
SONY
@ SONY
Definition: IRProtocol.h:101
PULSE_WIDTH
@ PULSE_WIDTH
Definition: IRProtocol.h:98
decode_results::overflow
bool overflow
Definition: IRremoteInt.h:206
IRDATA_FLAGS_IS_REPEAT
#define IRDATA_FLAGS_IS_REPEAT
The gap between the preceding frame is as smaller than the maximum gap expected for a repeat....
Definition: IRProtocol.h:125
decode_type_t
decode_type_t
An enum consisting of all supported formats.
Definition: IRProtocol.h:97
IRrecv::printIRResultRawFormatted
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks=true)
Dump out the timings in IrReceiver.irparams.rawbuf[] array 8 values per line.
Definition: IRReceive.hpp:2128
PulseDistanceWidthProtocolConstants::ProtocolIndex
decode_type_t ProtocolIndex
Definition: IRProtocol.h:140
IRrecv::restartAfterSend
void restartAfterSend()
Restarts receiver after send.
Definition: IRReceive.hpp:454
IRrecv::decodeBangOlufsen
bool decodeBangOlufsen()
Definition: ir_BangOlufsen.hpp:284
IRrecv::IRrecv
IRrecv()
Instantiate the IRrecv class.
Definition: IRReceive.hpp:63
TICKS_LOW
#define TICKS_LOW(us)
Definition: IRremoteInt.h:479
DistanceWidthTimingInfoStruct::OneSpaceMicros
uint16_t OneSpaceMicros
Definition: IRProtocol.h:116
IRrecv::printIRResultShort
bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) __attribute__((deprecated("Remove second parameter
Function to print values and flags of IrReceiver.decodedIRData in one line.
Definition: IRReceive.hpp:1541
IRDATA_FLAGS_IS_AUTO_REPEAT
#define IRDATA_FLAGS_IS_AUTO_REPEAT
The current repeat frame is a repeat, that is always sent after a regular frame and cannot be avoided...
Definition: IRProtocol.h:126
decode_results::bits
uint8_t bits
Definition: IRremoteInt.h:199
decode_results::decode_type
decode_type_t decode_type
Definition: IRremoteInt.h:196
matchTicks
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Match function WITHOUT compensating for marks exceeded or spaces shortened by demodulator hardware Ma...
Definition: IRReceive.hpp:1264
irparams_struct::ReceiveCompleteCallbackFunction
void(* ReceiveCompleteCallbackFunction)(void)
The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP...
Definition: IRremoteInt.h:135
PULSE_DISTANCE
@ PULSE_DISTANCE
Definition: IRProtocol.h:98
IRrecv::begin
void begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback=false, uint_fast8_t aFeedbackLEDPin=USE_DEFAULT_FEEDBACK_LED_PIN)
Initializes the receive and feedback pin.
Definition: IRReceive.hpp:311
IRrecv::checkForRepeatSpaceTicksAndSetFlag
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks)
Definition: IRReceive.hpp:1248
RECORD_GAP_MICROS_WARNING_THRESHOLD
#define RECORD_GAP_MICROS_WARNING_THRESHOLD
Threshold for warnings at printIRResult*() to report about changing the RECORD_GAP_MICROS value to a ...
Definition: IRremote.hpp:141
IRrecv::decodeSonyMSB
bool decodeSonyMSB(decode_results *aResults)
Definition: ir_Sony.hpp:145
IRrecv::decodeSony
bool decodeSony()
Definition: ir_Sony.hpp:107
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1375
DistanceWidthTimingInfoStruct::ZeroMarkMicros
uint16_t ZeroMarkMicros
Definition: IRProtocol.h:117
IRrecv::read
IRData * read()
Returns pointer to IrReceiver.decodedIRData if IR receiver data is available, else nullptr.
Definition: IRReceive.hpp:543
MAGIQUEST
@ MAGIQUEST
Definition: IRProtocol.h:103
timerDisableReceiveInterrupt
void timerDisableReceiveInterrupt()
Disables the receive sample timer interrupt.
Definition: IRTimer.hpp:124
IRrecv::decodeLGMSB
bool decodeLGMSB(decode_results *aResults)
Definition: ir_LG.hpp:269
PulseDistanceWidthProtocolConstants::Flags
uint8_t Flags
Definition: IRProtocol.h:143
LocalDebugLevelStart.h
PROTOCOL_IS_PULSE_WIDTH_MASK
#define PROTOCOL_IS_PULSE_WIDTH_MASK
Definition: IRProtocol.h:154
DECODE_DENON
#define DECODE_DENON
Definition: IRProtocol.h:58
IRDATA_FLAGS_PARITY_FAILED
#define IRDATA_FLAGS_PARITY_FAILED
The current (autorepeat) frame violated parity check.
Definition: IRProtocol.h:127
decode_results::value
uint32_t value
Definition: IRremoteInt.h:198
DistanceWidthTimingInfoStruct
Definition: IRProtocol.h:112
MATCH_SPACE
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1413
IRrecv::decodeSAMSUNG
bool decodeSAMSUNG(decode_results *aResults)
Definition: ir_Samsung.hpp:361
IRDecodedRawDataType
uint32_t IRDecodedRawDataType
Definition: IRremoteInt.h:151
IRrecv::decodeLegoPowerFunctions
bool decodeLegoPowerFunctions()
Definition: ir_Lego.hpp:144
irparams_struct::OverflowFlag
bool OverflowFlag
Raw buffer OverflowFlag occurred.
Definition: IRremoteInt.h:144
IRrecv::decodeFAST
bool decodeFAST()
Definition: ir_FAST.hpp:96
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:139
printIRResultShort
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, bool aPrintRepeatGap)
Deprecated static function to be able to print data to send or copied received data.
Definition: IRReceive.hpp:1719
FeedbackLEDControlStruct::LedFeedbackEnabled
bool LedFeedbackEnabled
Disabled for receive at default. Feedback for send is always enabled and can be disabled by NO_LED_SE...
Definition: IRFeedbackLED.hpp:44
IRrecv::getProtocolString
const char * getProtocolString()
Definition: IRReceive.hpp:2348
irparams_struct::rawlen
IRRawlenType rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:145
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:401
IRData
Data structure for the user application, available as decodedIRData.
Definition: IRremoteInt.h:162
IRDATA_FLAGS_EXTRA_INFO
#define IRDATA_FLAGS_EXTRA_INFO
There is extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID,...
Definition: IRProtocol.h:130
FNV_PRIME_32
#define FNV_PRIME_32
used for decodeHash()
Definition: IRReceive.hpp:1125
STR
#define STR(x)
Definition: IRremote.hpp:85
IRrecv::compensateAndPrintIRResultAsCArray
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks=true)
Dump out the IrReceiver.irparams.rawbuf[] to be used as C definition for sendRaw().
Definition: IRReceive.hpp:2227
IRrecv::decodeSamsung
bool decodeSamsung()
Definition: ir_Samsung.hpp:270
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRremoteInt.h:174
IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT
#define IRDATA_FLAGS_IS_PROTOCOL_WITH_DIFFERENT_REPEAT
Here we have a repeat of type NEC2 or SamsungLG.
Definition: IRProtocol.h:131
sMicrosAtLastStopTimer
unsigned long sMicrosAtLastStopTimer
Definition: IRReceive.hpp:49
IRrecv::printIRResultMinimal
void printIRResultMinimal(Print *aSerial)
Function to print protocol number, address, command, raw data and repeat flag of IrReceiver....
Definition: IRReceive.hpp:2065
DistanceWidthTimingInfoStruct::OneMarkMicros
uint16_t OneMarkMicros
Definition: IRProtocol.h:115
IRDATA_FLAGS_WAS_OVERFLOW
#define IRDATA_FLAGS_WAS_OVERFLOW
irparams.rawlen is set to 0 in this case to avoid endless OverflowFlag.
Definition: IRProtocol.h:132
MATCH
bool MATCH(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1319
IRrecv::checkHeader
bool checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants)
Definition: IRReceive.hpp:1213
IRrecv::compare
uint_fast8_t compare(uint16_t oldval, uint16_t newval)
Compare two (tick) values for Hash decoder Use a tolerance of 20% to enable e.g.
Definition: IRReceive.hpp:1133
IRrecv::printActiveIRProtocols
static void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1454
printActiveIRProtocols
void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1462
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRremoteInt.h:165
IR_REC_STATE_STOP
#define IR_REC_STATE_STOP
Definition: IRremoteInt.h:119
IR_REC_STATE_MARK
#define IR_REC_STATE_MARK
Definition: IRremoteInt.h:117
IRData::decodedRawData
IRDecodedRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send<protocol>Raw functions.
Definition: IRremoteInt.h:167
IRrecv::printIRDuration
void printIRDuration(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks)
Definition: IRReceive.hpp:2106
IRReceiveTimerInterruptHandler
void IRReceiveTimerInterruptHandler()
Definition: IRReceive.hpp:277
IRrecv::getMaximumTicksFromRawData
uint8_t getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark)
Definition: IRReceive.hpp:1864
IRrecv::restartTimer
void restartTimer()
Definition: IRReceive.hpp:397
IRrecv::restartTimerWithTicksToAdd
void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter)
Configures the timer and the state machine for IR reception.
Definition: IRReceive.hpp:439
FNV_BASIS_32
#define FNV_BASIS_32
used for decodeHash()
Definition: IRReceive.hpp:1126
IRrecv::isIdle
bool isIdle()
Definition: IRReceive.hpp:529
MARANTZ
@ MARANTZ
Definition: IRProtocol.h:103
timerResetInterruptPending
void timerResetInterruptPending()
timerEnableReceiveInterrupt
void timerEnableReceiveInterrupt()
Enables the receive sample timer interrupt, which consumes a small amount of CPU every 50 us.
Definition: IRTimer.hpp:117
getMarkExcessMicros
int getMarkExcessMicros()
Getter function for MARK_EXCESS_MICROS.
Definition: IRReceive.hpp:1420
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1327
MATCH_MARK
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1367
irparams_struct::TickCounterForISR
volatile uint_fast16_t TickCounterForISR
Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is indepen...
Definition: IRremoteInt.h:133
irparams_struct::StateForISR
volatile uint8_t StateForISR
State Machine state.
Definition: IRremoteInt.h:127
IRrecv::setReceivePin
void setReceivePin(uint_fast8_t aReceivePinNumber)
Sets / changes the receiver pin number.
Definition: IRReceive.hpp:331
irparams_struct::rawbuf
IRRawbufType rawbuf[RAW_BUFFER_LENGTH]
raw data / tick counts per mark/space. With 8 bit we can only store up to 12.7 ms....
Definition: IRremoteInt.h:147
DistanceWidthTimingInfoStruct::ZeroSpaceMicros
uint16_t ZeroSpaceMicros
Definition: IRProtocol.h:118
IRrecv::decodeDenonOld
bool decodeDenonOld(decode_results *aResults)
Definition: ir_Denon.hpp:285
IRrecv::start
void start()
Start the receiving process.
Definition: IRReceive.hpp:379
IRrecv::initDecodedIRData
void initDecodedIRData()
Is internally called by decode before calling decoders.
Definition: IRReceive.hpp:502
IRrecv::irparams
irparams_struct irparams
Definition: IRremoteInt.h:400
KASEIKYO
@ KASEIKYO
Definition: IRProtocol.h:99
IRrecv::lastDecodedCommand
uint16_t lastDecodedCommand
Definition: IRremoteInt.h:406
DENON
@ DENON
Definition: IRProtocol.h:98
DEBUG_PRINTLN
#define DEBUG_PRINTLN(...)
Definition: LocalDebugLevelStart.h:80
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:133
TICKS_HIGH
#define TICKS_HIGH(us)
Definition: IRremoteInt.h:480
IRrecv::getMaximumMarkTicksFromRawData
uint8_t getMaximumMarkTicksFromRawData()
Definition: IRReceive.hpp:1840
RC6A
@ RC6A
Definition: IRProtocol.h:99
IRrecv::decodeBoseWave
bool decodeBoseWave()
Definition: ir_BoseWave.hpp:62
setLEDFeedback
void setLEDFeedback(bool aEnableLEDFeedback)
Definition: IRFeedbackLED.hpp:74
IRDATA_FLAGS_TOGGLE_BIT
#define IRDATA_FLAGS_TOGGLE_BIT
Is set if RC5 or RC6 toggle bit is set.
Definition: IRProtocol.h:128
IRDATA_FLAGS_EMPTY
#define IRDATA_FLAGS_EMPTY
Definition: IRProtocol.h:124
RC5
@ RC5
Definition: IRProtocol.h:99
IRrecv::available
bool available()
Returns true if IR receiver has received a complete IR frame (detected by timeout after last mark).
Definition: IRReceive.hpp:536
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRremoteInt.h:166
IRrecv::printIRResultAsCVariables
void printIRResultAsCVariables(Print *aSerial)
Print results as C variables to be used for sendXXX() uint16_t address = 0x44; uint16_t command = 0x1...
Definition: IRReceive.hpp:2310
PulseDistanceWidthProtocolConstants::DistanceWidthTimingInfo
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo
Definition: IRProtocol.h:142
IRrecv::getMaximumSpaceTicksFromRawData
uint8_t getMaximumSpaceTicksFromRawData()
Definition: IRReceive.hpp:1850
INPUT_MARK
#define INPUT_MARK
Sensor output for a mark ("flash")
Definition: IRremote.hpp:153
IRrecv::decode_old
bool decode_old(decode_results *aResults)
Definition: IRReceive.hpp:2361
FeedbackLEDControl
struct FeedbackLEDControlStruct FeedbackLEDControl
The feedback LED control instance.
Definition: IRFeedbackLED.hpp:47
IRrecv::decodeStrictPulseDistanceWidthData
bool decodeStrictPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst)
Definition: IRReceive.hpp:961
IRrecv::end
void end()
Alias for stop().
Definition: IRReceive.hpp:483
IRData::rawlen
IRRawlenType rawlen
Counter of entries in rawbuf of last received frame.
Definition: IRremoteInt.h:182
IRrecv::decodeNECMSB
bool decodeNECMSB(decode_results *aResults)
Definition: ir_NEC.hpp:332
IRrecv::decodeNEC
bool decodeNEC()
Decodes also Onkyo and Apple.
Definition: ir_NEC.hpp:235
PROTOCOL_IS_MSB_MASK
#define PROTOCOL_IS_MSB_MASK
Definition: IRProtocol.h:158
RC6
@ RC6
Definition: IRProtocol.h:99
IRrecv::decodeHashOld
bool decodeHashOld(decode_results *aResults)
Definition: IRReceive.hpp:1184
IRrecv::printIRSendUsage
void printIRSendUsage(Print *aSerial)
Function to print values and flags of IrReceiver.decodedIRData in one line.
Definition: IRReceive.hpp:1904
IRrecv::decodeOpenLASIR
bool decodeOpenLASIR()
Decode an OpenLASIR frame.
Definition: ir_OpenLASIR.hpp:229
IRrecv::decodeMagiQuest
bool decodeMagiQuest()
Definition: ir_MagiQuest.hpp:156
IRrecv::getTotalDurationOfRawData
uint32_t getTotalDurationOfRawData()
Definition: IRReceive.hpp:1881
IRrecv::decodeDenon
bool decodeDenon()
Definition: ir_Denon.hpp:167
IRrecv::decodeLG
bool decodeLG()
Definition: ir_LG.hpp:172
IRrecv::stopTimer
void stopTimer()
Definition: IRReceive.hpp:470
IRrecv::decode
bool decode()
The main decode function, attempts to decode the recently receive IR signal.
Definition: IRReceive.hpp:560
IRrecv::decodeJVC
bool decodeJVC()
Definition: ir_JVC.hpp:116
UNKNOWN
@ UNKNOWN
Definition: IRProtocol.h:98
RAW_BUFFER_LENGTH
#define RAW_BUFFER_LENGTH
The RAW_BUFFER_LENGTH determines the length of the byte buffer where the received IR timing data is s...
Definition: IRremoteInt.h:78
IRrecv::decodeKaseikyo
bool decodeKaseikyo()
Definition: ir_Kaseikyo.hpp:197
IRrecv::ReceiveInterruptHandler
void ReceiveInterruptHandler()
Definition: IRReceive.hpp:109
decode_results::rawlen
uint_fast8_t rawlen
Definition: IRremoteInt.h:205
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRremoteInt.h:163
IR_REC_STATE_SPACE
#define IR_REC_STATE_SPACE
Definition: IRremoteInt.h:118
printIRDataShort
void printIRDataShort(Print *aSerial, IRData *aIRDataPtr)
Definition: IRReceive.hpp:1664
IRrecv::resume
void resume()
Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame.
Definition: IRReceive.hpp:491
DistanceWidthTimingInfoStruct::HeaderSpaceMicros
uint16_t HeaderSpaceMicros
Definition: IRProtocol.h:114
IRrecv::lastDecodedAddress
uint16_t lastDecodedAddress
Definition: IRremoteInt.h:405
IRrecv::compensateAndStoreIRResultInArray
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr)
Store the decodedIRData to be used for sendRaw().
Definition: IRReceive.hpp:2284
IrReceiver
IRrecv IrReceiver
The receiver instance.
Definition: IRReceive.hpp:57
IRData::initialGapTicks
uint16_t initialGapTicks
Contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
Definition: IRremoteInt.h:183
LocalDebugLevelEnd.h
IRrecv::decodeWithThresholdPulseDistanceWidthData
void decodeWithThresholdPulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneThresholdMicros, bool aIsPulseWidthProtocol, bool aMSBfirst)
New threshold decoder to be activated by USE_THRESHOLD_DECODER Assumes a 0 for shorter and a 1 for lo...
Definition: IRReceive.hpp:833
IR_REC_STATE_IDLE
#define IR_REC_STATE_IDLE
Definition: IRremoteInt.h:116
getProtocolString
const char * getProtocolString(decode_type_t aProtocol)
Definition: IRProtocol.hpp:95
IRrecv::printIRResultAsCArray
void printIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks=true, bool aDoCompensate=true)
Definition: IRReceive.hpp:2230
IRrecv::decodeJVCMSB
bool decodeJVCMSB(decode_results *aResults)
Definition: ir_JVC.hpp:166
SHARP
@ SHARP
Definition: IRProtocol.h:101
IRrecv::decodeWhynter
bool decodeWhynter()
Definition: ir_Others.hpp:94
irparams_struct::IRReceivePin
uint_fast8_t IRReceivePin
Pin connected to IR data from detector.
Definition: IRremoteInt.h:128
irparams_struct::initialGapTicks
uint16_t initialGapTicks
Tick counts of the length of the gap between previous and current IR frame. Pre 4....
Definition: IRremoteInt.h:146