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)
96 #define LOCAL_DEBUG_ATTACH_INTERRUPT
101 #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
118 #if !defined(IR_RECEIVE_PIN)
119 #if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
120 #warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
121 #define IR_RECEIVE_PIN 10
122 #elif defined(__AVR_ATtiny816__)
123 #warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
124 #define IR_RECEIVE_PIN 14
126 #warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
127 #define IR_RECEIVE_PIN 2
131 #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
132 #define IR_FEEDBACK_LED_PIN LED_BUILTIN
136 (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) \
137 || defined(__AVR_ATtiny88__) \
138 || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
139 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
140 || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
141 || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
143 || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) \
144 || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) \
146 #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.
155 #if defined(LOCAL_DEBUG)
156 uint32_t sMicrosOfGap;
163 #if defined(ESP8266) || defined(ESP32)
167 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
176 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
184 uint32_t tCurrentMicros = micros();
186 uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
192 #if defined(LOCAL_TRACE_STATE_MACHINE)
193 Serial.print(tState);
194 Serial.print(F(
" D="));
195 Serial.print(tMicrosOfMarkOrSpace);
201 if (tIRLevel == LOW) {
213 #if defined(LOCAL_TRACE)
214 sMicrosOfGap = tMicrosOfMarkOrSpace32;
216 #if defined(ENABLE_NEC2_REPEATS)
233 #if (TINY_RECEIVER_BITS > 16)
240 #if !defined(ENABLE_NEC2_REPEATS)
266 #if (TINY_RECEIVER_BITS > 16)
312 #
if !defined(ENABLE_NEC2_REPEATS)
322 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
328 #if defined(ENABLE_NEC2_REPEATS)
335 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
339 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
341 #if defined(ENABLE_NEC2_REPEATS)
346 # if defined(LOCAL_DEBUG)
347 Serial.print(F(
"Parity check for command failed. Command="));
349 Serial.print(F(
" parity="));
356 # if defined(LOCAL_DEBUG)
357 Serial.print(F(
"Parity check for command failed. Command="));
359 Serial.print(F(
" parity="));
370 #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
375 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
376 # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
383 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
393 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
401 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
402 handleReceivedTinyIRData();
420 #ifdef _IR_MEASURE_TIMING
447 #if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
456 #if defined(USE_FAST_PROTOCOL)
457 aSerial->print(F(
"C=0x"));
459 aSerial->print(F(
"A=0x"));
461 aSerial->print(F(
" C=0x"));
465 aSerial->print(F(
" R"));
467 #if !defined(DISABLE_PARITY_CHECKS)
469 aSerial->print(F(
" P"));
475 #if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR)
477 #define STR_HELPER(x) #x
478 #define STR(x) STR_HELPER(x)
484 #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
485 #define USE_ATTACH_INTERRUPT_DIRECT
487 #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
489 #define USE_ATTACH_INTERRUPT
492 # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
495 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
496 # if defined(ARDUINO_AVR_DIGISPARKPRO)
497 # if (IR_RECEIVE_PIN == 3)
499 # elif (IR_RECEIVE_PIN == 9)
502 # error "IR_RECEIVE_PIN must be 9 or 3."
503 # endif // if (IR_RECEIVE_PIN == 9)
504 # else // defined(ARDUINO_AVR_DIGISPARKPRO)
505 # if (IR_RECEIVE_PIN == 14)
507 # elif (IR_RECEIVE_PIN == 3)
510 # error "IR_RECEIVE_PIN must be 14 or 3."
511 # endif // if (IR_RECEIVE_PIN == 14)
514 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
515 # if (IR_RECEIVE_PIN == 21)
517 # elif (IR_RECEIVE_PIN == 20)
520 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
521 #define USE_ATTACH_INTERRUPT
524 # else // defined(__AVR_ATtiny25__)
528 # if (IR_RECEIVE_PIN == 2)
530 # elif (IR_RECEIVE_PIN == 3)
533 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
536 # 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
539 # 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
544 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
545 #define USE_ATTACH_INTERRUPT
546 # endif // if (IR_RECEIVE_PIN == 2)
547 # endif // defined(__AVR_ATtiny25__)
548 #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
555 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
559 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
560 # if defined(USE_ATTACH_INTERRUPT)
561 #if defined(NOT_AN_INTERRUPT)
573 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
574 Serial.println(F(
"Use attachInterrupt for pin=" STR(
IR_RECEIVE_PIN)));
578 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
579 Serial.println(F(
"Use static interrupt for pin=" STR(
IR_RECEIVE_PIN)));
581 # if defined(USE_INT0)
589 # elif defined(USE_INT1)
596 # elif defined(USE_PCIE) // For ATtiny85 etc.
604 # elif defined(USE_PCINT0)
607 # elif defined(USE_PCINT1)
610 # elif defined(USE_PCINT2)
616 #endif // defined(USE_ATTACH_INTERRUPT)
621 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
625 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
626 # if defined(USE_ATTACH_INTERRUPT)
633 # if defined(USE_INT0)
637 EIMSK &= ~(1 << INT0);
639 # elif defined(USE_INT1)
643 EIMSK &= ~(1 << INT1);
645 # elif defined(USE_PCIE) // For ATtiny85 etc.
649 GIMSK &= ~(1 << PCIE);
651 # elif defined(USE_PCINT0)
652 PCICR &= ~(_BV(PCIE0));
653 # elif defined(USE_PCINT1)
654 PCICR &= ~(_BV(PCIE1));
655 # elif defined(USE_PCINT2)
656 PCICR &= ~(_BV(PCIE2));
659 #endif // defined(USE_ATTACH_INTERRUPT)
666 #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
667 # if defined(USE_INT0)
670 # elif defined(USE_INT1)
673 # elif defined(USE_PCIE) // For ATtiny85 etc.
677 # elif defined(USE_PCINT0)
679 # elif defined(USE_PCINT1)
681 # elif defined(USE_PCINT2)
684 void dummyFunctionToAvoidCompilerErrors()
689 #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
693 #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
694 #undef LOCAL_DEBUG_ATTACH_INTERRUPT
696 #if defined(LOCAL_TRACE_STATE_MACHINE)
697 #undef LOCAL_TRACE_STATE_MACHINE
700 #if defined(LOCAL_DEBUG)
703 #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...