Go to the documentation of this file.
70 #ifndef _TINY_IR_RECEIVER_HPP
71 #define _TINY_IR_RECEIVER_HPP
96 #if defined(LOCAL_DEBUG)
97 #define LOCAL_DEBUG_ATTACH_INTERRUPT
110 #if defined(IR_INPUT_PIN)
111 #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
112 #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(NO_LED_RECEIVE_FEEDBACK_CODE)
129 #define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
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)))) ) \
147 #define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
162 #if defined(ESP8266) || defined(ESP32)
166 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
175 #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
176 # if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
187 uint32_t tCurrentMicros = micros();
189 uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
202 if (tIRLevel == LOW) {
214 #if defined(TRACE) // Do not use LOCAL_TRACE here since sMicrosOfGap is read in a cpp file at TRACE
217 #if defined(ENABLE_NEC2_REPEATS)
234 #if (TINY_RECEIVER_BITS > 16)
242 #if !defined(ENABLE_NEC2_REPEATS)
271 #if (TINY_RECEIVER_BITS > 16)
318 #
if !defined(ENABLE_NEC2_REPEATS)
328 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
334 #if defined(ENABLE_NEC2_REPEATS)
341 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
345 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
347 #if defined(ENABLE_NEC2_REPEATS)
352 DEBUG_PRINT(F(
"Parity check for command failed. Command="));
360 DEBUG_PRINT(F(
"Parity check for command failed. Command="));
372 #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled
377 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
378 # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
385 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
395 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
403 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
422 #ifdef _IR_MEASURE_TIMING
460 #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
462 # if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
471 #if defined(USE_FAST_PROTOCOL)
472 aSerial->print(F(
"C=0x"));
474 aSerial->print(F(
"A=0x"));
476 aSerial->print(F(
" C=0x"));
480 aSerial->print(F(
" R"));
482 #if !defined(DISABLE_PARITY_CHECKS)
484 aSerial->print(F(
" P"));
490 #if !defined(STR_HELPER) && !defined(STR)
492 #define STR_HELPER(x) #x
493 #define STR(x) STR_HELPER(x)
499 #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
500 #define USE_ATTACH_INTERRUPT_DIRECT
502 #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
504 #define USE_ATTACH_INTERRUPT
507 # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
510 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
511 # if defined(ARDUINO_AVR_DIGISPARKPRO)
512 # if (IR_RECEIVE_PIN == 3)
514 # elif (IR_RECEIVE_PIN == 9)
517 # error "IR_RECEIVE_PIN must be 9 or 3."
518 # endif // if (IR_RECEIVE_PIN == 9)
519 # else // defined(ARDUINO_AVR_DIGISPARKPRO)
520 # if (IR_RECEIVE_PIN == 14)
522 # elif (IR_RECEIVE_PIN == 3)
525 # error "IR_RECEIVE_PIN must be 14 or 3."
526 # endif // if (IR_RECEIVE_PIN == 14)
529 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
530 # if (IR_RECEIVE_PIN == 21)
532 # elif (IR_RECEIVE_PIN == 20)
535 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
536 #define USE_ATTACH_INTERRUPT
539 # else // defined(__AVR_ATtiny25__)
543 # if (IR_RECEIVE_PIN == 2)
545 # elif (IR_RECEIVE_PIN == 3)
548 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
551 # 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
554 # 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
559 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
560 #define USE_ATTACH_INTERRUPT
561 # endif // if (IR_RECEIVE_PIN == 2)
562 # endif // defined(__AVR_ATtiny25__)
563 #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
570 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
574 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
575 # if defined(USE_ATTACH_INTERRUPT)
576 # if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt
582 # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
593 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
597 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
601 # if defined(USE_INT0)
609 # elif defined(USE_INT1)
616 # elif defined(USE_PCIE) // For ATtiny85 etc.
624 # elif defined(USE_PCINT0)
627 # elif defined(USE_PCINT1)
630 # elif defined(USE_PCINT2)
636 #endif // defined(USE_ATTACH_INTERRUPT)
641 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
645 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
646 # if defined(USE_ATTACH_INTERRUPT)
653 # if defined(USE_INT0)
657 EIMSK &= ~(1 << INT0);
659 # elif defined(USE_INT1)
663 EIMSK &= ~(1 << INT1);
665 # elif defined(USE_PCIE) // For ATtiny85 etc.
669 GIMSK &= ~(1 << PCIE);
671 # elif defined(USE_PCINT0)
672 PCICR &= ~(_BV(PCIE0));
673 # elif defined(USE_PCINT1)
674 PCICR &= ~(_BV(PCIE1));
675 # elif defined(USE_PCINT2)
676 PCICR &= ~(_BV(PCIE2));
679 #endif // defined(USE_ATTACH_INTERRUPT)
686 #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
687 # if defined(USE_INT0)
690 # elif defined(USE_INT1)
693 # elif defined(USE_PCIE) // For ATtiny85 etc.
697 # elif defined(USE_PCINT0)
699 # elif defined(USE_PCINT1)
701 # elif defined(USE_PCINT2)
704 void dummyFunctionToAvoidCompilerErrors()
709 #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
713 #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
714 #undef LOCAL_DEBUG_ATTACH_INTERRUPT
718 #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_ONE_THRESHOLD
#define DEBUG_PRINTLN(...)
#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...
#define TINY_RECEIVER_MARK_TIMEOUT