Go to the documentation of this file.
68 #ifndef _TINY_IR_RECEIVER_HPP
69 #define _TINY_IR_RECEIVER_HPP
90 #define LOCAL_DEBUG_ATTACH_INTERRUPT
98 #define LOCAL_TRACE_STATE_MACHINE
114 #if defined(IR_INPUT_PIN)
115 #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
116 #define IR_RECEIVE_PIN IR_INPUT_PIN
119 #if !defined(IR_RECEIVE_PIN)
120 # if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
121 #warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
122 #define IR_RECEIVE_PIN 10
123 # elif defined(__AVR_ATtiny816__)
124 #warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
125 #define IR_RECEIVE_PIN 14
127 #warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
128 #define IR_RECEIVE_PIN 2
132 #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
133 #define IR_FEEDBACK_LED_PIN LED_BUILTIN
137 (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) \
138 || defined(__AVR_ATtiny88__) \
139 || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
140 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
141 || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
142 || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
144 || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) \
145 || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) \
147 #define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT // Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change.
156 #if defined(LOCAL_DEBUG)
157 uint32_t sMicrosOfGap;
164 #if defined(ESP8266) || defined(ESP32)
168 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
177 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
185 uint32_t tCurrentMicros = micros();
187 uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
193 #if defined(LOCAL_TRACE_STATE_MACHINE)
194 Serial.print(tState);
195 Serial.print(F(
" D="));
196 Serial.print(tMicrosOfMarkOrSpace);
202 if (tIRLevel == LOW) {
214 #if defined(LOCAL_TRACE)
215 sMicrosOfGap = tMicrosOfMarkOrSpace32;
217 #if defined(ENABLE_NEC2_REPEATS)
234 #if (TINY_RECEIVER_BITS > 16)
241 #if !defined(ENABLE_NEC2_REPEATS)
267 #if (TINY_RECEIVER_BITS > 16)
313 #
if !defined(ENABLE_NEC2_REPEATS)
323 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
329 #if defined(ENABLE_NEC2_REPEATS)
336 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
340 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
342 #if defined(ENABLE_NEC2_REPEATS)
347 # if defined(LOCAL_DEBUG)
348 Serial.print(F(
"Parity check for command failed. Command="));
350 Serial.print(F(
" parity="));
357 # if defined(LOCAL_DEBUG)
358 Serial.print(F(
"Parity check for command failed. Command="));
360 Serial.print(F(
" parity="));
371 #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
376 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
377 # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
384 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
394 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
402 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
421 #ifdef _IR_MEASURE_TIMING
459 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
467 #if defined(USE_FAST_PROTOCOL)
468 aSerial->print(F(
"C=0x"));
470 aSerial->print(F(
"A=0x"));
472 aSerial->print(F(
" C=0x"));
476 aSerial->print(F(
" R"));
478 #if !defined(DISABLE_PARITY_CHECKS)
480 aSerial->print(F(
" P"));
486 #if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR)
488 #define STR_HELPER(x) #x
489 #define STR(x) STR_HELPER(x)
495 #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
496 #define USE_ATTACH_INTERRUPT_DIRECT
498 #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
500 #define USE_ATTACH_INTERRUPT
503 # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
506 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
507 # if defined(ARDUINO_AVR_DIGISPARKPRO)
508 # if (IR_RECEIVE_PIN == 3)
510 # elif (IR_RECEIVE_PIN == 9)
513 # error "IR_RECEIVE_PIN must be 9 or 3."
514 # endif // if (IR_RECEIVE_PIN == 9)
515 # else // defined(ARDUINO_AVR_DIGISPARKPRO)
516 # if (IR_RECEIVE_PIN == 14)
518 # elif (IR_RECEIVE_PIN == 3)
521 # error "IR_RECEIVE_PIN must be 14 or 3."
522 # endif // if (IR_RECEIVE_PIN == 14)
525 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
526 # if (IR_RECEIVE_PIN == 21)
528 # elif (IR_RECEIVE_PIN == 20)
531 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
532 #define USE_ATTACH_INTERRUPT
535 # else // defined(__AVR_ATtiny25__)
539 # if (IR_RECEIVE_PIN == 2)
541 # elif (IR_RECEIVE_PIN == 3)
544 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
547 # elif IR_RECEIVE_PIN == 8 || IR_RECEIVE_PIN == 9 || IR_RECEIVE_PIN == 10 || IR_RECEIVE_PIN == 11 || IR_RECEIVE_PIN == 12 || IR_RECEIVE_PIN == 13
550 # elif IR_RECEIVE_PIN == A0 || IR_RECEIVE_PIN == A1 || IR_RECEIVE_PIN == A2 || IR_RECEIVE_PIN == A3 || IR_RECEIVE_PIN == A4 || IR_RECEIVE_PIN == A5
555 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
556 #define USE_ATTACH_INTERRUPT
557 # endif // if (IR_RECEIVE_PIN == 2)
558 # endif // defined(__AVR_ATtiny25__)
559 #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
566 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
570 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
571 # if defined(USE_ATTACH_INTERRUPT)
572 # if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt
578 # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
589 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
590 Serial.println(F(
"Use attachInterrupt for pin=" STR(
IR_RECEIVE_PIN)));
593 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
594 Serial.println(F(
"Use static interrupt for pin=" STR(
IR_RECEIVE_PIN)));
597 # if defined(USE_INT0)
605 # elif defined(USE_INT1)
612 # elif defined(USE_PCIE) // For ATtiny85 etc.
620 # elif defined(USE_PCINT0)
623 # elif defined(USE_PCINT1)
626 # elif defined(USE_PCINT2)
632 #endif // defined(USE_ATTACH_INTERRUPT)
637 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
641 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
642 # if defined(USE_ATTACH_INTERRUPT)
649 # if defined(USE_INT0)
653 EIMSK &= ~(1 << INT0);
655 # elif defined(USE_INT1)
659 EIMSK &= ~(1 << INT1);
661 # elif defined(USE_PCIE) // For ATtiny85 etc.
665 GIMSK &= ~(1 << PCIE);
667 # elif defined(USE_PCINT0)
668 PCICR &= ~(_BV(PCIE0));
669 # elif defined(USE_PCINT1)
670 PCICR &= ~(_BV(PCIE1));
671 # elif defined(USE_PCINT2)
672 PCICR &= ~(_BV(PCIE2));
675 #endif // defined(USE_ATTACH_INTERRUPT)
682 #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
683 # if defined(USE_INT0)
686 # elif defined(USE_INT1)
689 # elif defined(USE_PCIE) // For ATtiny85 etc.
693 # elif defined(USE_PCINT0)
695 # elif defined(USE_PCINT1)
697 # elif defined(USE_PCINT2)
700 void dummyFunctionToAvoidCompilerErrors()
705 #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
709 #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
710 #undef LOCAL_DEBUG_ATTACH_INTERRUPT
712 #if defined(LOCAL_TRACE_STATE_MACHINE)
713 #undef LOCAL_TRACE_STATE_MACHINE
716 #if defined(LOCAL_DEBUG)
719 #endif // _TINY_IR_RECEIVER_HPP
uint8_t IRReceiverState
The state of the state machine.
#define lowerValue25Percent(aDuration)
#define IR_RECEIVER_STATE_WAITING_FOR_START_MARK
Control and data variables of the state machine for TinyReceiver.
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK
uint8_t Flags
One of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT, and IRDATA_FLAGS_PARITY_FAILED.
TinyIRReceiverStruct TinyIRReceiverControl
#define IRDATA_FLAGS_IS_REPEAT
The gap between the preceding frame is as smaller than the maximum gap expected for a repeat....
bool enablePCIInterruptForTinyReceiver()
Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt() functi...
volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData
bool isTinyReceiverIdle()
#define TINY_RECEIVER_ONE_SPACE
void handleReceivedTinyIRData()
Declaration of the callback function provided by the user application.
#define IRDATA_FLAGS_PARITY_FAILED
The current (autorepeat) frame violated parity check.
void disablePCIInterruptForTinyReceiver()
#define TINY_RECEIVER_BITS
bool TinyReceiverDecode()
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE
bool justWritten
Is set true if new data is available. Used by the main loop / TinyReceiverDecode(),...
#define upperValue50Percent(aDuration)
uint32_t LastChangeMicros
Microseconds of last Pin Change Interrupt.
#define TINY_RECEIVER_HEADER_MARK
uint32_t IRRawDataMask
The corresponding bit mask for IRRawDataBitCounter.
Is filled before calling the user callback to transfer received data to main loop for further process...
void IRPinChangeInterruptHandler(void)
The ISR (Interrupt Service Routine) of TinyIRRreceiver.
void printTinyReceiverResultMinimal(Print *aSerial)
uint8_t IRRawDataBitCounter
How many bits are currently contained in raw data.
#define TINY_RECEIVER_HEADER_SPACE
#define TINY_RECEIVER_UNIT
#define IRDATA_FLAGS_EMPTY
#define TINY_RECEIVER_BIT_MARK
#define upperValue25Percent(aDuration)
#define NEC_REPEAT_HEADER_SPACE
#define TINY_RECEIVER_ZERO_SPACE
#define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE
bool isIRReceiverAttachedForTinyReceiver()
#define lowerValue50Percent(aDuration)
#define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK
struct LongUnion::@6 UWord
LongUnion IRRawData
The current raw data. LongUnion helps with decoding of address and command.
#define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE
bool initPCIInterruptForTinyReceiver()
Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mo...