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 //
60 
61 /*
62  * The control structure instance
63  */
64 struct irparams_struct irparams; // the irparams instance
65 
71  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
72  setReceivePin(0);
73 #if !defined(NO_LED_FEEDBACK_CODE)
75 #endif
76 }
77 
78 IRrecv::IRrecv(uint_fast8_t aReceivePin) {
79  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
80  setReceivePin(aReceivePin);
81 #if !defined(NO_LED_FEEDBACK_CODE)
83 #endif
84 }
85 
91 IRrecv::IRrecv(uint_fast8_t aReceivePin, uint_fast8_t aFeedbackLEDPin) {
92  decodedIRData.rawDataPtr = &irparams; // for decodePulseDistanceData() etc.
93  setReceivePin(aReceivePin);
94 #if !defined(NO_LED_FEEDBACK_CODE)
96 #else
97  (void) aFeedbackLEDPin;
98 #endif
99 }
100 
101 /**********************************************************************************************************************
102  * Interrupt Service Routine - Called every 50 us
103  *
104  * Duration in ticks of 50 us of alternating SPACE, MARK are recorded in irparams.rawbuf array.
105  * 'rawlen' counts the number of entries recorded so far.
106  * First entry is the SPACE between transmissions.
107  *
108  * As soon as one SPACE entry gets longer than RECORD_GAP_TICKS, state switches to STOP (frame received). Timing of SPACE continues.
109  * A call of resume() switches from STOP to IDLE.
110  * As soon as first MARK arrives in IDLE, gap width is recorded and new logging starts.
111  *
112  * With digitalRead and Feedback LED
113  * 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
114  * With portInputRegister and mask and Feedback LED code commented
115  * 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
116  * => Minimal CPU frequency is 4 MHz
117  *
118  **********************************************************************************************************************/
119 #if defined(ESP8266) || defined(ESP32)
120 IRAM_ATTR
121 #endif
123 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
124  digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
125 #endif
126 // 7 - 8.5 us for ISR body (without pushes and pops) for ATmega328 @16MHz
127 
128 #if defined(TIMER_REQUIRES_RESET_INTR_PENDING)
129  timerResetInterruptPending(); // reset TickCounterForISR interrupt flag if required (currently only for Teensy and ATmega4809)
130 #endif
131 
132 // Read if IR Receiver -> SPACE [xmt LED off] or a MARK [xmt LED on]
133 #if defined(__AVR__)
134  uint8_t tIRInputLevel = *irparams.IRReceivePinPortInputRegister & irparams.IRReceivePinMask;
135 #else
136  uint_fast8_t tIRInputLevel = (uint_fast8_t) digitalReadFast(irparams.IRReceivePin);
137 #endif
138 
139  /*
140  * Increase TickCounter and clip it at maximum 0xFFFF / 3.2 seconds at 50 us ticks
141  */
142  if (irparams.TickCounterForISR < UINT16_MAX) {
143  irparams.TickCounterForISR++; // One more 50uS tick
144  }
145 
146  /*
147  * Due to a ESP32 compiler bug https://github.com/espressif/esp-idf/issues/1552 no switch statements are possible for ESP32
148  * So we change the code to if / else if
149  */
150 // switch (irparams.StateForISR) {
151 //
153  /*
154  * Here we are just resumed and maybe in the middle of a transmission
155  */
156  if (tIRInputLevel == INPUT_MARK) {
157  // check if we did not start in the middle of a transmission by checking the minimum length of leading space
159 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
160 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
161 #endif
162  /*
163  * Gap between two transmissions just ended; Record gap duration + start recording transmission
164  * Initialize all state machine variables
165  */
166  irparams.OverflowFlag = false;
167 // irparams.rawbuf[0] = irparams.TickCounterForISR;
168  irparams.initialGapTicks = irparams.TickCounterForISR; // Enabling 8 bit buffer since 4.4
169  irparams.rawlen = 1;
171  } // otherwise stay in idle state
172  irparams.TickCounterForISR = 0; // reset counter in both cases
173  }
174 
175  } else if (irparams.StateForISR == IR_REC_STATE_MARK) { // Timing mark
176  if (tIRInputLevel != INPUT_MARK) {
177  /*
178  * Mark ended here. Record mark time in rawbuf array
179  */
180 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
181 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
182 #endif
185  irparams.TickCounterForISR = 0; // This resets the tick counter also at end of frame :-)
186  }
187 
188  } else if (irparams.StateForISR == IR_REC_STATE_SPACE) { // Timing space
189  if (tIRInputLevel == INPUT_MARK) {
190  /*
191  * Space ended here. Check for overflow and record space time in rawbuf array
192  */
194  // Flag up a read OverflowFlag; Stop the state machine
195  irparams.OverflowFlag = true;
197 #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
198  /*
199  * Call callback if registered (not NULL)
200  */
203  }
204 #endif
205  } else {
206 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
207 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
208 #endif
211  }
213 
215  /*
216  * Maximum space duration reached here.
217  * Current code is ready for processing!
218  * We received a long space, which indicates gap between codes.
219  * Switch to IR_REC_STATE_STOP
220  * Don't reset TickCounterForISR; keep counting width of next leading space
221  */
222  /*
223  * These 2 variables allow to call resume() directly after decode.
224  * After resume(), decodedIRData.rawDataPtr->initialGapTicks and decodedIRData.rawDataPtr->rawlen are
225  * the first variables, which are overwritten by the next received frame.
226  * since 4.3.0.
227  */
231 #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
232  /*
233  * Call callback if registered (not NULL)
234  */
237  }
238 #endif
239  }
240  } else if (irparams.StateForISR == IR_REC_STATE_STOP) {
241  /*
242  * Complete command received
243  * stay here until resume() is called, which switches state to IR_REC_STATE_IDLE
244  */
245 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
246 // digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles
247 #endif
248  if (tIRInputLevel == INPUT_MARK) {
249  // Reset gap TickCounterForISR, to prepare for detection if we are in the middle of a transmission after call of resume()
251  }
252  }
253 
254 #if !defined(NO_LED_FEEDBACK_CODE)
256  setFeedbackLED(tIRInputLevel == INPUT_MARK);
257  }
258 #endif
259 
260 #ifdef _IR_MEASURE_TIMING
261  digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles
262 #endif
263 
264 }
265 
266 /*
267  * The ISR, which calls the interrupt handler
268  */
269 #if defined(TIMER_INTR_NAME) || defined(ISR)
270 # if defined(TIMER_INTR_NAME)
271 ISR (TIMER_INTR_NAME) // for ISR definitions
272 # elif defined(ISR)
273 ISR()
274 // for functions definitions which are called by separate (board specific) ISR
275 # endif
276 {
278 }
279 #endif
280 
281 /**********************************************************************************************************************
282  * Stream like API
283  **********************************************************************************************************************/
290 void IRrecv::begin(uint_fast8_t aReceivePin, bool aEnableLEDFeedback, uint_fast8_t aFeedbackLEDPin) {
291 
292  setReceivePin(aReceivePin);
293 #if !defined(NO_LED_FEEDBACK_CODE)
294  uint_fast8_t tEnableLEDFeedback = DO_NOT_ENABLE_LED_FEEDBACK;
295  if (aEnableLEDFeedback) {
296  tEnableLEDFeedback = LED_FEEDBACK_ENABLED_FOR_RECEIVE;
297  }
298  setLEDFeedback(aFeedbackLEDPin, tEnableLEDFeedback);
299 #else
300  (void) aEnableLEDFeedback;
301  (void) aFeedbackLEDPin;
302 #endif
303 
304 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
305  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
306 #endif
307  start();
308 }
309 
313 void IRrecv::setReceivePin(uint_fast8_t aReceivePinNumber) {
314  irparams.IRReceivePin = aReceivePinNumber;
315 #if defined(__AVR__)
316 # if defined(__digitalPinToBit)
317  if (__builtin_constant_p(aReceivePinNumber)) {
318  irparams.IRReceivePinMask = 1UL << (__digitalPinToBit(aReceivePinNumber));
319  } else {
320  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
321  }
322 # else
323  irparams.IRReceivePinMask = digitalPinToBitMask(aReceivePinNumber); // requires 10 bytes PGM, even if not referenced (?because it is assembler code?)
324 # endif
325 # if defined(__digitalPinToPINReg)
326  /*
327  * This code is 54 bytes smaller, if aReceivePinNumber is a constant :-), but 38 byte longer if it is not constant (,which is not likely).
328  */
329  if (__builtin_constant_p(aReceivePinNumber)) {
330  irparams.IRReceivePinPortInputRegister = __digitalPinToPINReg(aReceivePinNumber);
331  } else {
332  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
333  }
334 # else
335  irparams.IRReceivePinPortInputRegister = portInputRegister(digitalPinToPort(aReceivePinNumber)); // requires 44 bytes PGM, even if not referenced
336 # endif
337 #endif
338  // Set pin mode once. pinModeFast makes no difference if used, but saves 224 if not referenced :-(
339  pinModeFast(aReceivePinNumber, INPUT); // Seems to be at least required by ESP32
340 }
341 
342 #if !defined(IR_REMOTE_DISABLE_RECEIVE_COMPLETE_CALLBACK)
343 
346 void IRrecv::registerReceiveCompleteCallback(void (*aReceiveCompleteCallbackFunction)(void)) {
347  irparams.ReceiveCompleteCallbackFunction = aReceiveCompleteCallbackFunction;
348 }
349 #endif
350 
357 
358  // Setup for cyclic 50 us interrupt
359  timerConfigForReceive(); // no interrupts enabled here!
360 
361  // Initialize state machine state
362  resume();
363 
364  // Timer interrupt is enabled after state machine reset
365  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
366 #ifdef _IR_MEASURE_TIMING
367  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
368 #endif
369 }
370 
371 /*
372  * Do not resume() reading of IR data
373  */
375  // Setup for cyclic 50 us interrupt
376  timerConfigForReceive(); // no interrupts enabled here!
377  // Timer interrupt is enabled after state machine reset
378  timerEnableReceiveInterrupt(); // Enables the receive sample timer interrupt which consumes a small amount of CPU every 50 us.
379 #ifdef _IR_MEASURE_TIMING
380  pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT);
381 #endif
382 }
387  start();
388 }
389 
395 void IRrecv::start(uint32_t aMicrosecondsToAddToGapCounter) {
396  irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
397  start();
398 }
399 void IRrecv::restartTimer(uint32_t aMicrosecondsToAddToGapCounter) {
400  irparams.TickCounterForISR += aMicrosecondsToAddToGapCounter / MICROS_PER_TICK;
401  restartTimer();
402 }
403 void IRrecv::startWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
404  irparams.TickCounterForISR += aTicksToAddToGapCounter;
405  start();
406 }
407 void IRrecv::restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter) {
408  irparams.TickCounterForISR += aTicksToAddToGapCounter;
409  restartTimer();
410 }
411 
412 void IRrecv::addTicksToInternalTickCounter(uint16_t aTicksToAddToInternalTickCounter) {
413  irparams.TickCounterForISR += aTicksToAddToInternalTickCounter;
414 }
415 
416 void IRrecv::addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter) {
417  irparams.TickCounterForISR += aMicrosecondsToAddToInternalTickCounter / MICROS_PER_TICK;
418 }
423 #if defined(SEND_PWM_BY_TIMER) && !defined(SEND_PWM_DOES_NOT_USE_RECEIVE_TIMER)
424  start();
425 #endif
426 }
427 
431 void IRrecv::stop() {
433 }
434 
437 }
442  stop();
443 }
447 void IRrecv::end() {
448  stop();
449 }
450 
457 }
458 
464  // This check allows to call resume at arbitrary places or more than once
467  }
468 }
469 
475 
476  if (irparams.OverflowFlag) {
478 #if defined(LOCAL_DEBUG)
479  Serial.print(F("Overflow happened, try to increase the \"RAW_BUFFER_LENGTH\" value of "));
480  Serial.print(RAW_BUFFER_LENGTH);
481  Serial.println(F(" with #define RAW_BUFFER_LENGTH=<biggerValue>"));
482 #endif
483 
484  } else {
486  // save last protocol, command and address for repeat handling (where they are compared or copied back :-))
487  lastDecodedProtocol = decodedIRData.protocol; // repeat patterns can be equal between protocols (e.g. NEC, Samsung and LG), so we must keep the original one
490 
491  }
497 }
498 
504 }
505 
511  return NULL;
512  }
513  if (decode()) {
514  return &decodedIRData;
515  } else {
516  return NULL;
517  }
518 }
519 
528  return false;
529  }
530 
531  initDecodedIRData(); // sets IRDATA_FLAGS_WAS_OVERFLOW
532 
534  /*
535  * Set OverflowFlag flag and return true here, to let the loop call resume or print raw data.
536  */
538  return true;
539  }
540 
541 #if defined(DECODE_NEC) || defined(DECODE_ONKYO)
542  IR_TRACE_PRINTLN(F("Attempting NEC/Onkyo decode"));
543  if (decodeNEC()) {
544  return true;
545  }
546 #endif
547 
548 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
549  IR_TRACE_PRINTLN(F("Attempting Panasonic/Kaseikyo decode"));
550  if (decodeKaseikyo()) {
551  return true;
552  }
553 #endif
554 
555 #if defined(DECODE_DENON)
556  IR_TRACE_PRINTLN(F("Attempting Denon/Sharp decode"));
557  if (decodeDenon()) {
558  return true;
559  }
560 #endif
561 
562 #if defined(DECODE_SONY)
563  IR_TRACE_PRINTLN(F("Attempting Sony decode"));
564  if (decodeSony()) {
565  return true;
566  }
567 #endif
568 
569 #if defined(DECODE_RC5)
570  IR_TRACE_PRINTLN(F("Attempting RC5 decode"));
571  if (decodeRC5()) {
572  return true;
573  }
574 #endif
575 
576 #if defined(DECODE_RC6)
577  IR_TRACE_PRINTLN(F("Attempting RC6 decode"));
578  if (decodeRC6()) {
579  return true;
580  }
581 #endif
582 
583 #if defined(DECODE_LG)
584  IR_TRACE_PRINTLN(F("Attempting LG decode"));
585  if (decodeLG()) {
586  return true;
587  }
588 #endif
589 
590 #if defined(DECODE_JVC)
591  IR_TRACE_PRINTLN(F("Attempting JVC decode"));
592  if (decodeJVC()) {
593  return true;
594  }
595 #endif
596 
597 #if defined(DECODE_SAMSUNG)
598  IR_TRACE_PRINTLN(F("Attempting Samsung decode"));
599  if (decodeSamsung()) {
600  return true;
601  }
602 #endif
603  /*
604  * Start of the exotic protocols
605  */
606 
607 #if defined(DECODE_BEO)
608  IR_TRACE_PRINTLN(F("Attempting Bang & Olufsen decode"));
609  if (decodeBangOlufsen()) {
610  return true;
611  }
612 #endif
613 
614 #if defined(DECODE_FAST)
615  IR_TRACE_PRINTLN(F("Attempting FAST decode"));
616  if (decodeFAST()) {
617  return true;
618  }
619 #endif
620 
621 #if defined(DECODE_WHYNTER)
622  IR_TRACE_PRINTLN(F("Attempting Whynter decode"));
623  if (decodeWhynter()) {
624  return true;
625  }
626 #endif
627 
628 #if defined(DECODE_LEGO_PF)
629  IR_TRACE_PRINTLN(F("Attempting Lego Power Functions"));
630  if (decodeLegoPowerFunctions()) {
631  return true;
632  }
633 #endif
634 
635 #if defined(DECODE_BOSEWAVE)
636  IR_TRACE_PRINTLN(F("Attempting Bosewave decode"));
637  if (decodeBoseWave()) {
638  return true;
639  }
640 #endif
641 
642 #if defined(DECODE_MAGIQUEST)
643  IR_TRACE_PRINTLN(F("Attempting MagiQuest decode"));
644  if (decodeMagiQuest()) {
645  return true;
646  }
647 #endif
648 
649  /*
650  * Try the universal decoder for pulse distance protocols
651  */
652 #if defined(DECODE_DISTANCE_WIDTH)
653  IR_TRACE_PRINTLN(F("Attempting universal Distance Width decode"));
654  if (decodeDistanceWidth()) {
655  return true;
656  }
657 #endif
658 
659  /*
660  * Last resort is the universal hash decode which always return true
661  */
662 #if defined(DECODE_HASH)
663  IR_TRACE_PRINTLN(F("Hash decode"));
664  // decodeHash returns a hash on any input.
665  // Thus, it needs to be last in the list.
666  // If you add any decodes, add them before this.
667  if (decodeHash()) {
668  return true;
669  }
670 #endif
671 
672  /*
673  * Return true here, to let the loop decide to call resume or to print raw data.
674  */
675  return true;
676 }
677 
678 /**********************************************************************************************************************
679  * Common decode functions
680  **********************************************************************************************************************/
702 bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
703  uint16_t aOneSpaceMicros, uint16_t aZeroMarkMicros, bool aMSBfirst) {
704 
705  auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
706 
707  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we check aOneSpaceMicros -> pulse distance protocol
708 
709  IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
710  IRRawDataType tMask = 1UL; // Mask is only used for LSB first
711 
712  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
713  // get one mark and space pair
714  unsigned int tMarkTicks;
715  unsigned int tSpaceTicks;
716  bool tBitValue;
717 
718  if (isPulseDistanceProtocol) {
719  /*
720  * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
721  * !!!We only check variable length space indicating a 1 or 0!!!
722  */
723  tRawBufPointer++;
724  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
725  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
726 
727  } else {
728  /*
729  * PULSE_WIDTH here.
730  * !!!We only check variable length mark indicating a 1 or 0!!!
731  */
732  tMarkTicks = *tRawBufPointer++;
733  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
734  tRawBufPointer++;
735  }
736 
737  if (aMSBfirst) {
738  tDecodedData <<= 1;
739  }
740 
741  if (tBitValue) {
742  // It's a 1 -> set the bit
743  if (aMSBfirst) {
744  tDecodedData |= 1;
745  } else {
746  tDecodedData |= tMask;
747  }
748  IR_TRACE_PRINTLN(F("=> 1"));
749  } else {
750  // do not set the bit
751  IR_TRACE_PRINTLN(F("=> 0"));
752  }
753  tMask <<= 1;
754  }
755  decodedIRData.decodedRawData = tDecodedData;
756  return true;
757 }
758 
759 /*
760  * Old deprecated version with 7 parameters and unused aZeroSpaceMicros parameter
761  */
762 bool IRrecv::decodePulseDistanceWidthData(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
763  uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
764 
765  (void) aZeroSpaceMicros;
766  auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
767  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
768 
769  IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
770  IRRawDataType tMask = 1UL; // Mask is only used for LSB first
771 
772  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
773  // get one mark and space pair
774  unsigned int tMarkTicks;
775  unsigned int tSpaceTicks;
776  bool tBitValue;
777 
778  if (isPulseDistanceProtocol) {
779  /*
780  * Pulse distance here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration.
781  */
782 
783  (void) aZeroSpaceMicros;
784  tRawBufPointer++;
785  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
786  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
787  } else {
788  /*
789  * Pulse width here, it is not required to check (constant) space duration and zero mark duration.
790  */
791  tMarkTicks = *tRawBufPointer++;
792  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
793  tRawBufPointer++;
794  }
795 
796  if (aMSBfirst) {
797  tDecodedData <<= 1;
798  }
799 
800  if (tBitValue) {
801  // It's a 1 -> set the bit
802  if (aMSBfirst) {
803  tDecodedData |= 1;
804  } else {
805  tDecodedData |= tMask;
806  }
807  IR_TRACE_PRINTLN(F("=> 1"));
808  } else {
809  // do not set the bit
810  IR_TRACE_PRINTLN(F("=> 0"));
811  }
812  tMask <<= 1;
813  }
814  decodedIRData.decodedRawData = tDecodedData;
815  return true;
816 }
817 
818 /*
819  * Check for additional required characteristics of timing like length of mark for a constant mark protocol,
820  * where space length determines the bit value. Requires up to 194 additional bytes of program memory.
821  * Only sensible for development or very exotic requirements.
822  * @param aZeroMarkMicros For strict checks
823  * @param aZeroSpaceMicros For strict checks
824  *
825  * Not used yet
826  */
827 bool IRrecv::decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros,
828  uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst) {
829 
830  auto *tRawBufPointer = &decodedIRData.rawDataPtr->rawbuf[aStartOffset];
831 
832  bool isPulseDistanceProtocol = (aOneMarkMicros == aZeroMarkMicros); // If true, we have a constant mark -> pulse distance protocol
833 
834  IRRawDataType tDecodedData = 0; // For MSB first tDecodedData is shifted left each loop
835  IRRawDataType tMask = 1UL; // Mask is only used for LSB first
836 
837  for (uint_fast8_t i = aNumberOfBits; i > 0; i--) {
838  // get one mark and space pair
839  unsigned int tMarkTicks;
840  unsigned int tSpaceTicks;
841  bool tBitValue;
842 
843  if (isPulseDistanceProtocol) {
844  /*
845  * PULSE_DISTANCE here, it is not required to check constant mark duration (aOneMarkMicros) and zero space duration.
846  */
847  tMarkTicks = *tRawBufPointer++;
848  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
849  tBitValue = matchSpace(tSpaceTicks, aOneSpaceMicros); // Check for variable length space indicating a 1 or 0
850 
851  // Check for constant length mark
852  if (!matchMark(tMarkTicks, aOneMarkMicros)) {
853 #if defined(LOCAL_DEBUG)
854  Serial.print(F("Mark="));
855  Serial.print(tMarkTicks * MICROS_PER_TICK);
856  Serial.print(F(" is not "));
857  Serial.print(aOneMarkMicros);
858  Serial.print(F(". Index="));
859  Serial.print(aNumberOfBits - i);
860  Serial.print(' ');
861 #endif
862  return false;
863  }
864 
865  } else {
866  /*
867  * PULSE_DISTANCE -including PULSE_DISTANCE_WIDTH- here.
868  * !!!We only check variable length mark indicating a 1 or 0!!!
869  * It is not required to check space duration and zero mark duration.
870  */
871  tMarkTicks = *tRawBufPointer++;
872  tBitValue = matchMark(tMarkTicks, aOneMarkMicros); // Check for variable length mark indicating a 1 or 0
873  tSpaceTicks = *tRawBufPointer++; // maybe buffer overflow for last bit, but we do not evaluate this value :-)
874  }
875 
876  if (aMSBfirst) {
877  tDecodedData <<= 1;
878  }
879 
880  if (tBitValue) {
881  // It's a 1 -> set the bit
882  if (aMSBfirst) {
883  tDecodedData |= 1;
884  } else {
885  tDecodedData |= tMask;
886  }
887  IR_TRACE_PRINTLN(F("=> 1"));
888  } else {
889  /*
890  * Additionally check length of tSpaceTicks parameter for PULSE_DISTANCE or tMarkTicks for PULSE_WIDTH
891  * which determine a zero
892  */
893  if (isPulseDistanceProtocol) {
894  if (!matchSpace(tSpaceTicks, aZeroSpaceMicros)) {
895 #if defined(LOCAL_DEBUG)
896  Serial.print(F("Space="));
897  Serial.print(tSpaceTicks * MICROS_PER_TICK);
898  Serial.print(F(" is not "));
899  Serial.print(aOneSpaceMicros);
900  Serial.print(F(" or "));
901  Serial.print(aZeroSpaceMicros);
902  Serial.print(F(". Index="));
903  Serial.print(aNumberOfBits - i);
904  Serial.print(' ');
905 #endif
906  return false;
907  }
908  } else {
909  if (!matchMark(tMarkTicks, aZeroMarkMicros)) {
910 #if defined(LOCAL_DEBUG)
911  Serial.print(F("Mark="));
912  Serial.print(tMarkTicks * MICROS_PER_TICK);
913  Serial.print(F(" is not "));
914  Serial.print(aOneMarkMicros);
915  Serial.print(F(" or "));
916  Serial.print(aZeroMarkMicros);
917  Serial.print(F(". Index="));
918  Serial.print(aNumberOfBits - i);
919  Serial.print(' ');
920 #endif
921  return false;
922  }
923  }
924  // do not set the bit
925  IR_TRACE_PRINTLN(F("=> 0"));
926  }
927  // If we have no stop bit, assume that last space, which is not recorded, is correct, since we can not check it
928  if (aZeroSpaceMicros == aOneSpaceMicros
929  && tRawBufPointer < &decodedIRData.rawDataPtr->rawbuf[decodedIRData.rawDataPtr->rawlen]) {
930  // Check for constant length space (of pulse width protocol) here
931  if (!matchSpace(tSpaceTicks, aOneSpaceMicros)) {
932 #if defined(LOCAL_DEBUG)
933  Serial.print(F("Space="));
934  Serial.print(tSpaceTicks * MICROS_PER_TICK);
935  Serial.print(F(" is not "));
936  Serial.print(aOneSpaceMicros);
937  Serial.print(F(". Index="));
938  Serial.print(aNumberOfBits - i);
939  Serial.print(' ');
940 #endif
941  return false;
942  }
943  }
944  tMask <<= 1;
945  }
946  decodedIRData.decodedRawData = tDecodedData;
947  return true;
948 }
949 
954 bool IRrecv::decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits,
955  IRRawlenType aStartOffset) {
956 
957  return decodePulseDistanceWidthData(aNumberOfBits, aStartOffset, aProtocolConstants->DistanceWidthTimingInfo.OneMarkMicros,
958  aProtocolConstants->DistanceWidthTimingInfo.OneSpaceMicros, aProtocolConstants->DistanceWidthTimingInfo.ZeroMarkMicros,
959  aProtocolConstants->Flags);
960 }
961 
962 /*
963  * Static variables for the getBiphaselevel function
964  */
965 uint_fast8_t sBiphaseDecodeRawbuffOffset; // Index into raw timing array
966 uint16_t sBiphaseCurrentTimingIntervals; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[sBiphaseDecodeRawbuffOffset] timing.
967 uint_fast8_t sBiphaseUsedTimingIntervals; // Number of already used intervals of sCurrentTimingIntervals.
969 
970 void IRrecv::initBiphaselevel(uint_fast8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit) {
971  sBiphaseDecodeRawbuffOffset = aRCDecodeRawbuffOffset;
972  sBiphaseTimeUnit = aBiphaseTimeUnit;
974 }
975 
992 uint_fast8_t IRrecv::getBiphaselevel() {
993  uint_fast8_t tLevelOfCurrentInterval; // 0 (SPACE) or 1 (MARK)
994 
996  return SPACE; // After end of recorded buffer, assume space.
997  }
998 
999  tLevelOfCurrentInterval = (sBiphaseDecodeRawbuffOffset) & 1; // on odd rawbuf offsets we have mark timings
1000 
1001  /*
1002  * Setup data if sUsedTimingIntervals is 0
1003  */
1004  if (sBiphaseUsedTimingIntervals == 0) {
1005  uint16_t tCurrentTimingWith = decodedIRData.rawDataPtr->rawbuf[sBiphaseDecodeRawbuffOffset];
1006  uint16_t tMarkExcessCorrection = (tLevelOfCurrentInterval == MARK) ? MARK_EXCESS_MICROS : -MARK_EXCESS_MICROS;
1007 
1008  if (matchTicks(tCurrentTimingWith, sBiphaseTimeUnit + tMarkExcessCorrection)) {
1010  } else if (matchTicks(tCurrentTimingWith, (2 * sBiphaseTimeUnit) + tMarkExcessCorrection)) {
1012  } else if (matchTicks(tCurrentTimingWith, (3 * sBiphaseTimeUnit) + tMarkExcessCorrection)) {
1014  } else {
1015  return -1;
1016  }
1017  }
1018 
1019 // We use another interval from tCurrentTimingIntervals
1021 
1022 // keep track of current timing offset
1024  // we have used all intervals of current timing, switch to next timing value
1027  }
1028 
1029  IR_TRACE_PRINTLN(tLevelOfCurrentInterval);
1030 
1031  return tLevelOfCurrentInterval;
1032 }
1033 
1034 /**********************************************************************************************************************
1035  * Internal Hash decode function
1036  **********************************************************************************************************************/
1037 #define FNV_PRIME_32 16777619
1038 #define FNV_BASIS_32 2166136261
1040 
1045 uint_fast8_t IRrecv::compare(uint16_t oldval, uint16_t newval) {
1046  if (newval * 10 < oldval * 8) {
1047  return 0;
1048  }
1049  if (oldval * 10 < newval * 8) {
1050  return 2;
1051  }
1052  return 1;
1053 }
1054 
1073  unsigned long hash = FNV_BASIS_32; // the result is the same no matter if we use a long or unsigned long variable
1074 
1075 // Require at least 6 samples to prevent triggering on noise
1076  if (decodedIRData.rawlen < 6) {
1077  IR_DEBUG_PRINT(F("HASH: "));
1078  IR_DEBUG_PRINT(F("Data length="));
1080  IR_DEBUG_PRINTLN(F(" is less than 6"));
1081  return false;
1082  }
1083  for (IRRawlenType i = 1; (i + 2) < decodedIRData.rawlen; i++) {
1084  // Compare mark with mark and space with space
1085  uint_fast8_t value = compare(decodedIRData.rawDataPtr->rawbuf[i], decodedIRData.rawDataPtr->rawbuf[i + 2]);
1086  // Add value into the hash
1087  hash = (hash * FNV_PRIME_32) ^ value;
1088  }
1089 
1093 
1094  return true;
1095 }
1096 
1098  unsigned long hash = FNV_BASIS_32;
1099 
1100 // Require at least 6 samples to prevent triggering on noise
1101  if (aResults->rawlen < 6) {
1102  return false;
1103  }
1104 
1105  for (uint8_t i = 3; i < aResults->rawlen; i++) {
1106  uint_fast8_t value = compare(aResults->rawbuf[i - 2], aResults->rawbuf[i]);
1107  // Add value into the hash
1108  hash = (hash * FNV_PRIME_32) ^ value;
1109  }
1110 
1111  aResults->value = hash;
1112  aResults->bits = 32;
1113  aResults->decode_type = UNKNOWN;
1115 
1116  return true;
1117 }
1118 
1119 /**********************************************************************************************************************
1120  * Match functions
1121  **********************************************************************************************************************/
1122 
1123 /*
1124  * returns true if values do match
1125  */
1127 // Check header "mark" and "space"
1129 #if defined(LOCAL_TRACE)
1130  Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
1131  Serial.println(F(": Header mark length is wrong"));
1132 #endif
1133  return false;
1134  }
1136 #if defined(LOCAL_TRACE)
1137  Serial.print(::getProtocolString(aProtocolConstants->ProtocolIndex));
1138  Serial.println(F(": Header space length is wrong"));
1139 #endif
1140  return false;
1141  }
1142  return true;
1143 }
1144 
1145 /*
1146  * 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.
1147  * And if really required, it can be enabled here, or done manually in user program.
1148  * And we have still no RC6 toggle bit check for detecting a second press on the same button.
1149  */
1150 void IRrecv::checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks) {
1151  if (decodedIRData.initialGapTicks < aMaximumRepeatSpaceTicks
1152 #if defined(ENABLE_FULL_REPEAT_CHECK)
1153  && decodedIRData.address == lastDecodedAddress && decodedIRData.command == lastDecodedCommand /* requires around 85 bytes program space */
1154 #endif
1155  ) {
1157  }
1158 }
1159 
1165 bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1166 #if defined(LOCAL_TRACE)
1167  Serial.print(F("Testing: "));
1168  Serial.print(TICKS_LOW(aMatchValueMicros), DEC);
1169  Serial.print(F(" <= "));
1170  Serial.print(aMeasuredTicks, DEC);
1171  Serial.print(F(" <= "));
1172  Serial.print(TICKS_HIGH(aMatchValueMicros), DEC);
1173 #endif
1174  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros)) && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros)));
1175 #if defined(LOCAL_TRACE)
1176  if (passed) {
1177  Serial.println(F(" => passed"));
1178  } else {
1179  Serial.println(F(" => FAILED"));
1180  }
1181 #endif
1182  return passed;
1183 }
1184 
1185 bool MATCH(uint16_t measured_ticks, uint16_t desired_us) {
1186  return matchTicks(measured_ticks, desired_us);
1187 }
1188 
1193 bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1194 #if defined(LOCAL_TRACE)
1195  Serial.print(F("Testing mark (actual vs desired): "));
1196  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1197  Serial.print(F("us vs "));
1198  Serial.print(aMatchValueMicros, DEC);
1199  Serial.print(F("us: "));
1200  Serial.print(TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1201  Serial.print(F(" <= "));
1202  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1203  Serial.print(F(" <= "));
1204  Serial.print(TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1205 #endif
1206  // compensate for marks exceeded by demodulator hardware
1207  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros + MARK_EXCESS_MICROS))
1208  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros + MARK_EXCESS_MICROS)));
1209 #if defined(LOCAL_TRACE)
1210  if (passed) {
1211  Serial.println(F(" => passed"));
1212  } else {
1213  Serial.println(F(" => FAILED"));
1214  }
1215 #endif
1216  return passed;
1217 }
1218 
1219 bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us) {
1220  return matchMark(measured_ticks, desired_us);
1221 }
1222 
1227 bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros) {
1228 #if defined(LOCAL_TRACE)
1229  Serial.print(F("Testing space (actual vs desired): "));
1230  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1231  Serial.print(F("us vs "));
1232  Serial.print(aMatchValueMicros, DEC);
1233  Serial.print(F("us: "));
1234  Serial.print(TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1235  Serial.print(F(" <= "));
1236  Serial.print(aMeasuredTicks * MICROS_PER_TICK, DEC);
1237  Serial.print(F(" <= "));
1238  Serial.print(TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS) * MICROS_PER_TICK, DEC);
1239 #endif
1240  // compensate for spaces shortened by demodulator hardware
1241  bool passed = ((aMeasuredTicks >= TICKS_LOW(aMatchValueMicros - MARK_EXCESS_MICROS))
1242  && (aMeasuredTicks <= TICKS_HIGH(aMatchValueMicros - MARK_EXCESS_MICROS)));
1243 #if defined(LOCAL_TRACE)
1244  if (passed) {
1245  Serial.println(F(" => passed"));
1246  } else {
1247  Serial.println(F(" => FAILED"));
1248  }
1249 #endif
1250  return passed;
1251 }
1252 
1253 bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us) {
1254  return matchSpace(measured_ticks, desired_us);
1255 }
1256 
1261  return MARK_EXCESS_MICROS;
1262 }
1263 
1264 /*
1265  * Check if protocol is not detected and detected space between two transmissions
1266  * is smaller than known value for protocols (Sony with around 24 ms)
1267  * @return true, if CheckForRecordGapsMicros() has printed a message, i.e. gap < 15ms (RECORD_GAP_MICROS_WARNING_THRESHOLD)
1268  */
1269 bool IRrecv::checkForRecordGapsMicros(Print *aSerial) {
1270  /*
1271  * Check if protocol is not detected and detected space between two transmissions
1272  * is smaller than known value for protocols (Sony with around 24 ms)
1273  */
1276  aSerial->println();
1277  aSerial->print(F("Space of "));
1278  aSerial->print(decodedIRData.initialGapTicks * MICROS_PER_TICK);
1279  aSerial->print(F(" us between two detected transmission is smaller than the minimal gap of "));
1280  aSerial->print(RECORD_GAP_MICROS_WARNING_THRESHOLD);
1281  aSerial->println(F(" us known for implemented protocols like NEC, Sony, RC% etc.."));
1282  aSerial->println(F("But it can be OK for some yet unsupported protocols, and especially for repeats."));
1283  aSerial->println(F("If you get unexpected results, try to increase the RECORD_GAP_MICROS in IRremote.h."));
1284  aSerial->println();
1285  return true;
1286  }
1287  return false;
1288 }
1289 
1290 /**********************************************************************************************************************
1291  * Print functions
1292  * Since a library should not allocate the "Serial" object, all functions require a pointer to a Print object.
1293  **********************************************************************************************************************/
1294 void IRrecv::printActiveIRProtocols(Print *aSerial) {
1295 // call no class function with same name
1296  ::printActiveIRProtocols(aSerial);
1297 }
1298 void printActiveIRProtocols(Print *aSerial) {
1299 #if defined(DECODE_ONKYO)
1300  aSerial->print(F("Onkyo, "));
1301 #elif defined(DECODE_NEC)
1302  aSerial->print(F("NEC/NEC2/Onkyo/Apple, "));
1303 #endif
1304 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
1305  aSerial->print(F("Panasonic/Kaseikyo, "));
1306 #endif
1307 #if defined(DECODE_DENON)
1308  aSerial->print(F("Denon/Sharp, "));
1309 #endif
1310 #if defined(DECODE_SONY)
1311  aSerial->print(F("Sony, "));
1312 #endif
1313 #if defined(DECODE_RC5)
1314  aSerial->print(F("RC5, "));
1315 #endif
1316 #if defined(DECODE_RC6)
1317  aSerial->print(F("RC6, "));
1318 #endif
1319 #if defined(DECODE_LG)
1320  aSerial->print(F("LG, "));
1321 #endif
1322 #if defined(DECODE_JVC)
1323  aSerial->print(F("JVC, "));
1324 #endif
1325 #if defined(DECODE_SAMSUNG)
1326  aSerial->print(F("Samsung, "));
1327 #endif
1328  /*
1329  * Start of the exotic protocols
1330  */
1331 #if defined(DECODE_BEO)
1332  aSerial->print(F("Bang & Olufsen, "));
1333 #endif
1334 #if defined(DECODE_FAST)
1335  aSerial->print(F("FAST, "));
1336 #endif
1337 #if defined(DECODE_WHYNTER)
1338  aSerial->print(F("Whynter, "));
1339 #endif
1340 #if defined(DECODE_LEGO_PF)
1341  aSerial->print(F("Lego Power Functions, "));
1342 #endif
1343 #if defined(DECODE_BOSEWAVE)
1344  aSerial->print(F("Bosewave, "));
1345 #endif
1346 #if defined(DECODE_MAGIQUEST)
1347  aSerial->print(F("MagiQuest, "));
1348 #endif
1349 #if defined(DECODE_DISTANCE_WIDTH)
1350  aSerial->print(F("Universal Pulse Distance Width, "));
1351 #endif
1352 #if defined(DECODE_HASH)
1353  aSerial->print(F("Hash "));
1354 #endif
1355 #if defined(NO_DECODER) // for sending raw only
1356  (void)aSerial; // to avoid compiler warnings
1357 #endif
1358 }
1359 
1370 bool IRrecv::printIRResultShort(Print *aSerial, bool aPrintRepeatGap, bool aCheckForRecordGapsMicros) {
1371 // call no class function with same name
1372  ::printIRResultShort(aSerial, &decodedIRData, aPrintRepeatGap);
1373  if (aCheckForRecordGapsMicros && decodedIRData.protocol != UNKNOWN) {
1374  return checkForRecordGapsMicros(aSerial);
1375  }
1376  return false;
1377 }
1378 
1379 void IRrecv::printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo) {
1380  aSerial->print(aDistanceWidthTimingInfo->HeaderMarkMicros);
1381  aSerial->print(F(", "));
1382  aSerial->print(aDistanceWidthTimingInfo->HeaderSpaceMicros);
1383  aSerial->print(F(", "));
1384  aSerial->print(aDistanceWidthTimingInfo->OneMarkMicros);
1385  aSerial->print(F(", "));
1386  aSerial->print(aDistanceWidthTimingInfo->OneSpaceMicros);
1387  aSerial->print(F(", "));
1388  aSerial->print(aDistanceWidthTimingInfo->ZeroMarkMicros);
1389  aSerial->print(F(", "));
1390  aSerial->print(aDistanceWidthTimingInfo->ZeroSpaceMicros);
1391 }
1392 
1393 /*
1394  * Get maximum of mark ticks in rawDataPtr.
1395  * Skip leading start and trailing stop bit.
1396  */
1398  uint8_t tMaximumTick = 0;
1399  for (IRRawlenType i = 3; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1400  auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
1401  if (tMaximumTick < tTick) {
1402  tMaximumTick = tTick;
1403  }
1404  }
1405  return tMaximumTick;
1406 }
1408  uint8_t tMaximumTick = 0;
1409  for (IRRawlenType i = 4; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1410  auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
1411  if (tMaximumTick < tTick) {
1412  tMaximumTick = tTick;
1413  }
1414  }
1415  return tMaximumTick;
1416 }
1417 
1418 /*
1419  * The optimizing compiler internally generates this function, if getMaximumMarkTicksFromRawData() and getMaximumSpaceTicksFromRawData() is used.
1420  */
1421 uint8_t IRrecv::getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark) {
1422  uint8_t tMaximumTick = 0;
1423  IRRawlenType i;
1424  if (aSearchSpaceInsteadOfMark) {
1425  i = 4;
1426  } else {
1427  i = 3;
1428  }
1429  for (; i < decodedIRData.rawlen - 2; i += 2) { // Skip leading start and trailing stop bit.
1430  auto tTick = decodedIRData.rawDataPtr->rawbuf[i];
1431  if (tMaximumTick < tTick) {
1432  tMaximumTick = tTick;
1433  }
1434  }
1435  return tMaximumTick;
1436 }
1437 
1439  uint16_t tSumOfDurationTicks = 0;
1440 
1441  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
1442  tSumOfDurationTicks += decodedIRData.rawDataPtr->rawbuf[i];
1443  }
1444  return tSumOfDurationTicks * (uint32_t) MICROS_PER_TICK;
1445 }
1446 
1455 void IRrecv::printIRSendUsage(Print *aSerial) {
1459 #if defined(DECODE_DISTANCE_WIDTH)
1460  uint_fast8_t tNumberOfArrayData = 0;
1462 # if __INT_WIDTH__ < 32
1463  aSerial->print(F("Send on a 8 bit platform with: "));
1464  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 32) + 1;
1465  if(tNumberOfArrayData > 1) {
1466  aSerial->println();
1467  aSerial->print(F(" uint32_t tRawData[]={0x"));
1468 # else
1469  aSerial->print(F("Send on a 32 bit platform with: "));
1470  tNumberOfArrayData = ((decodedIRData.numberOfBits - 1) / 64) + 1;
1471  if(tNumberOfArrayData > 1) {
1472  aSerial->println();
1473  aSerial->print(F(" uint64_t tRawData[]={0x"));
1474 # endif
1475  for (uint_fast8_t i = 0; i < tNumberOfArrayData; ++i) {
1476 # if (__INT_WIDTH__ < 32)
1477  aSerial->print(decodedIRData.decodedRawDataArray[i], HEX);
1478 # else
1479  PrintULL::print(aSerial, decodedIRData.decodedRawDataArray[i], HEX);
1480 # endif
1481  if (i != tNumberOfArrayData - 1) {
1482  aSerial->print(F(", 0x"));
1483  }
1484  }
1485  aSerial->println(F("};"));
1486  aSerial->print(F(" "));
1487  }
1488  } else {
1489  aSerial->print(F("Send with: "));
1490  }
1491  aSerial->print(F("IrSender.send"));
1492 
1493 #else
1494  aSerial->print(F("Send with: IrSender.send"));
1495 #endif
1496 
1497 #if defined(DECODE_DISTANCE_WIDTH)
1499 #endif
1500  aSerial->print(getProtocolString());
1501  aSerial->print(F("(0x"));
1502 #if defined(DECODE_MAGIQUEST)
1503  if (decodedIRData.protocol == MAGIQUEST) {
1504 # if (__INT_WIDTH__ < 32)
1505  aSerial->print(decodedIRData.decodedRawData, HEX);
1506 # else
1507  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1508 # endif
1509  } else {
1510  aSerial->print(decodedIRData.address, HEX);
1511  }
1512 #else
1513  /*
1514  * New decoders have address and command
1515  */
1516  aSerial->print(decodedIRData.address, HEX);
1517 #endif
1518 
1519  aSerial->print(F(", 0x"));
1520  aSerial->print(decodedIRData.command, HEX);
1521  if (decodedIRData.protocol == SONY) {
1522  aSerial->print(F(", 2, "));
1523  aSerial->print(decodedIRData.numberOfBits);
1524  } else {
1525  aSerial->print(F(", <numberOfRepeats>"));
1526  }
1527 
1528 #if defined(DECODE_DISTANCE_WIDTH)
1529  } else {
1530  /*
1531  * Pulse distance or pulse width here
1532  */
1533  aSerial->print("PulseDistanceWidth");
1534  if(tNumberOfArrayData > 1) {
1535  aSerial->print("FromArray(38, ");
1536  } else {
1537  aSerial->print("(38, ");
1538  }
1539  printDistanceWidthTimingInfo(aSerial, &decodedIRData.DistanceWidthTimingInfo);
1540 
1541  if(tNumberOfArrayData > 1) {
1542  aSerial->print(F(", &tRawData[0], "));
1543  } else {
1544  aSerial->print(F(", 0x"));
1545 # if (__INT_WIDTH__ < 32)
1546  aSerial->print(decodedIRData.decodedRawData, HEX);
1547 # else
1548  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1549 # endif
1550  aSerial->print(F(", "));
1551  }
1552  aSerial->print(decodedIRData.numberOfBits);// aNumberOfBits
1553  aSerial->print(F(", PROTOCOL_IS_"));
1554 
1556  aSerial->print('M');
1557  } else {
1558  aSerial->print('L');
1559  }
1560  aSerial->print(F("SB_FIRST, <RepeatPeriodMillis>, <numberOfRepeats>"));
1561  }
1562 #endif
1563 #if defined(DECODE_PANASONIC) || defined(DECODE_KASEIKYO)
1565  aSerial->print(F(", 0x"));
1566  aSerial->print(decodedIRData.extra, HEX);
1567  }
1568 #endif
1569  aSerial->print(F(");"));
1570  aSerial->println();
1571  }
1572 }
1573 
1580 void IRrecv::printIRResultMinimal(Print *aSerial) {
1581  aSerial->print(F("P="));
1582  aSerial->print(decodedIRData.protocol);
1583  if (decodedIRData.protocol == UNKNOWN) {
1584 #if defined(DECODE_HASH)
1585  aSerial->print(F(" #=0x"));
1586 # if (__INT_WIDTH__ < 32)
1587  aSerial->print(decodedIRData.decodedRawData, HEX);
1588 # else
1589  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1590 # endif
1591 #endif
1592  aSerial->print(' ');
1593  aSerial->print((decodedIRData.rawlen + 1) / 2, DEC);
1594  aSerial->println(F(" bits received"));
1595  } else {
1596  /*
1597  * New decoders have address and command
1598  */
1599  aSerial->print(F(" A=0x"));
1600  aSerial->print(decodedIRData.address, HEX);
1601 
1602  aSerial->print(F(" C=0x"));
1603  aSerial->print(decodedIRData.command, HEX);
1604 
1605  aSerial->print(F(" Raw=0x"));
1606 #if (__INT_WIDTH__ < 32)
1607  aSerial->print(decodedIRData.decodedRawData, HEX);
1608 #else
1609  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1610 #endif
1611 
1613  aSerial->print(F(" R"));
1614  }
1615  }
1616 }
1617 
1624 void IRrecv::printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
1625 
1626 // Print Raw data
1627  aSerial->print(F("rawData["));
1628  aSerial->print(decodedIRData.rawlen, DEC);
1629  aSerial->println(F("]: "));
1630 
1631  /*
1632  * Print initial gap
1633  */
1634  aSerial->print(F(" -"));
1635  if (aOutputMicrosecondsInsteadOfTicks) {
1636  aSerial->println((uint32_t) decodedIRData.initialGapTicks * MICROS_PER_TICK, DEC);
1637  } else {
1638  aSerial->println(decodedIRData.initialGapTicks, DEC);
1639  }
1640 
1641 // Newline is printed every 8. value, if tCounterForNewline % 8 == 0
1642  uint_fast8_t tCounterForNewline = 6; // first newline is after the 2 values of the start bit
1643 
1644 // check if we have a protocol with no or 8 start bits
1645 #if defined(DECODE_DENON) || defined(DECODE_MAGIQUEST)
1646  if (
1647 # if defined(DECODE_DENON)
1649 # endif
1650 # if defined(DECODE_MAGIQUEST)
1652 # endif
1653  false) {
1654  tCounterForNewline = 0; // no or 8 start bits
1655  }
1656 #endif
1657 
1658  uint32_t tDuration;
1659  uint16_t tSumOfDurationTicks = 0;
1660  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
1661  auto tCurrentTicks = decodedIRData.rawDataPtr->rawbuf[i];
1662  if (aOutputMicrosecondsInsteadOfTicks) {
1663  tDuration = tCurrentTicks * MICROS_PER_TICK;
1664  } else {
1665  tDuration = tCurrentTicks;
1666  }
1667  tSumOfDurationTicks += tCurrentTicks; // compute length of protocol frame
1668 
1669  if (!(i & 1)) { // even
1670  aSerial->print('-');
1671  } else { // odd
1672  aSerial->print(F(" +"));
1673  }
1674 
1675  // padding only for big values
1676  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 1000) {
1677  aSerial->print(' ');
1678  }
1679  if (aOutputMicrosecondsInsteadOfTicks && tDuration < 100) {
1680  aSerial->print(' ');
1681  }
1682  if (tDuration < 10) {
1683  aSerial->print(' ');
1684  }
1685  aSerial->print(tDuration, DEC);
1686 
1687  if ((i & 1) && (i + 1) < decodedIRData.rawlen) {
1688  aSerial->print(','); //',' not required for last one
1689  }
1690 
1691  tCounterForNewline++;
1692  if ((tCounterForNewline % 8) == 0) {
1693  aSerial->println();
1694  }
1695  }
1696 
1697  aSerial->println();
1698  aSerial->print("Sum: ");
1699  if (aOutputMicrosecondsInsteadOfTicks) {
1700  aSerial->println((uint32_t) tSumOfDurationTicks * MICROS_PER_TICK, DEC);
1701  } else {
1702  aSerial->println(tSumOfDurationTicks, DEC);
1703  }
1704 }
1705 
1717 void IRrecv::compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks) {
1718 // Start declaration
1719  if (aOutputMicrosecondsInsteadOfTicks) {
1720  aSerial->print(F("uint16_t rawData[")); // variable type, array name
1721  } else {
1722  aSerial->print(F("uint8_t rawTicks[")); // variable type, array name
1723  }
1724 
1725  aSerial->print(decodedIRData.rawlen - 1, DEC); // array size
1726  aSerial->print(F("] = {")); // Start declaration
1727 
1728 // Dump data
1729  for (IRRawlenType i = 1; i < decodedIRData.rawlen; i++) {
1730  uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
1731 
1732  if (i & 1) {
1733  // Mark
1734  tDuration -= MARK_EXCESS_MICROS;
1735  } else {
1736  tDuration += MARK_EXCESS_MICROS;
1737  }
1738 
1739  if (aOutputMicrosecondsInsteadOfTicks) {
1740  aSerial->print(tDuration);
1741  } else {
1742  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
1743  /*
1744  * Clip to 8 bit value
1745  */
1746  tTicks = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks;
1747  aSerial->print(tTicks);
1748  }
1749  if (i + 1 < decodedIRData.rawlen) aSerial->print(','); // ',' not required on last one
1750  if (!(i & 1)) aSerial->print(' ');
1751  }
1752 
1753 // End declaration
1754  aSerial->print(F("};")); //
1755 
1756 // Comment
1757  aSerial->print(F(" // "));
1758  printIRResultShort(aSerial);
1759 
1760 // Newline
1761  aSerial->println("");
1762 }
1763 
1774 
1775 // Store data, skip leading space#
1776  IRRawlenType i;
1777  for (i = 1; i < decodedIRData.rawlen; i++) {
1778  uint32_t tDuration = decodedIRData.rawDataPtr->rawbuf[i] * MICROS_PER_TICK;
1779  if (i & 1) {
1780  // Mark
1781  tDuration -= MARK_EXCESS_MICROS;
1782  } else {
1783  tDuration += MARK_EXCESS_MICROS;
1784  }
1785 
1786  unsigned int tTicks = (tDuration + (MICROS_PER_TICK / 2)) / MICROS_PER_TICK;
1787  *aArrayPtr = (tTicks > UINT8_MAX) ? UINT8_MAX : tTicks; // we store it in an 8 bit array
1788  aArrayPtr++;
1789  }
1790 }
1791 
1797 // Now dump "known" codes
1798  if (decodedIRData.protocol != UNKNOWN) {
1799 
1800  /*
1801  * New decoders have address and command
1802  */
1803  aSerial->print(F("uint16_t"));
1804  aSerial->print(F(" address = 0x"));
1805  aSerial->print(decodedIRData.address, HEX);
1806  aSerial->println(';');
1807 
1808  aSerial->print(F("uint16_t"));
1809  aSerial->print(F(" command = 0x"));
1810  aSerial->print(decodedIRData.command, HEX);
1811  aSerial->println(';');
1812 
1813  // All protocols have raw data
1814 #if __INT_WIDTH__ < 32
1815  aSerial->print(F("uint32_t rawData = 0x"));
1816 #else
1817  aSerial->print(F("uint64_t rawData = 0x"));
1818 #endif
1819 #if (__INT_WIDTH__ < 32)
1820  aSerial->print(decodedIRData.decodedRawData, HEX);
1821 #else
1822  PrintULL::print(aSerial, decodedIRData.decodedRawData, HEX);
1823 #endif
1824  aSerial->println(';');
1825  aSerial->println();
1826  }
1827 }
1828 
1829 #if defined(__AVR__)
1830 const __FlashStringHelper* IRrecv::getProtocolString() {
1831 // call no class function with same name
1833 }
1834 #else
1836  // call no class function with same name
1838 }
1839 #endif
1840 
1841 /**********************************************************************************************************************
1842  * The OLD and DEPRECATED decode function with parameter aResults, kept for backward compatibility to old 2.0 tutorials
1843  * This function calls the old MSB first decoders and fills only the 3 variables:
1844  * aResults->value
1845  * aResults->bits
1846  * aResults->decode_type
1847  **********************************************************************************************************************/
1849 
1851  return false;
1852  }
1853 
1854 // copy for usage by legacy programs
1855  aResults->rawbuf[0] = irparams.initialGapTicks;
1856  for (int i = 1; i < RAW_BUFFER_LENGTH; ++i) {
1857  aResults->rawbuf[i] = irparams.rawbuf[i]; // copy 8 bit array into a 16 bit array
1858  }
1859  aResults->rawlen = irparams.rawlen;
1860  if (irparams.OverflowFlag) {
1861  // Copy overflow flag to decodedIRData.flags
1862  irparams.OverflowFlag = false;
1863  irparams.rawlen = 0; // otherwise we have OverflowFlag again at next ISR call
1864  IR_DEBUG_PRINTLN(F("Overflow happened"));
1865  }
1866  aResults->overflow = irparams.OverflowFlag;
1867  aResults->value = 0;
1868 
1870 
1871 #if defined(DECODE_NEC)
1872  IR_DEBUG_PRINTLN(F("Attempting old NEC decode"));
1873  if (decodeNECMSB(aResults)) {
1874  return true;
1875  }
1876 #endif
1877 
1878 #if defined(DECODE_SONY)
1879  IR_DEBUG_PRINTLN(F("Attempting old Sony decode"));
1880  if (decodeSonyMSB(aResults)) {
1881  return true;
1882  }
1883 #endif
1884 
1885 #if defined(DECODE_RC5)
1886  IR_DEBUG_PRINTLN(F("Attempting RC5 decode"));
1887  if (decodeRC5()) {
1888  aResults->bits = decodedIRData.numberOfBits;
1889  aResults->value = decodedIRData.decodedRawData;
1890  aResults->decode_type = RC5;
1891 
1892  return true;
1893  }
1894 #endif
1895 
1896 #if defined(DECODE_RC6)
1897  IR_DEBUG_PRINTLN(F("Attempting RC6 decode"));
1898  if (decodeRC6()) {
1899  aResults->bits = decodedIRData.numberOfBits;
1900  aResults->value = decodedIRData.decodedRawData;
1901  aResults->decode_type = RC6;
1902  return true;
1903  }
1904 #endif
1905 
1906 // Removed bool IRrecv::decodePanasonicMSB(decode_results *aResults) since implementations was wrong (wrong length), and nobody recognized it
1907 
1908 #if defined(DECODE_LG)
1909  IR_DEBUG_PRINTLN(F("Attempting old LG decode"));
1910  if (decodeLGMSB(aResults)) {return true;}
1911 #endif
1912 
1913 #if defined(DECODE_JVC)
1914  IR_DEBUG_PRINTLN(F("Attempting old JVC decode"));
1915  if (decodeJVCMSB(aResults)) {
1916  return true;
1917  }
1918 #endif
1919 
1920 #if defined(DECODE_SAMSUNG)
1921  IR_DEBUG_PRINTLN(F("Attempting old SAMSUNG decode"));
1922  if (decodeSAMSUNG(aResults)) {
1923  return true;
1924  }
1925 #endif
1926 
1927 #if defined(DECODE_DENON)
1928  IR_DEBUG_PRINTLN(F("Attempting old Denon decode"));
1929  if (decodeDenonOld(aResults)) {
1930  return true;
1931  }
1932 #endif
1933 
1934 // decodeHash returns a hash on any input.
1935 // Thus, it needs to be last in the list.
1936 // If you add any decodes, add them before this.
1937  if (decodeHashOld(aResults)) {
1938  return true;
1939  }
1940 // Throw away and start over
1941  resume();
1942  return false;
1943 }
1944 
1946 #if defined(_IR_MEASURE_TIMING)
1947 #undef _IR_MEASURE_TIMING
1948 #endif
1949 #if defined(LOCAL_TRACE)
1950 #undef LOCAL_TRACE
1951 #endif
1952 #if defined(LOCAL_DEBUG)
1953 #undef LOCAL_DEBUG
1954 #endif
1955 #endif // _IR_RECEIVE_HPP
IRData::address
uint16_t address
Decoded address, Distance protocol (tMarkTicksLong (if tMarkTicksLong == 0, then tMarkTicksShort) << ...
Definition: IRProtocol.h:110
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:250
IRrecv::decodeHash
bool decodeHash()
decodeHash - decode an arbitrary IR code.
Definition: IRReceive.hpp:1072
decode_results
Results returned from old decoders !!!deprecated!!!
Definition: IRremoteInt.h:183
digitalReadFast
#define digitalReadFast
Definition: digitalWriteFast.h:393
DistanceWidthTimingInfoStruct::HeaderMarkMicros
uint16_t HeaderMarkMicros
Definition: IRProtocol.h:80
decode_results::rawbuf
uint16_t * rawbuf
Definition: IRremoteInt.h:194
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:431
IRrecv::lastDecodedProtocol
decode_type_t lastDecodedProtocol
Definition: IRremoteInt.h:361
IRData::numberOfBits
uint16_t numberOfBits
Number of bits received for data (address + command + parity) - to determine protocol length if diffe...
Definition: IRProtocol.h:119
RECORD_GAP_TICKS
#define RECORD_GAP_TICKS
Minimum gap between IR transmissions, in MICROS_PER_TICK.
Definition: IRremote.hpp:173
IRrecv::disableIRIn
void disableIRIn()
Alias for stop().
Definition: IRReceive.hpp:441
IRRawlenType
unsigned int IRRawlenType
Definition: IRremoteInt.h:91
IRrecv::enableIRIn
void enableIRIn()
Alias for start().
Definition: IRReceive.hpp:386
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:1269
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:346
IRrecv
Main class for receiving IR signals.
Definition: IRremoteInt.h:200
IRrecv::decodeDistanceWidth
bool decodeDistanceWidth()
Definition: ir_DistanceWidthProtocol.hpp:197
SONY
@ SONY
Definition: IRProtocol.h:64
PULSE_WIDTH
@ PULSE_WIDTH
Definition: IRProtocol.h:42
decode_results::overflow
bool overflow
Definition: IRremoteInt.h:196
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:92
PulseDistanceWidthProtocolConstants::ProtocolIndex
decode_type_t ProtocolIndex
Definition: IRProtocol.h:135
IRrecv::restartAfterSend
void restartAfterSend()
Restarts receiver after send.
Definition: IRReceive.hpp:422
IRrecv::IRrecv
IRrecv()
Instantiate the IRrecv class.
Definition: IRReceive.hpp:70
sBiphaseDecodeRawbuffOffset
uint_fast8_t sBiphaseDecodeRawbuffOffset
Definition: IRReceive.hpp:965
TICKS_LOW
#define TICKS_LOW(us)
Definition: IRremoteInt.h:427
IRrecv::printIRResultAsCVariables
void printIRResultAsCVariables(Print *aSerial)
Print results as C variables to be used for sendXXX()
Definition: IRReceive.hpp:1796
DistanceWidthTimingInfoStruct::OneSpaceMicros
uint16_t OneSpaceMicros
Definition: IRProtocol.h:83
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:131
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:93
decode_results::bits
uint8_t bits
Definition: IRremoteInt.h:189
decode_results::decode_type
decode_type_t decode_type
Definition: IRremoteInt.h:186
IRData::decodedRawData
IRRawDataType decodedRawData
Up to 32/64 bit decoded raw data, to be used for send functions.
Definition: IRProtocol.h:113
matchTicks
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Match function without compensating for marks exceeded or spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1165
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:139
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:290
IRrecv::checkForRepeatSpaceTicksAndSetFlag
void checkForRepeatSpaceTicksAndSetFlag(uint16_t aMaximumRepeatSpaceTicks)
Definition: IRReceive.hpp:1150
IR_DEBUG_PRINT
#define IR_DEBUG_PRINT(...)
If DEBUG, print the arguments, otherwise do nothing.
Definition: IRremoteInt.h:161
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:169
IRrecv::decodeSonyMSB
bool decodeSonyMSB(decode_results *aResults)
Definition: ir_Sony.hpp:154
IRrecv::decodePulseDistanceWidthDataStrict
bool decodePulseDistanceWidthDataStrict(uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset, uint16_t aOneMarkMicros, uint16_t aZeroMarkMicros, uint16_t aOneSpaceMicros, uint16_t aZeroSpaceMicros, bool aMSBfirst)
Definition: IRReceive.hpp:827
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:129
matchSpace
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for spaces shortened by demodulator hardware.
Definition: IRReceive.hpp:1227
DistanceWidthTimingInfoStruct::ZeroMarkMicros
uint16_t ZeroMarkMicros
Definition: IRProtocol.h:84
IRrecv::read
IRData * read()
If IR receiver data is available, returns pointer to IrReceiver.decodedIRData, else NULL.
Definition: IRReceive.hpp:509
IRrecv::getBiphaselevel
uint_fast8_t getBiphaselevel()
Gets the level of one time interval (aBiphaseTimeUnit) at a time from the raw buffer.
Definition: IRReceive.hpp:992
MAGIQUEST
@ MAGIQUEST
Definition: IRProtocol.h:69
sBiphaseCurrentTimingIntervals
uint16_t sBiphaseCurrentTimingIntervals
Definition: IRReceive.hpp:966
timerDisableReceiveInterrupt
void timerDisableReceiveInterrupt()
Disables the receive sample timer interrupt.
Definition: IRTimer.hpp:115
IRrecv::decodeLGMSB
bool decodeLGMSB(decode_results *aResults)
Definition: ir_LG.hpp:290
PulseDistanceWidthProtocolConstants::Flags
uint8_t Flags
Definition: IRProtocol.h:138
irparams
struct irparams_struct irparams
Definition: IRReceive.hpp:64
decode_results::value
uint32_t value
Definition: IRremoteInt.h:188
DistanceWidthTimingInfoStruct
Definition: IRProtocol.h:79
MATCH_SPACE
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1253
IRrecv::decodeSAMSUNG
bool decodeSAMSUNG(decode_results *aResults)
Definition: ir_Samsung.hpp:368
IRrecv::decodeBangOlufsen
bool decodeBangOlufsen()
Definition: ir_BangOlufsen.hpp:293
IRrecv::decodeLegoPowerFunctions
bool decodeLegoPowerFunctions()
Definition: ir_Lego.hpp:128
irparams_struct::OverflowFlag
bool OverflowFlag
Raw buffer OverflowFlag occurred.
Definition: IRremoteInt.h:141
IRrecv::decodeFAST
bool decodeFAST()
Definition: ir_FAST.hpp:98
PulseDistanceWidthProtocolConstants
Definition: IRProtocol.h:134
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
irparams_struct::rawlen
IRRawlenType rawlen
counter of entries in rawbuf
Definition: IRremoteInt.h:142
IRrecv::decodedIRData
IRData decodedIRData
Definition: IRremoteInt.h:358
IRData
Data structure for the user application, available as decodedIRData.
Definition: IRProtocol.h:108
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:97
FNV_PRIME_32
#define FNV_PRIME_32
used for decodeHash()
Definition: IRReceive.hpp:1037
IRrecv::decodeSamsung
bool decodeSamsung()
Definition: ir_Samsung.hpp:269
IRData::flags
uint8_t flags
IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above.
Definition: IRProtocol.h:120
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:98
DistanceWidthTimingInfoStruct::OneMarkMicros
uint16_t OneMarkMicros
Definition: IRProtocol.h:82
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:1370
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:99
DO_NOT_ENABLE_LED_FEEDBACK
#define DO_NOT_ENABLE_LED_FEEDBACK
Definition: IRremoteInt.h:391
MATCH
bool MATCH(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1185
IRrecv::checkHeader
bool checkHeader(PulseDistanceWidthProtocolConstants *aProtocolConstants)
Definition: IRReceive.hpp:1126
IRrecv::decodePulseDistanceWidthData
bool decodePulseDistanceWidthData(PulseDistanceWidthProtocolConstants *aProtocolConstants, uint_fast8_t aNumberOfBits, IRRawlenType aStartOffset=3)
Decode pulse distance protocols for PulseDistanceWidthProtocolConstants.
Definition: IRReceive.hpp:954
sBiphaseUsedTimingIntervals
uint_fast8_t sBiphaseUsedTimingIntervals
Definition: IRReceive.hpp:967
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:1045
IRrecv::printActiveIRProtocols
static void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1294
printActiveIRProtocols
void printActiveIRProtocols(Print *aSerial)
Definition: IRReceive.hpp:1298
IRData::command
uint16_t command
Decoded command, Distance protocol (tMarkTicksShort << 8) | tSpaceTicksShort.
Definition: IRProtocol.h:111
IR_REC_STATE_STOP
#define IR_REC_STATE_STOP
Definition: IRremoteInt.h:123
IR_REC_STATE_MARK
#define IR_REC_STATE_MARK
Definition: IRremoteInt.h:121
IRReceiveTimerInterruptHandler
void IRReceiveTimerInterruptHandler()
Definition: IRReceive.hpp:122
IRrecv::getMaximumTicksFromRawData
uint8_t getMaximumTicksFromRawData(bool aSearchSpaceInsteadOfMark)
Definition: IRReceive.hpp:1421
IRrecv::restartTimer
void restartTimer()
Definition: IRReceive.hpp:374
IRrecv::restartTimerWithTicksToAdd
void restartTimerWithTicksToAdd(uint16_t aTicksToAddToGapCounter)
Definition: IRReceive.hpp:407
FNV_BASIS_32
#define FNV_BASIS_32
used for decodeHash()
Definition: IRReceive.hpp:1038
IRrecv::isIdle
bool isIdle()
Returns status of reception.
Definition: IRReceive.hpp:455
sBiphaseTimeUnit
uint16_t sBiphaseTimeUnit
Definition: IRReceive.hpp:968
timerResetInterruptPending
void timerResetInterruptPending()
IRrecv::printDistanceWidthTimingInfo
void printDistanceWidthTimingInfo(Print *aSerial, DistanceWidthTimingInfoStruct *aDistanceWidthTimingInfo)
Definition: IRReceive.hpp:1379
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:1260
LED_FEEDBACK_ENABLED_FOR_RECEIVE
#define LED_FEEDBACK_ENABLED_FOR_RECEIVE
Definition: IRremoteInt.h:393
matchMark
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros)
Compensate for marks exceeded by demodulator hardware.
Definition: IRReceive.hpp:1193
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:1717
MATCH_MARK
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us)
Definition: IRReceive.hpp:1219
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:137
irparams_struct::StateForISR
volatile uint8_t StateForISR
State Machine state.
Definition: IRremoteInt.h:131
IRrecv::setReceivePin
void setReceivePin(uint_fast8_t aReceivePinNumber)
Sets / changes the receiver pin number.
Definition: IRReceive.hpp:313
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:144
DistanceWidthTimingInfoStruct::ZeroSpaceMicros
uint16_t ZeroSpaceMicros
Definition: IRProtocol.h:85
IRrecv::decodeDenonOld
bool decodeDenonOld(decode_results *aResults)
Definition: ir_Denon.hpp:280
IRRawDataType
uint32_t IRRawDataType
Definition: IRremoteInt.h:109
IRrecv::start
void start()
Start the receiving process.
Definition: IRReceive.hpp:356
IRrecv::compensateAndStoreIRResultInArray
void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr)
Store the decodedIRData to be used for sendRaw().
Definition: IRReceive.hpp:1773
IRrecv::printIRResultMinimal
void printIRResultMinimal(Print *aSerial)
Function to print protocol number, address, command, raw data and repeat flag of IrReceiver....
Definition: IRReceive.hpp:1580
IR_TRACE_PRINTLN
#define IR_TRACE_PRINTLN(...)
Definition: IRremoteInt.h:173
IRrecv::initDecodedIRData
void initDecodedIRData()
Is internally called by decode before calling decoders.
Definition: IRReceive.hpp:474
KASEIKYO
@ KASEIKYO
Definition: IRProtocol.h:53
DENON
@ DENON
Definition: IRProtocol.h:45
IRrecv::getMaximumMarkTicksFromRawData
uint8_t getMaximumMarkTicksFromRawData()
Definition: IRReceive.hpp:1397
IRrecv::addMicrosToInternalTickCounter
void addMicrosToInternalTickCounter(uint16_t aMicrosecondsToAddToInternalTickCounter)
Definition: IRReceive.hpp:416
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:100
IRrecv::lastDecodedCommand
uint32_t lastDecodedCommand
Definition: IRremoteInt.h:363
TICKS_HIGH
#define TICKS_HIGH(us)
Definition: IRremoteInt.h:428
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:91
RC5
@ RC5
Definition: IRProtocol.h:58
IRrecv::available
bool available()
Returns true if IR receiver data is available.
Definition: IRReceive.hpp:502
IRData::extra
uint16_t extra
Contains upper 16 bit of Magiquest WandID, Kaseikyo unknown vendor ID and Distance protocol (HeaderMa...
Definition: IRProtocol.h:112
PulseDistanceWidthProtocolConstants::DistanceWidthTimingInfo
DistanceWidthTimingInfoStruct DistanceWidthTimingInfo
Definition: IRProtocol.h:137
IRrecv::getMaximumSpaceTicksFromRawData
uint8_t getMaximumSpaceTicksFromRawData()
Definition: IRReceive.hpp:1407
IRrecv::decodeMagiQuest
bool decodeMagiQuest()
Definition: ir_MagiQuest.hpp:154
INPUT_MARK
#define INPUT_MARK
Sensor output for a mark ("flash")
Definition: IRremote.hpp:184
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:970
IRrecv::end
void end()
Alias for stop().
Definition: IRReceive.hpp:447
SPACE
#define SPACE
Definition: IRremoteInt.h:39
IRData::rawlen
IRRawlenType rawlen
counter of entries in rawbuf of last received frame.
Definition: IRProtocol.h:128
IRrecv::decodeNECMSB
bool decodeNECMSB(decode_results *aResults)
Definition: ir_NEC.hpp:345
IRrecv::decodeNEC
bool decodeNEC()
Decodes also Onkyo and Apple.
Definition: ir_NEC.hpp:238
RC6
@ RC6
Definition: IRProtocol.h:59
IRrecv::decodeHashOld
bool decodeHashOld(decode_results *aResults)
Definition: IRReceive.hpp:1097
IRrecv::printIRSendUsage
void printIRSendUsage(Print *aSerial)
Function to print values and flags of IrReceiver.decodedIRData in one line.
Definition: IRReceive.hpp:1455
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:412
IRrecv::stopTimer
void stopTimer()
Definition: IRReceive.hpp:435
IRrecv::decode
bool decode()
The main decode function, attempts to decode the recently receive IR signal.
Definition: IRReceive.hpp:526
IRrecv::decodeJVC
bool decodeJVC()
Definition: ir_JVC.hpp:119
UNKNOWN
@ UNKNOWN
Definition: IRProtocol.h:41
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:81
IRrecv::lastDecodedAddress
uint32_t lastDecodedAddress
Definition: IRremoteInt.h:362
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:165
IRrecv::getTotalDurationOfRawData
uint32_t getTotalDurationOfRawData()
Definition: IRReceive.hpp:1438
decode_results::rawlen
uint_fast8_t rawlen
Definition: IRremoteInt.h:195
IRData::protocol
decode_type_t protocol
UNKNOWN, NEC, SONY, RC5, PULSE_DISTANCE, ...
Definition: IRProtocol.h:109
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:122
IRrecv::getProtocolString
const char * getProtocolString()
Definition: IRReceive.hpp:1835
IRrecv::resume
void resume()
Restart the ISR (Interrupt Service Routine) state machine, to enable receiving of the next IR frame.
Definition: IRReceive.hpp:463
MARK
#define MARK
Definition: IRremoteInt.h:38
DistanceWidthTimingInfoStruct::HeaderSpaceMicros
uint16_t HeaderSpaceMicros
Definition: IRProtocol.h:81
IRrecv::startWithTicksToAdd
void startWithTicksToAdd(uint16_t aTicksToAddToGapCounter)
Definition: IRReceive.hpp:403
IRrecv::decode_old
bool decode_old(decode_results *aResults)
Definition: IRReceive.hpp:1848
IrReceiver
IRrecv IrReceiver
The receiver instance.
Definition: IRReceive.hpp:59
IRData::initialGapTicks
uint16_t initialGapTicks
contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
Definition: IRProtocol.h:129
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:1624
IR_REC_STATE_IDLE
#define IR_REC_STATE_IDLE
Definition: IRremoteInt.h:120
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:132
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:143