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-2023 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 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
37 //#define LOCAL_DEBUG //
38 #else
39 //#define LOCAL_DEBUG // This enables debug output only for this file
40 #endif
41 
42 #if defined(TRACE) && !defined(LOCAL_TRACE)
43 #define LOCAL_TRACE
44 #else
45 //#define LOCAL_TRACE // This enables debug output only for this file
46 #endif
47 /*
48  * Low level hardware timing measurement
49  */
50 //#define _IR_MEASURE_TIMING // for ISR
51 //#define _IR_TIMING_TEST_PIN 7 // "pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);" is executed at start()
52 //
53 /*
54  * Check for additional required characteristics of timing like length of mark for a constant mark protocol,
55  * where space length determines the bit value. Requires up to 194 additional bytes of program memory.
56  */
57 //#define DECODE_STRICT_CHECKS
65 
66 /*
67  * The control structure instance
68  */
69 struct irparams_struct irparams; // the irparams instance
70 
76  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
77  setReceivePin(0);
78 #if !defined(NO_LED_FEEDBACK_CODE)
80 #endif
81 }
82 
83 IRrecv::IRrecv(uint_fast8_t aReceivePin) {
84  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
85  setReceivePin(aReceivePin);
86 #if !defined(NO_LED_FEEDBACK_CODE)
88 #endif
89 }
90 
96 IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
97  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
98  setReceivePin(aReceivePin);
99 #if !defined(NO_LED_FEEDBACK_CODE)
100  setLEDFeedback(aFeedbackLEDPin, DO_NOT_ENABLE_LED_FEEDBACK);
101 #else
102  (void) aFeedbackLEDPin;
103 #endif
104 }
105 
106 /**********************************************************************************************************************
107  * Interrupt Service Routine - Called every 50 us
108  *
109  * Duration in ticks of 50 us of alternating SPACE, MARK are recorded in irparams.rawbuf array.
110  * 'rawlen' counts the number of entries recorded so far.
111  * First entry is the SPACE between transmissions.
112  *
113  * As soon as one SPACE entry gets longer than RECORD_GAP_TICKS, state switches to STOP (frame received). Timing of SPACE continues.
114  * A call of resume() switches from STOP to IDLE.
115  * As soon as first MARK arrives in IDLE, gap width is recorded and new logging starts.
116  *
117  * With digitalRead and Feedback LED
118  * 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
119  * With portInputRegister and mask and Feedback LED code commented
120  * 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
121  * => Minimal CPU frequency is 4 MHz
122  *
123  **********************************************************************************************************************/
124 #if defined(ESP8266) || defined(ESP32)
125 IRAM_ATTR
126 #endif
128 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
129  digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
130 #endif
131 // 7 - 8.5 us for ISR body (without pushes and pops) for ATmega328 @16MHz
132 
133 #if defined(TIMER_REQUIRES_RESET_INTR_PENDING)
134  timerResetInterruptPending(); // reset TickCounterForISR interrupt flag if required (currently only for Teensy and ATmega4809)
135 #endif
136 
137 // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
138 #if defined(__AVR__)
139  uint8_t tIRInputLevel = *irparams.IRReceivePinPortInputRegister & irparams.IRReceivePinMask;
140 #else
141  uint_fast8_t tIRInputLevel = (uint_fast8_t) digitalReadFast(irparams.IRReceivePin);
142 #endif
143 
144  /*
145  * Increase TickCounter and clip it at maximum 0xFFFF / 3.2 seconds at 50 us ticks
146  */
147  if (irparams.TickCounterForISR < UINT16_MAX) {
148  irparams.TickCounterForISR++; // One more 50uS tick
149  }
150 
151  /*
152  * Due to a ESP32 compiler bug https://github.com/espressif/esp-idf/issues/1552 no switch statements are possible for ESP32
153  * So we change the code to if / else if
154  */
155 // switch (irparams.StateForISR) {
156 //
158  /*
159  * Here we are just resumed and maybe in the middle of a transmission
160  */
161  if (tIRInputLevel == INPUT_MARK) {
162  // check if we did not start in the middle of a transmission by checking the minimum length of leading space
164 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
165 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
166 #endif
167  /*
168  * Gap between two transmissions just ended; Record gap duration + start recording transmission
169  * Initialize all state machine variables
170  */
171  irparams.OverflowFlag = false;
173  irparams.rawlen = 1;
175  } // otherwise stay in idle state
176  irparams.TickCounterForISR = 0; // reset counter in both cases
177  }
178 
179  } else if (irparams.StateForISR == IR_REC_STATE_MARK) { // Timing mark
180  if (tIRInputLevel != INPUT_MARK) {
181  /*
182  * Mark ended here. Record mark time in rawbuf array
183  */
184 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
185 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
186 #endif
189  irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-)
190  }
191 
192  } else if (irparams.StateForISR == IR_REC_STATE_SPACE) { // Timing space
193  if (tIRInputLevel == INPUT_MARK) {
194  /*
195  * Space ended here. Check for overflow and record space time in rawbuf array
196  */
198  // Flag up a read OverflowFlag; Stop the state machine
199  irparams.OverflowFlag = true;
201 #if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
202  /*
203  * Call callback if registered (not NULL)
204  */
207  }
208 #endif
209  } else {
210 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
211 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
212 #endif
215  }
217 
219  /*
220  * Maximum space duration reached here.
221  * Current code is ready for processing!
222  * We received a long space, which indicates gap between codes.
223  * Switch to IR_REC_STATE_STOP
224  * Don't reset TickCounterForISR; keep counting width of next leading space
225  */
227 #if !IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK
228  /*
229  * Call callback if registered (not NULL)
230  */
233  }
234 #endif
235  }
236  } else if (irparams.StateForISR == IR_REC_STATE_STOP) {
237  /*
238  * Complete command received
239  * stay here until resume() is called, which switches state to IR_REC_STATE_IDLE
240  */
241 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
242 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
243 #endif
244  if (tIRInputLevel == INPUT_MARK) {
245  // Reset gap TickCounterForISR, to prepare for detection if we are in the middle of a transmission after call of resume()
247  }
248  }
249 
250 #if !defined(NO_LED_FEEDBACK_CODE)
252  setFeedbackLED(tIRInputLevel == INPUT_MARK);
253  }
254 #endif
255 
256 #ifdef _IR_MEASURE_TIMING
257  digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
258 #endif
259 
260 }
261 
262 /*
263  * The ISR, which calls the interrupt handler
264  */
265 #if defined(TIMER_INTR_NAME) || defined(ISR)
266 # if defined(TIMER_INTR_NAME)
267 ISR (TIMER_INTR_NAME) // for ISR definitions
268 # elif defined(ISR)
269 ISR()
270 // for functions definitions which are called by separate (board specific) ISR
271 # endif
272 {
274 }
275 #endif
276 
277 /**********************************************************************************************************************
278  * Stream like API
279  **********************************************************************************************************************/
286 void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
287 
288  setReceivePin(aReceivePin);
289 #if !defined(NO_LED_FEEDBACK_CODE)
290  uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
291  if (aEnableLEDFeedback) {
292  tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE;
293  }
294  setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
295 #else
296  (void) aEnableLEDFeedback;
297  (void) aFeedbackLEDPin;
298 #endif
299 
300 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
301  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
302 #endif
303  start();
304 }
305 
309 void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) {
310  irparams.IRReceivePin = aReceivePinNumber;
311 #if defined(__AVR__)
312 # if defined(__digitalPinToBit)
313  if (__builtin_constant_p(aReceivePinNumber)) {
314  irparams.IRReceivePinMask = 1UL << (__digitalPinToBit(aReceivePinNumber));
315  } else {
316  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
317  }
318 # else
319  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
320 # endif
321 # if defined(__digitalPinToPINReg)
322  /*
323  * This code is 54 bytes smaller, if aReceivePinNumber is a constant :-), but 38 byte longer if it is not constant (,which is not likely).
324  */
325  if (__builtin_constant_p(aReceivePinNumber)) {
326  irparams.IRReceivePinPortInputRegister = __digitalPinToPINReg(aReceivePinNumber);
327  } else {
328  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
329  }
330 # else
331  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
332 # endif
333 #endif
334  // Set pin mode once. pinModeFast makes no difference if used, but saves 224 if not referenced :-(
335  pinModeFast(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32
336 }
337 
341 void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) {
342  irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction;
343 }
344 
351 
352  // Setup for cyclic 50 us interrupt
353  timerConfigForReceive(); // no interrupts enabled here!
354 
355  // Initialize state machine state
356  resume();
357 
358  // Timer interrupt is enabled after state machine reset
359  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
360 #ifdef _IR_MEASURE_TIMING
361  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
362 #endif
363 }
364 
365 /*
366  * Do not resume() reading of IR data
367  */
369  // Setup for cyclic 50 us interrupt
370  timerConfigForReceive(); // no interrupts enabled here!
371  // Timer interrupt is enabled after state machine reset
372  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
373 #ifdef _IR_MEASURE_TIMING
374  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
375 #endif
376 }
381  start();
382 }
383 
389 void IRrecv::start(uint32_t aMicrosecondsToAddToGapCounter) {
390  irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
391  start();
392 }
393 void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) {
394  irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
395  restartTimer();
396 }
397 void IRrecv::startWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
398  irparams.TickCounterForISR += aTicksToAddToGapCounter;
399  start();
400 }
401 void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
402  irparams.TickCounterForISR += aTicksToAddToGapCounter;
403  restartTimer();
404 }
405 
406 void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) {
407  irparams.TickCounterForISR += aTicksToAddToInternalTickCounter;
408 }
409 
410 void IRrecv::addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter) {
411  irparams.TickCounterForISR += aMicrosecondsToAddToInternalTickCounter / MICROS_PER_TICK;
412 }
417 #if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
418  start();
419 #endif
420 }
421 
425 void IRrecv::stop() {
427 }
428 
431 }
436  stop();
437 }
441 void IRrecv::end() {
442  stop();
443 }
444 
451 }
452 
458  // This check allows to call resume at arbitrary places or more than once
461  }
462 }
463 
469 
470  if (irparams.OverflowFlag) {
472 #if defined(LOCAL_DEBUG)
473  Serial.print(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of "));
474  Serial.print(RAW_BUFFER_LENGTH);
475  Serial.println(F(" with #define RAW_BUFFER_LENGTH=<biggerValue>"));
476 #endif
477 
478  } else {
480  // save last protocol, command and address for repeat handling (where they are compared or copied back :-))
481  lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC, Samsung and LG), so we must keep the original one
484 
485  }
486 
487  //These 2 variables allow to call resume() directly after decode, if no dump is required. since 4.3.0.
490 
496 }
497 
503 }
504 
510  return NULL;
511  }
512  if (decode()) {
513  return &decodedIRData;
514  } else {
515  return NULL;
516  }
517 }
518 
527  return false;
528  }
529 
530  initDecodedIRData(); // sets IRDATA_FLAGS_WAS_OVERFLOW
531 
533  /*
534  * Set OverflowFlag flag and return true here, to let the loop call resume or print raw data.
535  */
537  return true;
538  }
539 
540 #if defined(DECODE_NEC) || defined(DECODE_ONKYO)
541  IR_TRACE_PRINTLN(F("Attempting NEC/Onkyo decode"));
542  if (decodeNEC()) {
543  return true;
544  }
545 #endif
546 
547 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
548  IR_TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode"));
549  if (decodeKaseikyo()) {
550  return true;
551  }
552 #endif
553 
554 #if defined(DECODE_DENON)
555  IR_TRACE_PRINTLN(F("Attempting Denon/Sharp decode"));
556  if (decodeDenon()) {
557  return true;
558  }
559 #endif
560 
561 #if defined(DECODE_SONY)
562  IR_TRACE_PRINTLN(F("Attempting Sony decode"));
563  if (decodeSony()) {
564  return true;
565  }
566 #endif
567 
568 #if defined(DECODE_RC5)
569  IR_TRACE_PRINTLN(F("Attempting RC5 decode"));
570  if (decodeRC5()) {
571  return true;
572  }
573 #endif
574 
575 #if defined(DECODE_RC6)
576  IR_TRACE_PRINTLN(F("Attempting RC6 decode"));
577  if (decodeRC6()) {
578  return true;
579  }
580 #endif
581 
582 #if defined(DECODE_LG)
583  IR_TRACE_PRINTLN(F("Attempting LG decode"));
584  if (decodeLG()) {
585  return true;
586  }
587 #endif
588 
589 #if defined(DECODE_JVC)
590  IR_TRACE_PRINTLN(F("Attempting JVC decode"));
591  if (decodeJVC()) {
592  return true;
593  }
594 #endif
595 
596 #if defined(DECODE_SAMSUNG)
597  IR_TRACE_PRINTLN(F("Attempting Samsung decode"));
598  if (decodeSamsung()) {
599  return true;
600  }
601 #endif
602  /*
603  * Start of the exotic protocols
604  */
605 
606 #if defined(DECODE_BEO)
607  IR_TRACE_PRINTLN(F("Attempting Bang & Olufsen decode"));
608  if (decodeBangOlufsen()) {
609  return true;
610  }
611 #endif
612 
613 #if defined(DECODE_FAST)
614  IR_TRACE_PRINTLN(F("Attempting FAST decode"));
615  if (decodeFAST()) {
616  return true;
617  }
618 #endif
619 
620 #if defined(DECODE_WHYNTER)
621  IR_TRACE_PRINTLN(F("Attempting Whynter decode"));
622  if (decodeWhynter()) {
623  return true;
624  }
625 #endif
626 
627 #if defined(DECODE_LEGO_PF)
628  IR_TRACE_PRINTLN(F("Attempting Lego Power Functions"));
629  if (decodeLegoPowerFunctions()) {
630  return true;
631  }
632 #endif
633 
634 #if defined(DECODE_BOSEWAVE)
635  IR_TRACE_PRINTLN(F("Attempting Bosewave decode"));
636  if (decodeBoseWave()) {
637  return true;
638  }
639 #endif
640 
641 #if defined(DECODE_MAGIQUEST)
642  IR_TRACE_PRINTLN(F("Attempting MagiQuest decode"));
643  if (decodeMagiQuest()) {
644  return true;
645  }
646 #endif
647 
648  /*
649  * Try the universal decoder for pulse distance protocols
650  */
651 #if defined(DECODE_DISTANCE_WIDTH)
652  IR_TRACE_PRINTLN(F("Attempting universal Distance Width decode"));
653  if (decodeDistanceWidth()) {
654  return true;
655  }
656 #endif
657 
658  /*
659  * Last resort is the universal hash decode which always return true
660  */
661 #if defined(DECODE_HASH)
662  IR_TRACE_PRINTLN(F("Hash decode"));
663  // decodeHash returns a hash on any input.
664  // Thus, it needs to be last in the list.
665  // If you add any decodes, add them before this.
666  if (decodeHash()) {
667  return true;
668  }
669 #endif
670 
671  /*
672  * Return true here, to let the loop decide to call resume or to print raw data.
673  */
674  return true;
675 }
676 
677 /**********************************************************************************************************************
678  * Common decode functions
679  **********************************************************************************************************************/
703 bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint16_t aOneMarkMicros,
704  uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
705 
706  auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
707 
708  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
709 
710  IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
711  IRRawDataType tMask = 1UL; // Mask is only used for LSB first
712 
713  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
714  // get one mark and space pair
715  unsigned int tMarkTicks;
716  unsigned int tSpaceTicks;
717  bool tBitValue;
718 
719  if (isPulseDistanceProtocol) {
720  /*
721  * Pulse distance here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration.
722  */
723 #if defined DECODE_STRICT_CHECKS
724  tMarkTicks = *tRawBufPointer++;
725 #else
726  (void) aZeroSpaceMicros;
727  tRawBufPointer++;
728 #endif
729  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
730  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
731 
732 #if defined DECODE_STRICT_CHECKS
733  // Check for constant length mark
734  if (!matchMark(tMarkTicks, aOneMarkMicros)) {
735 # if defined(LOCAL_DEBUG)
736  Serial.print(F("Mark="));
737  Serial.print(tMarkTicks * MICROS_PER_TICK);
738  Serial.print(F(" is not "));
739  Serial.print(aOneMarkMicros);
740  Serial.print(F(". Index="));
741  Serial.print(aNumberOfBits - i);
742  Serial.print(' ');
743 # endif
744  return false;
745  }
746 #endif
747 
748  } else {
749  /*
750  * Pulse width here, it is not required to check (constant) space duration and zero mark duration.
751  */
752  tMarkTicks = *tRawBufPointer++;
753  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
754 
755 #if defined DECODE_STRICT_CHECKS
756  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
757 #else
758  (void) aZeroMarkMicros;
759  (void) aZeroSpaceMicros;
760  tRawBufPointer++;
761 #endif
762  }
763 
764  if (aMSBfirst) {
765  tDecodedData <<= 1;
766  }
767 
768  if (tBitValue) {
769  // It's a 1 -> set the bit
770  if (aMSBfirst) {
771  tDecodedData |= 1;
772  } else {
773  tDecodedData |= tMask;
774  }
775  IR_TRACE_PRINTLN('1');
776  } else {
777 #if defined DECODE_STRICT_CHECKS
778  /*
779  * Additionally check length of length parameter which determine a zero
780  */
781  if (isPulseDistanceProtocol) {
782  if (!matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
783 # if defined(LOCAL_DEBUG)
784  Serial.print(F("Space="));
785  Serial.print(tSpaceTicks * MICROS_PER_TICK);
786  Serial.print(F(" is not "));
787  Serial.print(aOneSpaceMicros);
788  Serial.print(F(" or "));
789  Serial.print(aZeroSpaceMicros);
790  Serial.print(F(". Index="));
791  Serial.print(aNumberOfBits - i);
792  Serial.print(' ');
793 # endif
794  return false;
795  }
796  } else {
797  if (!matchMark(tMarkTicks, aZeroMarkMicros)) {
798 # if defined(LOCAL_DEBUG)
799  Serial.print(F("Mark="));
800  Serial.print(tMarkTicks * MICROS_PER_TICK);
801  Serial.print(F(" is not "));
802  Serial.print(aOneMarkMicros);
803  Serial.print(F(" or "));
804  Serial.print(aZeroMarkMicros);
805  Serial.print(F(". Index="));
806  Serial.print(aNumberOfBits - i);
807  Serial.print(' ');
808 # endif
809  return false;
810  }
811  }
812 #endif
813  // do not set the bit
814  IR_TRACE_PRINTLN('0');
815  }
816 #if defined DECODE_STRICT_CHECKS
817  // If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
818  if (aZeroSpaceMicros == aOneSpaceMicros
819  && tRawBufPointer < &decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen]) {
820  // Check for constant length space (of pulse width protocol) here
821  if (!matchSpace(tSpaceTicks, aOneSpaceMicros)) {
822 # if defined(LOCAL_DEBUG)
823  Serial.print(F("Space="));
824  Serial.print(tSpaceTicks * MICROS_PER_TICK);
825  Serial.print(F(" is not "));
826  Serial.print(aOneSpaceMicros);
827  Serial.print(F(". Index="));
828  Serial.print(aNumberOfBits - i);
829  Serial.print(' ');
830 # endif
831  return false;
832  }
833  }
834 #endif
835  tMask <<= 1;
836  }
837  decodedIRData.decodedRawData = tDecodedData;
838  return true;
839 }
840 
845 bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
846  uint_fast8_t aStartOffset) {
847 
848  return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
849  aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros, aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros,
850  aProtocolConstants->DistanceWidthTimingInfo.ZeroSpaceMicros, aProtocolConstants->Flags);
851 }
852 
853 /*
854  * Static variables for the getBiphaselevel function
855  */
856 uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array
857 uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
858 uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals.
860 
861 void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) {
862  sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset;
863  sBiphaseTimeUnit = aBiphaseTimeUnit;
865 }
866 
883 uint_fast8_t IRrecv::getBiphaselevel() {
884  uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK)
885 
887  return SPACE; // After end of recorded buffer, assume space.
888  }
889 
890  tLevelOfCurrentInterval = (sBiphaseDecodeRawbuffOffset) & 1; // on odd rawbuf offsets we have mark timings
891 
892  /*
893  * Setup data if sUsedTimingIntervals is 0
894  */
895  if (sBiphaseUsedTimingIntervals == 0) {
896  uint16_t tCurrentTimingWith = decodedIRData.rawDataPtr->rawbuf[sBiphaseDecodeRawbuffOffset];
897  uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS;
898 
899  if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) {
901  } else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) {
903  } else if (matchTicks(tCurrentTimingWith, (3 * sBiphaseTimeUnit) + tMarkExcessCorrection)) {
905  } else {
906  return -1;
907  }
908  }
909 
910 // We use another interval from tCurrentTimingIntervals
912 
913 // keep track of current timing offset
915  // we have used all intervals of current timing, switch to next timing value
918  }
919 
920  IR_TRACE_PRINTLN(tLevelOfCurrentInterval);
921 
922  return tLevelOfCurrentInterval;
923 }
924 
925 /**********************************************************************************************************************
926  * Internal Hash decode function
927  **********************************************************************************************************************/
928 #define FNV_PRIME_32 16777619
929 #define FNV_BASIS_32 2166136261
930 
931 
936 uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
937  if (newval * 10 < oldval * 8) {
938  return 0;
939  }
940  if (oldval * 10 < newval * 8) {
941  return 2;
942  }
943  return 1;
944 }
945 
964  unsigned long hash = FNV_BASIS_32; // the result is the same no matter if we use a long or unsigned long variable
965 
966 // Require at least 6 samples to prevent triggering on noise
967  if (decodedIRData.rawlen < 6) {
968  return false;
969  }
970 #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
971  uint_fast8_t i;
972 #else
973  unsigned int i;
974 #endif
975  for (i = 1; (i + 2) < decodedIRData.rawlen; i++) {
976  // Compare mark with mark and space with space
977  uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]);
978  // Add value into the hash
979  hash = (hash * FNV_PRIME_32) ^ value;
980  }
981 
985 
986  return true;
987 }
988 
990  unsigned long hash = FNV_BASIS_32;
991 
992 // Require at least 6 samples to prevent triggering on noise
993  if (aResults->rawlen < 6) {
994  return false;
995  }
996 
997  for (uint8_t i = 3; i < aResults->rawlen; i++) {
998  uint_fast8_t value = compare(aResults->rawbuf[i - 2], aResults->rawbuf[i]);
999  // Add value into the hash
1000  hash = (hash * FNV_PRIME_32) ^ value;
1001  }
1002 
1003  aResults->value = hash;
1004  aResults->bits = 32;
1005  aResults->decode_type = UNKNOWN;
1007 
1008  return true;
1009 }
1010 
1011 /**********************************************************************************************************************
1012  * Match functions
1013  **********************************************************************************************************************/
1014 
1015 /*
1016  * returns true if values do match
1017  */
1019 // Check header "mark" and "space"
1021 #if defined(LOCAL_TRACE)
1022  Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
1023  Serial.println(F(": Header mark length is wrong"));
1024 #endif
1025  return false;
1026  }
1028 #if defined(LOCAL_TRACE)
1029  Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
1030  Serial.println(F(": Header space length is wrong"));
1031 #endif
1032  return false;
1033  }
1034  return true;
1035 }
1036 
1037 /*
1038  * Do 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.
1039  * And if really required, it can be enabled here, or done manually in user program.
1040  * And we have still no RC6 toggle bit check for detecting a second press on the same button.
1041  */
1042 void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks) {
1043  if (decodedIRData.rawDataPtr->rawbuf[0] < aMaximumRepeatSpaceTicks
1044 #if defined(ENABLE_FULL_REPEAT_CHECK)
1045  && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 85 bytes program space */
1046 #endif
1047  ) {
1049  }
1050 }
1051 
1056 bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1057 #if defined(LOCAL_TRACE)
1058  Serial.print(F("Testing: "));
1059  Serial.print(TICKS_LOW(aMatchValueMicros), DEC);
1060  Serial.print(F(" <= "));
1061  Serial.print(aMeasuredTicks, DEC);
1062  Serial.print(F(" <= "));
1063  Serial.print(TICKS_HIGH(aMatchValueMicros), DEC);
1064 #endif
1065  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
1066 #if defined(LOCAL_TRACE)
1067  if (passed) {
1068  Serial.println(F(" => passed"));
1069  } else {
1070  Serial.println(F(" => FAILED"));
1071  }
1072 #endif
1073  return passed;
1074 }
1075 
1076 bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
1077  return matchTicks(measured_ticks, desired_us);
1078 }
1079 
1083 bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1084 #if defined(LOCAL_TRACE)
1085  Serial.print(F("Testing mark (actual vs desired): "));
1086  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1087  Serial.print(F("us vs "));
1088  Serial.print(aMatchValueMicros, DEC);
1089  Serial.print(F("us: "));
1090  Serial.print(TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1091  Serial.print(F(" <= "));
1092  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1093  Serial.print(F(" <= "));
1094  Serial.print(TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1095 #endif
1096  // compensate for marks exceeded by demodulator hardware
1097  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS))
1098  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS)));
1099 #if defined(LOCAL_TRACE)
1100  if (passed) {
1101  Serial.println(F(" => passed"));
1102  } else {
1103  Serial.println(F(" => FAILED"));
1104  }
1105 #endif
1106  return passed;
1107 }
1108 
1109 bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
1110  return matchMark(measured_ticks, desired_us);
1111 }
1112 
1116 bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1117 #if defined(LOCAL_TRACE)
1118  Serial.print(F("Testing space (actual vs desired): "));
1119  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1120  Serial.print(F("us vs "));
1121  Serial.print(aMatchValueMicros, DEC);
1122  Serial.print(F("us: "));
1123  Serial.print(TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1124  Serial.print(F(" <= "));
1125  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1126  Serial.print(F(" <= "));
1127  Serial.print(TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1128 #endif
1129  // compensate for spaces shortened by demodulator hardware
1130  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS))
1131  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS)));
1132 #if defined(LOCAL_TRACE)
1133  if (passed) {
1134  Serial.println(F(" => passed"));
1135  } else {
1136  Serial.println(F(" => FAILED"));
1137  }
1138 #endif
1139  return passed;
1140 }
1141 
1142 bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) {
1143  return matchSpace(measured_ticks, desired_us);
1144 }
1145 
1150  return MARK_EXCESS_MICROS;
1151 }
1152 
1153 /*
1154  * Check if protocol is not detected and detected space between two transmissions
1155  * is smaller than known value for protocols (Sony with around 24 ms)
1156  * @return true, if CheckForRecordGapsMicros() has printed a message, i.e. gap < 15ms (RECORD_GAP_MICROS_WARNING_THRESHOLD)
1157  */
1158 bool IRrecv::checkForRecordGapsMicros(Print *aSerial) {
1159  /*
1160  * Check if protocol is not detected and detected space between two transmissions
1161  * is smaller than known value for protocols (Sony with around 24 ms)
1162  */
1165  aSerial->println();
1166  aSerial->print(F("Space of "));
1167  aSerial->print(decodedIRData.initialGap * MICROS_PER_TICK);
1168  aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of "));
1169  aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD);
1170  aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc.."));
1171  aSerial->println(F("But it can be OK for some yet unsupported protocols, and especially for repeats."));
1172  aSerial->println(F("If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h."));
1173  aSerial->println();
1174  return true;
1175  }
1176  return false;
1177 }
1178 
1179 /**********************************************************************************************************************
1180  * Print functions
1181  * Since a library should not allocate the "Serial" object, all functions require a pointer to a Print object.
1182  **********************************************************************************************************************/
1183 void IRrecv::printActiveIRProtocols(Print *aSerial) {
1184 // call no class function with same name
1185  ::printActiveIRProtocols(aSerial);
1186 }
1187 void printActiveIRProtocols(Print *aSerial) {
1188 #if defined(DECODE_ONKYO)
1189  aSerial->print(F("Onkyo, "));
1190 #elif defined(DECODE_NEC)
1191  aSerial->print(F("NEC/NEC2/Onkyo/Apple, "));
1192 #endif
1193 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
1194  aSerial->print(F("Panasonic/Kaseikyo, "));
1195 #endif
1196 #if defined(DECODE_DENON)
1197  aSerial->print(F("Denon/Sharp, "));
1198 #endif
1199 #if defined(DECODE_SONY)
1200  aSerial->print(F("Sony, "));
1201 #endif
1202 #if defined(DECODE_RC5)
1203  aSerial->print(F("RC5, "));
1204 #endif
1205 #if defined(DECODE_RC6)
1206  aSerial->print(F("RC6, "));
1207 #endif
1208 #if defined(DECODE_LG)
1209  aSerial->print(F("LG, "));
1210 #endif
1211 #if defined(DECODE_JVC)
1212  aSerial->print(F("JVC, "));
1213 #endif
1214 #if defined(DECODE_SAMSUNG)
1215  aSerial->print(F("Samsung, "));
1216 #endif
1217  /*
1218  * Start of the exotic protocols
1219  */
1220 #if defined(DECODE_BEO)
1221  aSerial->print(F("Bang & Olufsen, "));
1222 #endif
1223 #if defined(DECODE_FAST)
1224  aSerial->print(F("FAST, "));
1225 #endif
1226 #if defined(DECODE_WHYNTER)
1227  aSerial->print(F("Whynter, "));
1228 #endif
1229 #if defined(DECODE_LEGO_PF)
1230  aSerial->print(F("Lego Power Functions, "));
1231 #endif
1232 #if defined(DECODE_BOSEWAVE)
1233  aSerial->print(F("Bosewave , "));
1234 #endif
1235 #if defined(DECODE_MAGIQUEST)
1236  aSerial->print(F("MagiQuest, "));
1237 #endif
1238 #if defined(DECODE_DISTANCE_WIDTH)
1239  aSerial->print(F("Universal Pulse Distance Width, "));
1240 #endif
1241 #if defined(DECODE_HASH)
1242  aSerial->print(F("Hash "));
1243 #endif
1244 #if defined(NO_DECODER) // for sending raw only
1245  (void)aSerial; // to avoid compiler warnings
1246 #endif
1247 }
1248 
1259 bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
1260 // call no class function with same name
1261  ::printIRResultShort(aSerial, &decodedIRData, aPrintRepeatGap);
1262  if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) {
1263  return checkForRecordGapsMicros(aSerial);
1264  }
1265  return false;
1266 }
1267 
1268 void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo) {
1269  aSerial->print(aDistanceWidthTimingInfo->HeaderMarkMicros);
1270  aSerial->print(F(", "));
1271  aSerial->print(aDistanceWidthTimingInfo->HeaderSpaceMicros);
1272  aSerial->print(F(", "));
1273  aSerial->print(aDistanceWidthTimingInfo->OneMarkMicros);
1274  aSerial->print(F(", "));
1275  aSerial->print(aDistanceWidthTimingInfo->OneSpaceMicros);
1276  aSerial->print(F(", "));
1277  aSerial->print(aDistanceWidthTimingInfo->ZeroMarkMicros);
1278  aSerial->print(F(", "));
1279  aSerial->print(aDistanceWidthTimingInfo->ZeroSpaceMicros);
1280 }
1281 
1283  uint16_t tSumOfDurationTicks = 0;
1284  for (uint_fast8_t i = 1; i < decodedIRData.rawlen; i++) {
1285  tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i];
1286  }
1287  return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK;
1288 }
1289 
1297 void IRrecv::printIRSendUsage(Print *aSerial) {
1299  /*
1300  * Here we have a repeat of type NEC2 or SamsungLG. -> Inform the user to use this and not the initial protocol for sending.
1301  */
1302  Serial.print(F("!Use the "));
1303  Serial.print(getProtocolString());
1304  Serial.println(F(" protocol for sending!"));
1305  } else {
1308 #if defined(DECODE_DISTANCE_WIDTH)
1309  uint_fast8_t tNumberOfArrayData = 0;
1311 # if __INT_WIDTH__ < 32
1312  aSerial->print(F("Send on a 8 bit platform with: "));
1313  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1;
1314  if(tNumberOfArrayData > 1) {
1315  aSerial->println();
1316  aSerial->print(F(" uint32_t tRawData[]={0x"));
1317 # else
1318  aSerial->print(F("Send on a 32 bit platform with: "));
1319  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1;
1320  if(tNumberOfArrayData > 1) {
1321  aSerial->println();
1322  aSerial->print(F(" uint64_t tRawData[]={0x"));
1323 # endif
1324  for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
1325 # if (__INT_WIDTH__ < 32)
1326  aSerial->print(decodedIRData.decodedRawDataArray[i], HEX);
1327 # else
1328  PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX);
1329 # endif
1330  if (i != tNumberOfArrayData - 1) {
1331  aSerial->print(F(", 0x"));
1332  }
1333  }
1334  aSerial->println(F("};"));
1335  aSerial->print(F(" "));
1336  }
1337  } else {
1338  aSerial->print(F("Send with: "));
1339  }
1340  aSerial->print(F("IrSender.send"));
1341 
1342 #else
1343  aSerial->print(F("Send with: IrSender.send"));
1344 #endif
1345 
1346 #if defined(DECODE_DISTANCE_WIDTH)
1348 #endif
1349  aSerial->print(getProtocolString());
1350  aSerial->print(F("(0x"));
1351 #if defined(DECODE_MAGIQUEST)
1352  if (decodedIRData.protocol == MAGIQUEST) {
1353 # if (__INT_WIDTH__ < 32)
1354  aSerial->print(decodedIRData.decodedRawData, HEX);
1355 # else
1356  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1357 # endif
1358  } else {
1359  aSerial->print(decodedIRData.address, HEX);
1360  }
1361 #else
1362  /*
1363  * New decoders have address and command
1364  */
1365  aSerial->print(decodedIRData.address, HEX);
1366 #endif
1367 
1368  aSerial->print(F(", 0x"));
1369  aSerial->print(decodedIRData.command, HEX);
1370  if (decodedIRData.protocol == SONY) {
1371  aSerial->print(F(", 2, "));
1372  aSerial->print(decodedIRData.numberOfBits);
1373  } else {
1374  aSerial->print(F(", <numberOfRepeats>"));
1375  }
1376 
1377 #if defined(DECODE_DISTANCE_WIDTH)
1378  } else {
1379  /*
1380  * Pulse distance or pulse width here
1381  */
1382  aSerial->print("PulseDistanceWidth");
1383  if(tNumberOfArrayData > 1) {
1384  aSerial->print("FromArray(38, ");
1385  } else {
1386  aSerial->print("(38, ");
1387  }
1388  printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo);
1389 
1390  if(tNumberOfArrayData > 1) {
1391  aSerial->print(F(", &tRawData[0], "));
1392  } else {
1393  aSerial->print(F(", 0x"));
1394 # if (__INT_WIDTH__ < 32)
1395  aSerial->print(decodedIRData.decodedRawData, HEX);
1396 # else
1397  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1398 # endif
1399  aSerial->print(F(", "));
1400  }
1401  aSerial->print(decodedIRData.numberOfBits);// aNumberOfBits
1402  aSerial->print(F(", PROTOCOL_IS_"));
1403 
1405  aSerial->print('M');
1406  } else {
1407  aSerial->print('L');
1408  }
1409  aSerial->print(F("SB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>"));
1410  }
1411 #endif
1412 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
1414  aSerial->print(F(", 0x"));
1415  aSerial->print(decodedIRData.extra, HEX);
1416  }
1417 #endif
1418  aSerial->print(F(");"));
1419  aSerial->println();
1420  }
1421  }
1422 }
1423 
1430 void IRrecv::printIRResultMinimal(Print *aSerial) {
1431  aSerial->print(F("P="));
1432  aSerial->print(decodedIRData.protocol);
1433  if (decodedIRData.protocol == UNKNOWN) {
1434 #if defined(DECODE_HASH)
1435  aSerial->print(F(" #=0x"));
1436 # if (__INT_WIDTH__ < 32)
1437  aSerial->print(decodedIRData.decodedRawData, HEX);
1438 # else
1439  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1440 # endif
1441 #endif
1442  aSerial->print(' ');
1443  aSerial->print((decodedIRData.rawlen + 1) / 2, DEC);
1444  aSerial->println(F(" bits received"));
1445  } else {
1446  /*
1447  * New decoders have address and command
1448  */
1449  aSerial->print(F(" A=0x"));
1450  aSerial->print(decodedIRData.address, HEX);
1451 
1452  aSerial->print(F(" C=0x"));
1453  aSerial->print(decodedIRData.command, HEX);
1454 
1455  aSerial->print(F(" Raw=0x"));
1456 #if (__INT_WIDTH__ < 32)
1457  aSerial->print(decodedIRData.decodedRawData, HEX);
1458 #else
1459  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1460 #endif
1461 
1463  aSerial->print(F(" R"));
1464  }
1465  }
1466 }
1467 
1474 void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
1475 
1476  uint8_t tRawlen = decodedIRData.rawlen; // Get it once here in order to print quite consistent data, even if ISR is running
1477 // Print Raw data
1478  aSerial->print(F("rawData["));
1479  aSerial->print(tRawlen, DEC);
1480  aSerial->println(F("]: "));
1481 
1482  /*
1483  * Print initial gap
1484  */
1485  aSerial->print(F(" -"));
1486  if (aOutputMicrosecondsInsteadOfTicks) {
1487  aSerial->println((uint32_t) decodedIRData.initialGap * MICROS_PER_TICK, DEC);
1488  } else {
1489  aSerial->println(decodedIRData.initialGap, DEC);
1490  }
1491 #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
1492  uint_fast8_t i;
1493 #else
1494  unsigned int i;
1495 #endif
1496 
1497 // Newline is printed every 8. value, if tCounterForNewline % 8 == 0
1498  uint_fast8_t tCounterForNewline = 6; // first newline is after the 2 values of the start bit
1499 
1500 // check if we have a protocol with no or 8 start bits
1501 #if defined(DECODE_DENON) || defined(DECODE_MAGIQUEST)
1502  if (
1503 # if defined(DECODE_DENON)
1505 # endif
1506 # if defined(DECODE_MAGIQUEST)
1508 # endif
1509  false) {
1510  tCounterForNewline = 0; // no or 8 start bits
1511  }
1512 #endif
1513 
1514  uint32_t tDuration;
1515  uint16_t tSumOfDurationTicks = 0;
1516  for (i = 1; i < tRawlen; i++) {
1517  auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i];
1518  if (aOutputMicrosecondsInsteadOfTicks) {
1519  tDuration = tCurrentTicks * MICROS_PER_TICK;
1520  } else {
1521  tDuration = tCurrentTicks;
1522  }
1523  tSumOfDurationTicks += tCurrentTicks; // compute length of protocol frame
1524 
1525  if (!(i & 1)) { // even
1526  aSerial->print('-');
1527  } else { // odd
1528  aSerial->print(F(" +"));
1529  }
1530 
1531  // padding only for big values
1532  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 1000) {
1533  aSerial->print(' ');
1534  }
1535  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 100) {
1536  aSerial->print(' ');
1537  }
1538  if (tDuration < 10) {
1539  aSerial->print(' ');
1540  }
1541  aSerial->print(tDuration, DEC);
1542 
1543  if ((i & 1) && (i + 1) < tRawlen) {
1544  aSerial->print(','); //',' not required for last one
1545  }
1546 
1547  tCounterForNewline++;
1548  if ((tCounterForNewline % 8) == 0) {
1549  aSerial->println();
1550  }
1551  }
1552 
1553  aSerial->println();
1554  aSerial->print("Sum: ");
1555  if (aOutputMicrosecondsInsteadOfTicks) {
1556  aSerial->println((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC);
1557  } else {
1558  aSerial->println(tSumOfDurationTicks, DEC);
1559  }
1560 }
1561 
1573 void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
1574 // Start declaration
1575  if (aOutputMicrosecondsInsteadOfTicks) {
1576  aSerial->print(F("uint16_t rawData[")); // variable type, array name
1577  } else {
1578  aSerial->print(F("uint8_t rawTicks[")); // variable type, array name
1579  }
1580 
1581  aSerial->print(decodedIRData.rawlen - 1, DEC); // array size
1582  aSerial->print(F("] = {")); // Start declaration
1583 
1584 // Dump data
1585 #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
1586  uint_fast8_t i;
1587 #else
1588  unsigned int i;
1589 #endif
1590  for (i = 1; i < decodedIRData.rawlen; i++) {
1591  uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
1592 
1593  if (i & 1) {
1594  // Mark
1595  tDuration -= MARK_EXCESS_MICROS;
1596  } else {
1597  tDuration += MARK_EXCESS_MICROS;
1598  }
1599 
1600  if (aOutputMicrosecondsInsteadOfTicks) {
1601  aSerial->print(tDuration);
1602  } else {
1603  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
1604  /*
1605  * Clip to 8 bit value
1606  */
1607  tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks;
1608  aSerial->print(tTicks);
1609  }
1610  if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one
1611  if (!(i & 1)) aSerial->print(' ');
1612  }
1613 
1614 // End declaration
1615  aSerial->print(F("};")); //
1616 
1617 // Comment
1618  aSerial->print(F(" // "));
1619  printIRResultShort(aSerial);
1620 
1621 // Newline
1622  aSerial->println("");
1623 }
1624 
1635 
1636 // Store data, skip leading space#
1637 #if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
1638  uint_fast8_t i;
1639 #else
1640  unsigned int i;
1641 #endif
1642  for (i = 1; i < decodedIRData.rawlen; i++) {
1643  uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
1644  if (i & 1) {
1645  // Mark
1646  tDuration -= MARK_EXCESS_MICROS;
1647  } else {
1648  tDuration += MARK_EXCESS_MICROS;
1649  }
1650 
1651  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
1652  *aArrayPtr = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; // we store it in an 8 bit array
1653  aArrayPtr++;
1654  }
1655 }
1656 
1662 // Now dump "known" codes
1663  if (decodedIRData.protocol != UNKNOWN) {
1664 
1665  /*
1666  * New decoders have address and command
1667  */
1668  aSerial->print(F("uint16_t"));
1669  aSerial->print(F(" address = 0x"));
1670  aSerial->print(decodedIRData.address, HEX);
1671  aSerial->println(';');
1672 
1673  aSerial->print(F("uint16_t"));
1674  aSerial->print(F(" command = 0x"));
1675  aSerial->print(decodedIRData.command, HEX);
1676  aSerial->println(';');
1677 
1678  // All protocols have raw data
1679 #if __INT_WIDTH__ < 32
1680  aSerial->print(F("uint32_t rawData = 0x"));
1681 #else
1682  aSerial->print(F("uint64_t rawData = 0x"));
1683 #endif
1684 #if (__INT_WIDTH__ < 32)
1685  aSerial->print(decodedIRData.decodedRawData, HEX);
1686 #else
1687  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1688 #endif
1689  aSerial->println(';');
1690  aSerial->println();
1691  }
1692 }
1693 
1694 #if defined(__AVR__)
1695 const __FlashStringHelper* IRrecv::getProtocolString() {
1696 // call no class function with same name
1698 }
1699 #else
1701  // call no class function with same name
1703 }
1704 #endif
1705 
1706 /**********************************************************************************************************************
1707  * The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials
1708  * This function calls the old MSB first decoders and fills only the 3 variables:
1709  * aResults->value
1710  * aResults->bits
1711  * aResults->decode_type
1712  **********************************************************************************************************************/
1714 
1716  return false;
1717  }
1718 
1719 // copy for usage by legacy programs
1720  aResults->rawbuf = irparams.rawbuf;
1721  aResults->rawlen = irparams.rawlen;
1722  if (irparams.OverflowFlag) {
1723  // Copy overflow flag to decodedIRData.flags
1724  irparams.OverflowFlag = false;
1725  irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call
1726  IR_DEBUG_PRINTLN(F("Overflow happened"));
1727  }
1728  aResults->overflow = irparams.OverflowFlag;
1729  aResults->value = 0;
1730 
1732 
1733 #if defined(DECODE_NEC)
1734  IR_DEBUG_PRINTLN(F("Attempting old NEC decode"));
1735  if (decodeNECMSB(aResults)) {
1736  return true;
1737  }
1738 #endif
1739 
1740 #if defined(DECODE_SONY)
1741  IR_DEBUG_PRINTLN(F("Attempting old Sony decode"));
1742  if (decodeSonyMSB(aResults)) {
1743  return true;
1744  }
1745 #endif
1746 
1747 #if defined(DECODE_RC5)
1748  IR_DEBUG_PRINTLN(F("Attempting RC5 decode"));
1749  if (decodeRC5()) {
1750  aResults->bits = decodedIRData.numberOfBits;
1751  aResults->value = decodedIRData.decodedRawData;
1752  aResults->decode_type = RC5;
1753 
1754  return true;
1755  }
1756 #endif
1757 
1758 #if defined(DECODE_RC6)
1759  IR_DEBUG_PRINTLN(F("Attempting RC6 decode"));
1760  if (decodeRC6()) {
1761  aResults->bits = decodedIRData.numberOfBits;
1762  aResults->value = decodedIRData.decodedRawData;
1763  aResults->decode_type = RC6;
1764  return true;
1765  }
1766 #endif
1767 
1768 // Removed bool IRrecv::decodePanasonicMSB(decode_results *aResults) since implementations was wrong (wrong length), and nobody recognized it
1769 
1770 #if defined(DECODE_LG)
1771  IR_DEBUG_PRINTLN(F("Attempting old LG decode"));
1772  if (decodeLGMSB(aResults)) {return true;}
1773 #endif
1774 
1775 #if defined(DECODE_JVC)
1776  IR_DEBUG_PRINTLN(F("Attempting old JVC decode"));
1777  if (decodeJVCMSB(aResults)) {
1778  return true;
1779  }
1780 #endif
1781 
1782 #if defined(DECODE_SAMSUNG)
1783  IR_DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
1784  if (decodeSAMSUNG(aResults)) {
1785  return true;
1786  }
1787 #endif
1788 
1789 #if defined(DECODE_DENON)
1790  IR_DEBUG_PRINTLN(F("Attempting old Denon decode"));
1791  if (decodeDenonOld(aResults)) {
1792  return true;
1793  }
1794 #endif
1795 
1796 // decodeHash returns a hash on any input.
1797 // Thus, it needs to be last in the list.
1798 // If you add any decodes, add them before this.
1799  if (decodeHashOld(aResults)) {
1800  return true;
1801  }
1802 // Throw away and start over
1803  resume();
1804  return false;
1805 }
1806 
1808 #if defined(_IR_MEASURE_TIMING)
1809 #undef _IR_MEASURE_TIMING
1810 #endif
1811 #if defined(LOCAL_TRACE)
1812 #undef LOCAL_TRACE
1813 #endif
1814 #if defined(LOCAL_DEBUG)
1815 #undef LOCAL_DEBUG
1816 #endif
1817 #endif // _IR_RECEIVE_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:109
timerConfigForReceive
void timerConfigForReceive()
Configures the timer to be able to generate the receive sample interrupt, which consumes a small amou...
Definition: IRTimer.hpp:103
MICROS_PER_TICK
#define MICROS_PER_TICK
microseconds per clock interrupt tick
Definition: IRremote.hpp:249
IRrecv::decodeHash
bool decodeHash()
decodeHash - decode an arbitrary IR code.
Definition: IRReceive.hpp:963
decode_results
Results returned from old decoders !!!deprecated!!!
Definition: IRremoteInt.h:159
digitalReadFast
#define digitalReadFast
Definition: digitalWriteFast.h:393
DistanceWidthTimingInfoStruct::HeaderMarkMicros
uint16_t HeaderMarkMicros
Definition: IRProtocol.h:79
decode_results::rawbuf
uint16_t * rawbuf
Definition: IRremoteInt.h:170
DECODE_MAGIQUEST
#define DECODE_MAGIQUEST
Definition: IRremote.hpp:110
setFeedbackLED
void setFeedbackLED(bool aSwitchLedOn)
Flash LED while receiving or sending IR data.
Definition: IRFeedbackLED.hpp:108
IRrecv::stop
void stop()
Disables the timer for IR reception.
Definition: IRReceive.hpp:425
IRrecv::lastDecodedProtocol
decode_type_t lastDecodedProtocol
Definition: IRremoteInt.h:324
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:118
RECORD_GAP_TICKS
#define RECORD_GAP_TICKS
Minimum gap between IR transmissions, in MICROS_PER_TICK.
Definition: IRremote.hpp:172
IRrecv::disableIRIn
void disableIRIn()
Alias for stop().
Definition: IRReceive.hpp:435
IRrecv::enableIRIn
void enableIRIn()
Alias for start().
Definition: IRReceive.hpp:380
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:150
pinModeFast
#define pinModeFast
Definition: digitalWriteFast.h:371
IRrecv::checkForRecordGapsMicros
bool checkForRecordGapsMicros(Print *aSerial)
Definition: IRReceive.hpp:1158
digitalWriteFast
#define digitalWriteFast
Definition: digitalWriteFast.h:339
IRrecv::registerReceiveCompleteCallback
void registerReceiveCompleteCallback(void(*aReceiveCompleteCallbackFunction)(void))
Sets the function to call if a protocol message has arrived.
Definition: IRReceive.hpp:341
IRrecv
Main class for receiving IR signals.
Definition: IRremoteInt.h:176
IRrecv::decodeDistanceWidth
bool decodeDistanceWidth()
Definition: ir_DistanceWidthProtocol.hpp:152
SONY
@ SONY
Definition: IRProtocol.h:64
IRData::rawlen
uint_fast8_t rawlen
counter of entries in rawbuf
Definition: IRProtocol.h:123
PULSE_WIDTH
@ PULSE_WIDTH
Definition: IRProtocol.h:42
decode_results::overflow
bool overflow
Definition: IRremoteInt.h:172
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:91
PulseDistanceWidthProtocolConstants::ProtocolIndex
decode_type_t ProtocolIndex
Definition: IRProtocol.h:133
IRrecv::restartAfterSend
void restartAfterSend()
Restarts receiver after send.
Definition: IRReceive.hpp:416
IRrecv::IRrecv
IRrecv()
Instantiate the IRrecv class.
Definition: IRReceive.hpp:75
sBiphaseDecodeRawbuffOffset
uint_fast8_t sBiphaseDecodeRawbuffOffset
Definition: IRReceive.hpp:856
TICKS_LOW
#define TICKS_LOW(us)
Definition: IRremoteInt.h:392
IRrecv::printIRResultAsCVariables
void printIRResultAsCVariables(Print *aSerial)
Print results as C variables to be used for sendXXX()
Definition: IRReceive.hpp:1661
DistanceWidthTimingInfoStruct::OneSpaceMicros
uint16_t OneSpaceMicros
Definition: IRProtocol.h:82
irparams_struct::rawbuf
uint16_t rawbuf[RAW_BUFFER_LENGTH]
raw data / tick counts per mark/space, first entry is the length of the gap between previous and curr...
Definition: IRremoteInt.h:113
IRData::rawDataPtr
irparams_struct * rawDataPtr
Pointer of the raw timing data to be decoded. Mainly the OverflowFlag and the data buffer filled by r...
Definition: IRProtocol.h:129
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:92
decode_results::bits
uint8_t bits
Definition: IRremoteInt.h:165
decode_results::decode_type
decode_type_t decode_type
Definition: IRremoteInt.h:162
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:112
matchTicks
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Match function without compensating for marks exceeded or spaces shortened by demodulator hardware Cu...
Definition: IRReceive.hpp:1056
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:105
PULSE_DISTANCE
@ PULSE_DISTANCE
Definition: IRProtocol.h:43
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:286
IRrecv::checkForRepeatSpaceTicksAndSetFlag
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks)
Definition: IRReceive.hpp:1042
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:168
IRrecv::decodeSonyMSB
bool decodeSonyMSB(decode_results *aResults)
Definition: ir_Sony.hpp:154
IRrecv::decodeSony
bool decodeSony()
Definition: ir_Sony.hpp:109
irparams_struct
This struct contains the data and control used for receiver static functions and the ISR (interrupt s...
Definition: IRremoteInt.h:95
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1116
DistanceWidthTimingInfoStruct::ZeroMarkMicros
uint16_t ZeroMarkMicros
Definition: IRProtocol.h:83
IRrecv::read
IRData * read()
If IR receiver data is available, returns pointer to IrReceiver.decodedIRData, else NULL.
Definition: IRReceive.hpp:508
IRrecv::getBiphaselevel
uint_fast8_t getBiphaselevel()
Gets the level of one time interval (aBiphaseTimeUnit) at a time from the raw buffer.
Definition: IRReceive.hpp:883
MAGIQUEST
@ MAGIQUEST
Definition: IRProtocol.h:69
irparams_struct::rawlen
uint_fast8_t rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:109
sBiphaseCurrentTimingIntervals
uint16_t sBiphaseCurrentTimingIntervals
Definition: IRReceive.hpp:857
timerDisableReceiveInterrupt
void timerDisableReceiveInterrupt()
Disables the receive sample timer interrupt.
Definition: IRTimer.hpp:115
IRrecv::decodePulseDistanceWidthData
bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset=3)
Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
Definition: IRReceive.hpp:845
IRrecv::decodeLGMSB
bool decodeLGMSB(decode_results *aResults)
Definition: ir_LG.hpp:290
PulseDistanceWidthProtocolConstants::Flags
uint8_t Flags
Definition: IRProtocol.h:136
irparams
struct irparams_struct irparams
Definition: IRReceive.hpp:69
decode_results::value
uint32_t value
Definition: IRremoteInt.h:164
DistanceWidthTimingInfoStruct
Definition: IRProtocol.h:78
MATCH_SPACE
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1142
IRrecv::decodeSAMSUNG
bool decodeSAMSUNG(decode_results *aResults)
Definition: ir_Samsung.hpp:343
IRrecv::decodeBangOlufsen
bool decodeBangOlufsen()
Definition: ir_BangOlufsen.hpp:290
IRrecv::decodeLegoPowerFunctions
bool decodeLegoPowerFunctions()
Definition: ir_Lego.hpp:127
irparams_struct::OverflowFlag
bool OverflowFlag
Raw buffer OverflowFlag occurred.
Definition: IRremoteInt.h:107
IRrecv::decodeFAST
bool decodeFAST()
Definition: ir_FAST.hpp:97
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:132
FeedbackLEDControlStruct::LedFeedbackEnabled
uint8_t LedFeedbackEnabled
LED_FEEDBACK_ENABLED_FOR_RECEIVE or LED_FEEDBACK_ENABLED_FOR_SEND -> enable blinking of pin on IR pro...
Definition: IRFeedbackLED.hpp:44
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:321
IRData
Data structure for the user application, available as decodedIRData.
Definition: IRProtocol.h:107
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:96
FNV_PRIME_32
#define FNV_PRIME_32
used for decodeHash()
Definition: IRReceive.hpp:928
IRrecv::decodeSamsung
bool decodeSamsung()
Definition: ir_Samsung.hpp:244
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:119
IRData::initialGap
uint16_t initialGap
rawbuf[0] contains the initial gap of the last frame.
Definition: IRProtocol.h:127
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:97
DistanceWidthTimingInfoStruct::OneMarkMicros
uint16_t OneMarkMicros
Definition: IRProtocol.h:81
IRrecv::printIRResultShort
bool printIRResultShort(Print *aSerial, bool aPrintRepeatGap=true, bool aCheckForRecordGapsMicros=true)
Function to print values and flags of IrReceiver.decodedIRData in one line.
Definition: IRReceive.hpp:1259
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:98
DO_NOT_ENABLE_LED_FEEDBACK
#define DO_NOT_ENABLE_LED_FEEDBACK
Definition: IRremoteInt.h:354
MATCH
bool MATCH(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1076
IRrecv::checkHeader
bool checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants)
Definition: IRReceive.hpp:1018
sBiphaseUsedTimingIntervals
uint_fast8_t sBiphaseUsedTimingIntervals
Definition: IRReceive.hpp:858
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:936
IRrecv::printActiveIRProtocols
static void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1183
printActiveIRProtocols
void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1187
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:110
IR_REC_STATE_STOP
#define IR_REC_STATE_STOP
Definition: IRremoteInt.h:89
IR_REC_STATE_MARK
#define IR_REC_STATE_MARK
Definition: IRremoteInt.h:87
IRReceiveTimerInterruptHandler
void IRReceiveTimerInterruptHandler()
Definition: IRReceive.hpp:127
IRrecv::restartTimer
void restartTimer()
Definition: IRReceive.hpp:368
IRrecv::restartTimerWithTicksToAdd
void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter)
Definition: IRReceive.hpp:401
FNV_BASIS_32
#define FNV_BASIS_32
used for decodeHash()
Definition: IRReceive.hpp:929
IRrecv::isIdle
bool isIdle()
Returns status of reception.
Definition: IRReceive.hpp:449
sBiphaseTimeUnit
uint16_t sBiphaseTimeUnit
Definition: IRReceive.hpp:859
timerResetInterruptPending
void timerResetInterruptPending()
IRrecv::printDistanceWidthTimingInfo
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo)
Definition: IRReceive.hpp:1268
timerEnableReceiveInterrupt
void timerEnableReceiveInterrupt()
Enables the receive sample timer interrupt, which consumes a small amount of CPU every 50 us.
Definition: IRTimer.hpp:108
getMarkExcessMicros
int getMarkExcessMicros()
Getter function for MARK_EXCESS_MICROS.
Definition: IRReceive.hpp:1149
LED_FEEDBACK_ENABLED_FOR_RECEIVE
#define LED_FEEDBACK_ENABLED_FOR_RECEIVE
Definition: IRremoteInt.h:356
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1083
IRrecv::compensateAndPrintIRResultAsCArray
void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks=true)
Dump out the IrReceiver.decodedIRData.rawDataPtr->rawbuf[] to be used as C definition for sendRaw().
Definition: IRReceive.hpp:1573
MATCH_MARK
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1109
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:103
irparams_struct::StateForISR
volatile uint8_t StateForISR
State Machine state.
Definition: IRremoteInt.h:97
IRrecv::setReceivePin
void setReceivePin(uint_fast8_t aReceivePinNumber)
Sets / changes the receiver pin number.
Definition: IRReceive.hpp:309
DistanceWidthTimingInfoStruct::ZeroSpaceMicros
uint16_t ZeroSpaceMicros
Definition: IRProtocol.h:84
IRrecv::decodeDenonOld
bool decodeDenonOld(decode_results *aResults)
Definition: ir_Denon.hpp:280
IRRawDataType
uint32_t IRRawDataType
Definition: IRremoteInt.h:117
IRrecv::start
void start()
Start the receiving process.
Definition: IRReceive.hpp:350
IRrecv::compensateAndStoreIRResultInArray
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr)
Store the decodedIRData to be used for sendRaw().
Definition: IRReceive.hpp:1634
IRrecv::printIRResultMinimal
void printIRResultMinimal(Print *aSerial)
Function to print protocol number, address, command, raw data and repeat flag of IrReceiver....
Definition: IRReceive.hpp:1430
IR_TRACE_PRINTLN
#define IR_TRACE_PRINTLN(...)
Definition: IRremoteInt.h:149
IRrecv::initDecodedIRData
void initDecodedIRData()
Is internally called by decode before calling decoders.
Definition: IRReceive.hpp:468
KASEIKYO
@ KASEIKYO
Definition: IRProtocol.h:53
DENON
@ DENON
Definition: IRProtocol.h:45
IRrecv::addMicrosToInternalTickCounter
void addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter)
Definition: IRReceive.hpp:410
DECODE_DENON
#define DECODE_DENON
Definition: IRremote.hpp:96
IRDATA_FLAGS_IS_MSB_FIRST
#define IRDATA_FLAGS_IS_MSB_FIRST
Value is mainly determined by the (known) protocol.
Definition: IRProtocol.h:99
IRrecv::lastDecodedCommand
uint32_t lastDecodedCommand
Definition: IRremoteInt.h:326
TICKS_HIGH
#define TICKS_HIGH(us)
Definition: IRremoteInt.h:393
IRrecv::decodeRC5
bool decodeRC5()
Try to decode data as RC5 protocol.
Definition: ir_RC5_RC6.hpp:155
IRrecv::decodeBoseWave
bool decodeBoseWave()
Definition: ir_BoseWave.hpp:64
IRDATA_FLAGS_EMPTY
#define IRDATA_FLAGS_EMPTY
Definition: IRProtocol.h:90
RC5
@ RC5
Definition: IRProtocol.h:58
IRrecv::available
bool available()
Returns true if IR receiver data is available.
Definition: IRReceive.hpp:501
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRProtocol.h:111
PulseDistanceWidthProtocolConstants::DistanceWidthTimingInfo
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo
Definition: IRProtocol.h:135
IRrecv::decodeMagiQuest
bool decodeMagiQuest()
Definition: ir_MagiQuest.hpp:151
INPUT_MARK
#define INPUT_MARK
Sensor output for a mark ("flash")
Definition: IRremote.hpp:183
FeedbackLEDControl
struct FeedbackLEDControlStruct FeedbackLEDControl
The feedback LED control instance.
Definition: IRFeedbackLED.hpp:47
IRrecv::initBiphaselevel
void initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit)
Definition: IRReceive.hpp:861
IRrecv::end
void end()
Alias for stop().
Definition: IRReceive.hpp:441
SPACE
#define SPACE
Definition: IRremoteInt.h:39
IRrecv::decodeNECMSB
bool decodeNECMSB(decode_results *aResults)
Definition: ir_NEC.hpp:339
IRrecv::decodeNEC
bool decodeNEC()
Decodes also Onkyo and Apple.
Definition: ir_NEC.hpp:232
RC6
@ RC6
Definition: IRProtocol.h:59
IRrecv::decodeHashOld
bool decodeHashOld(decode_results *aResults)
Definition: IRReceive.hpp:989
IRrecv::printIRSendUsage
void printIRSendUsage(Print *aSerial)
Function to print values and flags of IrReceiver.decodedIRData in one line.
Definition: IRReceive.hpp:1297
IRrecv::decodeDenon
bool decodeDenon()
Definition: ir_Denon.hpp:155
IRrecv::decodeLG
bool decodeLG()
Definition: ir_LG.hpp:176
IRrecv::addTicksToInternalTickCounter
void addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter)
Definition: IRReceive.hpp:406
IRrecv::stopTimer
void stopTimer()
Definition: IRReceive.hpp:429
IRrecv::decode
bool decode()
The main decode function, attempts to decode the recently receive IR signal.
Definition: IRReceive.hpp:525
IRrecv::decodeJVC
bool decodeJVC()
Definition: ir_JVC.hpp:119
UNKNOWN
@ UNKNOWN
Definition: IRProtocol.h:41
RAW_BUFFER_LENGTH
#define RAW_BUFFER_LENGTH
The length of the buffer where the IR timing data is stored before decoding 100 is sufficient for mos...
Definition: IRremoteInt.h:74
IRrecv::lastDecodedAddress
uint32_t lastDecodedAddress
Definition: IRremoteInt.h:325
IRrecv::decodeKaseikyo
bool decodeKaseikyo()
Definition: ir_Kaseikyo.hpp:199
IR_DEBUG_PRINTLN
#define IR_DEBUG_PRINTLN(...)
If DEBUG, print the arguments as a line, otherwise do nothing.
Definition: IRremoteInt.h:141
IRrecv::getTotalDurationOfRawData
uint32_t getTotalDurationOfRawData()
Definition: IRReceive.hpp:1282
decode_results::rawlen
uint_fast8_t rawlen
Definition: IRremoteInt.h:171
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:108
IRrecv::decodeRC6
bool decodeRC6()
Try to decode data as RC6 protocol.
Definition: ir_RC5_RC6.hpp:394
IR_REC_STATE_SPACE
#define IR_REC_STATE_SPACE
Definition: IRremoteInt.h:88
IRrecv::getProtocolString
const char * getProtocolString()
Definition: IRReceive.hpp:1700
IRrecv::resume
void resume()
Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame.
Definition: IRReceive.hpp:457
MARK
#define MARK
Definition: IRremoteInt.h:38
DistanceWidthTimingInfoStruct::HeaderSpaceMicros
uint16_t HeaderSpaceMicros
Definition: IRProtocol.h:80
IRrecv::startWithTicksToAdd
void startWithTicksToAdd(uint16_t aTicksToAddToGapCounter)
Definition: IRReceive.hpp:397
IRrecv::decode_old
bool decode_old(decode_results *aResults)
Definition: IRReceive.hpp:1713
IrReceiver
IRrecv IrReceiver
The receiver instance.
Definition: IRReceive.hpp:64
IRrecv::printIRResultRawFormatted
void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks=true)
Dump out the timings in IrReceiver.decodedIRData.rawDataPtr->rawbuf[] array 8 values per line.
Definition: IRReceive.hpp:1474
IR_REC_STATE_IDLE
#define IR_REC_STATE_IDLE
Definition: IRremoteInt.h:86
getProtocolString
const char * getProtocolString(decode_type_t aProtocol)
Definition: IRProtocol.hpp:96
IRrecv::decodeJVCMSB
bool decodeJVCMSB(decode_results *aResults)
Definition: ir_JVC.hpp:177
setLEDFeedback
void setLEDFeedback(uint8_t aFeedbackLEDPin, uint8_t aEnableLEDFeedback)
Enable blinking of feedback LED (LED_BUILTIN is taken as default) on IR sending and receiving Cannot ...
Definition: IRFeedbackLED.hpp:56
SHARP
@ SHARP
Definition: IRProtocol.h:63
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:98