Go to the documentation of this file.
70 #ifndef _TINY_IR_RECEIVER_HPP
71 #define _TINY_IR_RECEIVER_HPP
96 #define LOCAL_DEBUG_ATTACH_INTERRUPT
103 #define LOCAL_TRACE_STATE_MACHINE
116 #if defined(IR_INPUT_PIN)
117 #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
118 #define IR_RECEIVE_PIN IR_INPUT_PIN
121 #if !defined(IR_RECEIVE_PIN)
122 # if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
123 #warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
124 #define IR_RECEIVE_PIN 10
125 # elif defined(__AVR_ATtiny816__)
126 #warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
127 #define IR_RECEIVE_PIN 14
129 #warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
130 #define IR_RECEIVE_PIN 2
134 #if !defined(NO_LED_RECEIVE_FEEDBACK_CODE)
135 #define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative
139 (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) \
140 || defined(__AVR_ATtiny88__) \
141 || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \
142 || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \
143 || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \
144 || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
146 || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) \
147 || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) \
149 #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.
164 #if defined(ESP8266) || defined(ESP32)
168 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
177 #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
178 # if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
189 uint32_t tCurrentMicros = micros();
191 uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32;
197 #if defined(LOCAL_TRACE_STATE_MACHINE)
198 Serial.print(tState);
199 Serial.print(F(
" D="));
200 Serial.print(tMicrosOfMarkOrSpace);
206 if (tIRLevel == LOW) {
218 #if defined(TRACE) // Do not use LOCAL_TRACE here since sMicrosOfGap is read in a cpp file at TRACE
221 #if defined(ENABLE_NEC2_REPEATS)
238 #if (TINY_RECEIVER_BITS > 16)
246 #if !defined(ENABLE_NEC2_REPEATS)
276 #if (TINY_RECEIVER_BITS > 16)
323 #
if !defined(ENABLE_NEC2_REPEATS)
333 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
339 #if defined(ENABLE_NEC2_REPEATS)
346 #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
350 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
352 #if defined(ENABLE_NEC2_REPEATS)
357 # if defined(LOCAL_DEBUG)
358 Serial.print(F(
"Parity check for command failed. Command="));
360 Serial.print(F(
" parity="));
367 # if defined(LOCAL_DEBUG)
368 Serial.print(F(
"Parity check for command failed. Command="));
370 Serial.print(F(
" parity="));
381 #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
386 #if (TINY_RECEIVER_ADDRESS_BITS > 0)
387 # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
394 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
404 # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
412 #if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
431 #ifdef _IR_MEASURE_TIMING
469 #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
471 # if defined(FEEDBACK_LED_IS_ACTIVE_LOW)
480 #if defined(USE_FAST_PROTOCOL)
481 aSerial->print(F(
"C=0x"));
483 aSerial->print(F(
"A=0x"));
485 aSerial->print(F(
" C=0x"));
489 aSerial->print(F(
" R"));
491 #if !defined(DISABLE_PARITY_CHECKS)
493 aSerial->print(F(
" P"));
499 #if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR)
501 #define STR_HELPER(x) #x
502 #define STR(x) STR_HELPER(x)
508 #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
509 #define USE_ATTACH_INTERRUPT_DIRECT
511 #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
513 #define USE_ATTACH_INTERRUPT
516 # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
519 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
520 # if defined(ARDUINO_AVR_DIGISPARKPRO)
521 # if (IR_RECEIVE_PIN == 3)
523 # elif (IR_RECEIVE_PIN == 9)
526 # error "IR_RECEIVE_PIN must be 9 or 3."
527 # endif // if (IR_RECEIVE_PIN == 9)
528 # else // defined(ARDUINO_AVR_DIGISPARKPRO)
529 # if (IR_RECEIVE_PIN == 14)
531 # elif (IR_RECEIVE_PIN == 3)
534 # error "IR_RECEIVE_PIN must be 14 or 3."
535 # endif // if (IR_RECEIVE_PIN == 14)
538 # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
539 # if (IR_RECEIVE_PIN == 21)
541 # elif (IR_RECEIVE_PIN == 20)
544 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
545 #define USE_ATTACH_INTERRUPT
548 # else // defined(__AVR_ATtiny25__)
552 # if (IR_RECEIVE_PIN == 2)
554 # elif (IR_RECEIVE_PIN == 3)
557 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
560 # 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
563 # 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
568 #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
569 #define USE_ATTACH_INTERRUPT
570 # endif // if (IR_RECEIVE_PIN == 2)
571 # endif // defined(__AVR_ATtiny25__)
572 #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
579 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
583 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
584 # if defined(USE_ATTACH_INTERRUPT)
585 # if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt
591 # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax
602 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
603 Serial.println(F(
"Use attachInterrupt for pin=" STR(
IR_RECEIVE_PIN)));
606 # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
607 Serial.println(F(
"Use static interrupt for pin=" STR(
IR_RECEIVE_PIN)));
610 # if defined(USE_INT0)
618 # elif defined(USE_INT1)
625 # elif defined(USE_PCIE) // For ATtiny85 etc.
633 # elif defined(USE_PCINT0)
636 # elif defined(USE_PCINT1)
639 # elif defined(USE_PCINT2)
645 #endif // defined(USE_ATTACH_INTERRUPT)
650 #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
654 #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
655 # if defined(USE_ATTACH_INTERRUPT)
662 # if defined(USE_INT0)
666 EIMSK &= ~(1 << INT0);
668 # elif defined(USE_INT1)
672 EIMSK &= ~(1 << INT1);
674 # elif defined(USE_PCIE) // For ATtiny85 etc.
678 GIMSK &= ~(1 << PCIE);
680 # elif defined(USE_PCINT0)
681 PCICR &= ~(_BV(PCIE0));
682 # elif defined(USE_PCINT1)
683 PCICR &= ~(_BV(PCIE1));
684 # elif defined(USE_PCINT2)
685 PCICR &= ~(_BV(PCIE2));
688 #endif // defined(USE_ATTACH_INTERRUPT)
695 #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
696 # if defined(USE_INT0)
699 # elif defined(USE_INT1)
702 # elif defined(USE_PCIE) // For ATtiny85 etc.
706 # elif defined(USE_PCINT0)
708 # elif defined(USE_PCINT1)
710 # elif defined(USE_PCINT2)
713 void dummyFunctionToAvoidCompilerErrors()
718 #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
722 #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
723 #undef LOCAL_DEBUG_ATTACH_INTERRUPT
725 #if defined(LOCAL_TRACE_STATE_MACHINE)
726 #undef LOCAL_TRACE_STATE_MACHINE
729 #if defined(LOCAL_DEBUG)
732 #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 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