Go to the documentation of this file.
68 #ifndef _TINY_IR_RECEIVER_HPP
69 #define _TINY_IR_RECEIVER_HPP
73 #if defined(DEBUG) && !defined(LOCAL_DEBUG)
93 #define LOCAL_DEBUG_ATTACH_INTERRUPT
98 #define LOCAL_TRACE_STATE_MACHINE
111 #if defined(IR_INPUT_PIN)
112 #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
113 #define IR_RECEIVE_PIN IR_INPUT_PIN
115 #if !defined(IR_RECEIVE_PIN)
116 #if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
117 #warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
118 #define IR_RECEIVE_PIN 10
119 #elif defined(__AVR_ATtiny816__)
120 #warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
121 #define IR_RECEIVE_PIN 14
123 #warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
124 #define IR_RECEIVE_PIN 2
128 #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
129 #define IR_FEEDBACK_LED_PIN LED_BUILTIN
133 (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) \
134 || defined(__AVR_ATtiny88__) \
135 || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
136 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
137 || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
138 || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
140 || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) \
141 || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) \
143 #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.
152 #if defined(LOCAL_DEBUG)
153 uint32_t sMicrosOfGap;
160 #if defined(ESP8266) || defined(ESP32)
164 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
173 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
181 uint32_t tCurrentMicros = micros();
183 uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
189 #if defined(LOCAL_TRACE_STATE_MACHINE)
190 Serial.print(tState);
191 Serial.print(F(
" D="));
192 Serial.print(tMicrosOfMarkOrSpace);
198 if (tIRLevel == LOW) {
210 #if defined(LOCAL_TRACE)
211 sMicrosOfGap = tMicrosOfMarkOrSpace32;
213 #if defined(ENABLE_NEC2_REPEATS)
230 #if (TINY_RECEIVER_BITS > 16)
237 #if !defined(ENABLE_NEC2_REPEATS)
263 #if (TINY_RECEIVER_BITS > 16)
309 #
if !defined(ENABLE_NEC2_REPEATS)
319 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
325 #if defined(ENABLE_NEC2_REPEATS)
332 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
336 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
338 #if defined(ENABLE_NEC2_REPEATS)
343 # if defined(LOCAL_DEBUG)
344 Serial.print(F(
"Parity check for command failed. Command="));
346 Serial.print(F(
" parity="));
353 # if defined(LOCAL_DEBUG)
354 Serial.print(F(
"Parity check for command failed. Command="));
356 Serial.print(F(
" parity="));
367 #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
372 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
373 # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
380 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
390 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
398 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
399 handleReceivedTinyIRData();
417 #ifdef _IR_MEASURE_TIMING
444 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
453 #if defined(USE_FAST_PROTOCOL)
454 aSerial->print(F(
"C=0x"));
456 aSerial->print(F(
"A=0x"));
458 aSerial->print(F(
" C=0x"));
462 aSerial->print(F(
" R"));
464 #if !defined(DISABLE_PARITY_CHECKS)
466 aSerial->print(F(
" P"));
472 #if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR)
474 #define STR_HELPER(x) #x
475 #define STR(x) STR_HELPER(x)
481 #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
482 #define USE_ATTACH_INTERRUPT_DIRECT
484 #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
486 #define USE_ATTACH_INTERRUPT
489 # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
492 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
493 # if defined(ARDUINO_AVR_DIGISPARKPRO)
494 # if (IR_RECEIVE_PIN == 3)
496 # elif (IR_RECEIVE_PIN == 9)
499 # error "IR_RECEIVE_PIN must be 9 or 3."
500 # endif // if (IR_RECEIVE_PIN == 9)
501 # else // defined(ARDUINO_AVR_DIGISPARKPRO)
502 # if (IR_RECEIVE_PIN == 14)
504 # elif (IR_RECEIVE_PIN == 3)
507 # error "IR_RECEIVE_PIN must be 14 or 3."
508 # endif // if (IR_RECEIVE_PIN == 14)
511 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
512 # if (IR_RECEIVE_PIN == 21)
514 # elif (IR_RECEIVE_PIN == 20)
517 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
518 #define USE_ATTACH_INTERRUPT
521 # else // defined(__AVR_ATtiny25__)
525 # if (IR_RECEIVE_PIN == 2)
527 # elif (IR_RECEIVE_PIN == 3)
530 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
533 # 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
536 # 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
541 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
542 #define USE_ATTACH_INTERRUPT
543 # endif // if (IR_RECEIVE_PIN == 2)
544 # endif // defined(__AVR_ATtiny25__)
545 #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
552 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
556 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
557 # if defined(USE_ATTACH_INTERRUPT)
558 #if defined(NOT_AN_INTERRUPT)
570 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
571 Serial.println(F(
"Use attachInterrupt for pin=" STR(
IR_RECEIVE_PIN)));
575 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
576 Serial.println(F(
"Use static interrupt for pin=" STR(
IR_RECEIVE_PIN)));
578 # if defined(USE_INT0)
586 # elif defined(USE_INT1)
593 # elif defined(USE_PCIE) // For ATtiny85 etc.
601 # elif defined(USE_PCINT0)
604 # elif defined(USE_PCINT1)
607 # elif defined(USE_PCINT2)
613 #endif // defined(USE_ATTACH_INTERRUPT)
618 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
622 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
623 # if defined(USE_ATTACH_INTERRUPT)
630 # if defined(USE_INT0)
634 EIMSK &= ~(1 << INT0);
636 # elif defined(USE_INT1)
640 EIMSK &= ~(1 << INT1);
642 # elif defined(USE_PCIE) // For ATtiny85 etc.
646 GIMSK &= ~(1 << PCIE);
648 # elif defined(USE_PCINT0)
649 PCICR &= ~(_BV(PCIE0));
650 # elif defined(USE_PCINT1)
651 PCICR &= ~(_BV(PCIE1));
652 # elif defined(USE_PCINT2)
653 PCICR &= ~(_BV(PCIE2));
656 #endif // defined(USE_ATTACH_INTERRUPT)
663 #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
664 # if defined(USE_INT0)
667 # elif defined(USE_INT1)
670 # elif defined(USE_PCIE) // For ATtiny85 etc.
674 # elif defined(USE_PCINT0)
676 # elif defined(USE_PCINT1)
678 # elif defined(USE_PCINT2)
681 void dummyFunctionToAvoidCompilerErrors()
686 #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
690 #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
691 #undef LOCAL_DEBUG_ATTACH_INTERRUPT
693 #if defined(LOCAL_TRACE_STATE_MACHINE)
694 #undef LOCAL_TRACE_STATE_MACHINE
697 #if defined(LOCAL_DEBUG)
700 #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
#define IRDATA_FLAGS_PARITY_FAILED
The current (autorepeat) frame violated parity check.
void disablePCIInterruptForTinyReceiver()
void handleTinyReceivedIRData()
Declaration of the callback function provided by the user application.
#define TINY_RECEIVER_BITS
#define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE
bool justWritten
Is set true if new data is available. Used by the main loop, to avoid multiple evaluations of the sam...
#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...