2021-01-04 09:54:10 +08:00
/*
2021-09-09 21:53:50 +08:00
* TinyIRReceiver . hpp
2021-01-04 09:54:10 +08:00
*
* Receives IR protocol data of NEC protocol using pin change interrupts .
* NEC is the protocol of most cheap remote controls for Arduino .
*
2022-11-12 02:53:54 +08:00
* Parity check is done for address and data .
* On a completely received IR command , the user function handleReceivedIRData ( uint8_t aAddress , uint8_t aCommand , uint8_t aFlags )
2022-06-09 03:23:20 +08:00
* is called in interrupt context but with interrupts being enabled to enable use of delay ( ) etc .
2021-01-04 09:54:10 +08:00
* ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
* Functions called in interrupt context should be running as short as possible ,
* so if you require longer action , save the data ( address + command ) and handle them in the main loop .
* ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
2022-11-12 02:53:54 +08:00
* aFlags can contain one of IRDATA_FLAGS_EMPTY , IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bits
2021-01-04 09:54:10 +08:00
*
2023-02-24 09:40:21 +08:00
* The FAST protocol is a proprietary modified JVC protocol without address , with parity and with a shorter header .
2023-02-12 07:23:11 +08:00
* FAST Protocol characteristics :
2023-02-24 09:40:21 +08:00
* - Bit timing is like NEC or JVC
* - The header is shorter , 3156 vs . 12500
* - No address and 16 bit data , interpreted as 8 bit command and 8 bit inverted command ,
* leading to a fixed protocol length of ( 6 + ( 16 * 3 ) + 1 ) * 526 = 55 * 526 = 28930 microseconds or 29 ms .
* - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance .
2021-01-04 09:54:10 +08:00
*
2023-02-12 07:23:11 +08:00
*
2022-08-09 04:39:52 +08:00
* This file is part of IRMP https : //github.com/IRMP-org/IRMP.
2021-03-23 01:04:04 +08:00
* This file is part of Arduino - IRremote https : //github.com/Arduino-IRremote/Arduino-IRremote.
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* MIT License
*
2024-02-15 20:12:12 +08:00
* Copyright ( c ) 2022 - 2024 Armin Joachimsmeyer
2023-02-20 10:22:15 +08:00
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is furnished
* to do so , subject to the following conditions :
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software .
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR IMPLIED ,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY , FITNESS FOR A
* PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER LIABILITY , WHETHER IN AN ACTION OF
* CONTRACT , TORT OR OTHERWISE , ARISING FROM , OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE .
2021-01-04 09:54:10 +08:00
*
2023-02-20 10:22:15 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2021-01-04 09:54:10 +08:00
*/
2022-02-12 02:14:29 +08:00
2022-02-04 07:29:22 +08:00
/*
* This library can be configured at compile time by the following options / macros :
* For more details see : https : //github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down)
*
2023-02-20 10:22:15 +08:00
* - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input .
2022-02-04 07:29:22 +08:00
* - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED .
2022-03-30 17:55:04 +08:00
* - NO_LED_FEEDBACK_CODE Disables the feedback LED function . Saves 14 bytes program memory .
2023-02-20 10:22:15 +08:00
* - DISABLE_PARITY_CHECKS Disable parity checks . Saves 48 bytes of program memory .
2024-02-13 22:46:48 +08:00
* - USE_EXTENDED_NEC_PROTOCOL Like NEC , but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value .
2024-02-15 20:00:20 +08:00
* - USE_ONKYO_PROTOCOL Like NEC , but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value .
2023-02-20 10:22:15 +08:00
* - USE_FAST_PROTOCOL Use FAST protocol ( no address and 16 bit data , interpreted as 8 bit command and 8 bit inverted command ) instead of NEC .
* - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code , send / receive the original frame for repeat .
2023-11-03 05:03:25 +08:00
* - USE_CALLBACK_FOR_TINY_RECEIVER Call the fixed function " void handleReceivedTinyIRData() " each time a frame or repeat is received .
2022-02-04 07:29:22 +08:00
*/
2021-01-04 09:54:10 +08:00
2022-03-30 17:55:04 +08:00
# ifndef _TINY_IR_RECEIVER_HPP
# define _TINY_IR_RECEIVER_HPP
2021-01-20 05:27:07 +08:00
2021-01-04 09:54:10 +08:00
# include <Arduino.h>
2022-11-12 02:53:54 +08:00
# if defined(DEBUG) && !defined(LOCAL_DEBUG)
# define LOCAL_DEBUG
# else
//#define LOCAL_DEBUG // This enables debug output only for this file
# endif
2022-07-27 07:19:00 +08:00
2024-03-16 03:54:05 +08:00
/*
* Protocol selection
*/
2022-11-14 22:00:43 +08:00
//#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory.
2024-02-13 22:11:11 +08:00
//#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
2024-02-13 22:46:48 +08:00
//#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value.
2023-04-17 23:54:24 +08:00
//#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO.
2023-02-20 10:22:15 +08:00
//#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat.
2023-02-12 07:23:11 +08:00
# include "TinyIR.h" // If not defined, it defines IR_RECEIVE_PIN, IR_FEEDBACK_LED_PIN and TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT
2021-03-28 17:35:56 +08:00
2021-10-24 18:38:35 +08:00
# include "digitalWriteFast.h"
2022-11-14 22:00:43 +08:00
/** \addtogroup TinyReceiver Minimal receiver for NEC and FAST protocol
2021-03-18 04:52:41 +08:00
* @ {
*/
2021-10-24 18:38:35 +08:00
2022-07-25 21:09:53 +08:00
# if defined(DEBUG)
# define LOCAL_DEBUG_ATTACH_INTERRUPT
# else
//#define LOCAL_DEBUG_ATTACH_INTERRUPT // to see if attachInterrupt() or static interrupt (by register tweaking) is used
# endif
# if defined(TRACE)
# define LOCAL_TRACE_STATE_MACHINE
# else
2022-11-13 04:42:07 +08:00
//#define LOCAL_TRACE_STATE_MACHINE // to see the state of the ISR (Interrupt Service Routine) state machine
2022-07-25 21:09:53 +08:00
# endif
2021-10-24 18:38:35 +08:00
//#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement.
//#define _IR_TIMING_TEST_PIN 7
2021-01-04 09:54:10 +08:00
TinyIRReceiverStruct TinyIRReceiverControl ;
2023-11-03 05:03:25 +08:00
volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData ;
2021-01-04 09:54:10 +08:00
2021-10-24 18:38:35 +08:00
/*
* Set input pin and output pin definitions etc .
*/
2023-02-12 07:23:11 +08:00
# if defined(IR_INPUT_PIN)
# warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN"
# define IR_RECEIVE_PIN IR_INPUT_PIN
# endif
# if !defined(IR_RECEIVE_PIN)
2022-09-30 06:20:21 +08:00
# if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
2023-02-12 07:23:11 +08:00
# warning "IR_RECEIVE_PIN is not defined, so it is set to 10"
# define IR_RECEIVE_PIN 10
2022-09-30 06:20:21 +08:00
# elif defined(__AVR_ATtiny816__)
2023-02-12 07:23:11 +08:00
# warning "IR_RECEIVE_PIN is not defined, so it is set to 14"
# define IR_RECEIVE_PIN 14
2021-10-24 18:38:35 +08:00
# else
2023-02-12 07:23:11 +08:00
# warning "IR_RECEIVE_PIN is not defined, so it is set to 2"
# define IR_RECEIVE_PIN 2
2021-10-24 18:38:35 +08:00
# endif
# endif
# if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN)
# define IR_FEEDBACK_LED_PIN LED_BUILTIN
# endif
# if !( \
( defined ( __AVR_ATtiny25__ ) | | defined ( __AVR_ATtiny45__ ) | | defined ( __AVR_ATtiny85__ ) ) /* ATtinyX5 */ \
| | defined ( __AVR_ATtiny88__ ) /* MH-ET LIVE Tiny88 */ \
| | defined ( __AVR_ATmega1280__ ) | | defined ( __AVR_ATmega1281__ ) | | defined ( __AVR_ATmega2560__ ) | | defined ( __AVR_ATmega2561__ ) \
| | defined ( __AVR_ATmega16U4__ ) | | defined ( __AVR_ATmega32U4__ ) \
| | defined ( __AVR_ATmega8__ ) | | defined ( __AVR_ATmega48__ ) | | defined ( __AVR_ATmega48P__ ) | | defined ( __AVR_ATmega48PB__ ) | | defined ( __AVR_ATmega88P__ ) | | defined ( __AVR_ATmega88PB__ ) \
| | defined ( __AVR_ATmega168__ ) | | defined ( __AVR_ATmega168PA__ ) | | defined ( __AVR_ATmega168PB__ ) | | defined ( __AVR_ATmega328__ ) | | defined ( __AVR_ATmega328P__ ) | | defined ( __AVR_ATmega328PB__ ) \
/* ATmegas with ports 0,1,2 above and ATtiny167 only 2 pins below */ \
2023-02-12 07:23:11 +08:00
| | ( ( defined ( __AVR_ATtiny87__ ) | | defined ( __AVR_ATtiny167__ ) ) & & ( ( defined ( ARDUINO_AVR_DIGISPARKPRO ) & & ( ( IR_RECEIVE_PIN = = 3 ) | | ( IR_RECEIVE_PIN = = 9 ) ) ) /*ATtinyX7(digisparkpro) and pin 3 or 9 */ \
| | ( ! defined ( ARDUINO_AVR_DIGISPARKPRO ) & & ( ( IR_RECEIVE_PIN = = 3 ) | | ( IR_RECEIVE_PIN = = 14 ) ) ) ) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \
2021-10-24 18:38:35 +08:00
)
# 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.
# endif
2021-03-22 21:44:53 +08:00
/**
* Declaration of the callback function provided by the user application .
2021-03-18 04:52:41 +08:00
* It is called every time a complete IR command or repeat was received .
*/
2023-11-03 05:03:25 +08:00
extern void handleTinyReceivedIRData ( ) ;
2021-01-04 09:54:10 +08:00
2022-11-12 02:53:54 +08:00
# if defined(LOCAL_DEBUG)
uint32_t sMicrosOfGap ; // The length of the gap before the start bit
# endif
2021-03-18 04:52:41 +08:00
/**
2022-11-13 04:42:07 +08:00
* The ISR ( Interrupt Service Routine ) of TinyIRRreceiver .
2021-03-18 04:52:41 +08:00
* It handles the NEC protocol decoding and calls the user callback function on complete .
2021-03-28 17:35:56 +08:00
* 5 us + 3 us for push + pop for a 16 MHz ATmega
2021-03-18 04:52:41 +08:00
*/
2023-05-09 05:22:42 +08:00
# if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
# endif
2022-11-10 07:58:54 +08:00
void IRPinChangeInterruptHandler ( void ) {
2021-10-24 18:38:35 +08:00
# if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
digitalWriteFast ( _IR_TIMING_TEST_PIN , HIGH ) ; // 2 clock cycles
2021-03-28 17:35:56 +08:00
# endif
2021-03-25 21:25:51 +08:00
/*
* Save IR input level
* Negative logic , true / HIGH means inactive / IR space , LOW / false means IR mark .
*/
2023-02-12 07:23:11 +08:00
uint_fast8_t tIRLevel = digitalReadFast ( IR_RECEIVE_PIN ) ;
2021-01-04 09:54:10 +08:00
2021-12-08 21:14:04 +08:00
# if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
2021-01-05 00:15:03 +08:00
digitalWriteFast ( IR_FEEDBACK_LED_PIN , ! tIRLevel ) ;
2021-01-04 09:54:10 +08:00
# endif
/*
* 1. compute microseconds after last change
*/
2022-11-12 02:53:54 +08:00
// Repeats can be sent after a pause, which is longer than 64000 microseconds, so we need a 32 bit value for check of repeats
2021-01-04 09:54:10 +08:00
uint32_t tCurrentMicros = micros ( ) ;
2022-07-27 07:19:00 +08:00
uint32_t tMicrosOfMarkOrSpace32 = tCurrentMicros - TinyIRReceiverControl . LastChangeMicros ;
uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32 ;
2022-11-12 02:53:54 +08:00
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . LastChangeMicros = tCurrentMicros ;
uint8_t tState = TinyIRReceiverControl . IRReceiverState ;
2022-07-25 21:09:53 +08:00
# if defined(LOCAL_TRACE_STATE_MACHINE)
2021-01-04 09:54:10 +08:00
Serial . print ( tState ) ;
2022-07-25 21:09:53 +08:00
Serial . print ( F ( " D= " ) ) ;
Serial . print ( tMicrosOfMarkOrSpace ) ;
2021-01-04 09:54:10 +08:00
// Serial.print(F(" I="));
// Serial.print(tIRLevel);
2022-07-25 21:09:53 +08:00
Serial . print ( ' | ' ) ;
2021-01-04 09:54:10 +08:00
# endif
2022-05-21 00:54:51 +08:00
if ( tIRLevel = = LOW ) {
2021-01-04 09:54:10 +08:00
/*
2021-03-25 21:25:51 +08:00
* We have a mark here
2021-01-04 09:54:10 +08:00
*/
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > 2 * TINY_RECEIVER_HEADER_MARK ) {
2021-01-04 09:54:10 +08:00
// timeout -> must reset state machine
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
2022-05-21 00:54:51 +08:00
if ( tState = = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ) {
2021-03-25 21:25:51 +08:00
// We are at the beginning of the header mark, check timing at the next transition
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE ;
2022-11-12 02:53:54 +08:00
TinyIRReceiverControl . Flags = IRDATA_FLAGS_EMPTY ; // If we do it here, it saves 4 bytes
# if defined(LOCAL_TRACE)
sMicrosOfGap = tMicrosOfMarkOrSpace32 ;
# endif
2023-02-20 10:22:15 +08:00
# if defined(ENABLE_NEC2_REPEATS)
// Check for repeat, where full frame is sent again after TINY_RECEIVER_REPEAT_PERIOD ms
2022-11-12 02:53:54 +08:00
// Not required for NEC, where repeats are detected by a special header space duration
2022-07-27 07:19:00 +08:00
// Must use 32 bit arithmetic here!
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace32 < TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE ) {
2022-11-12 02:53:54 +08:00
TinyIRReceiverControl . Flags = IRDATA_FLAGS_IS_REPEAT ;
}
2022-07-27 07:19:00 +08:00
# endif
2021-01-04 09:54:10 +08:00
}
2022-05-21 00:54:51 +08:00
else if ( tState = = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK ) {
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > = lowerValue25Percent ( TINY_RECEIVER_HEADER_SPACE )
& & tMicrosOfMarkOrSpace < = upperValue25Percent ( TINY_RECEIVER_HEADER_SPACE ) ) {
2021-03-25 21:25:51 +08:00
/*
* We have a valid data header space here - > initialize data
*/
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . IRRawDataBitCounter = 0 ;
2023-02-20 10:22:15 +08:00
# if (TINY_RECEIVER_BITS > 16)
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . IRRawData . ULong = 0 ;
2022-11-12 02:53:54 +08:00
# else
TinyIRReceiverControl . IRRawData . UWord = 0 ;
# endif
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . IRRawDataMask = 1 ;
2021-03-25 21:25:51 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ;
2023-02-20 10:22:15 +08:00
# if !defined(ENABLE_NEC2_REPEATS)
2022-11-12 02:53:54 +08:00
// Check for NEC repeat header
2022-05-21 00:54:51 +08:00
} else if ( tMicrosOfMarkOrSpace > = lowerValue25Percent ( NEC_REPEAT_HEADER_SPACE )
2021-03-25 21:25:51 +08:00
& & tMicrosOfMarkOrSpace < = upperValue25Percent ( NEC_REPEAT_HEADER_SPACE )
2023-02-20 10:22:15 +08:00
& & TinyIRReceiverControl . IRRawDataBitCounter > = TINY_RECEIVER_BITS ) {
2021-03-25 21:25:51 +08:00
/*
* We have a repeat header here and no broken receive before - > set repeat flag
*/
2022-11-12 02:53:54 +08:00
TinyIRReceiverControl . Flags = IRDATA_FLAGS_IS_REPEAT ;
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ;
2022-11-12 02:53:54 +08:00
# endif
2022-05-21 00:54:51 +08:00
} else {
2021-01-04 09:54:10 +08:00
// This parts are optimized by the compiler into jumps to one code :-)
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
}
2022-05-21 00:54:51 +08:00
else if ( tState = = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK ) {
2021-01-04 09:54:10 +08:00
// Check data space length
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > = lowerValue50Percent ( TINY_RECEIVER_ZERO_SPACE )
& & tMicrosOfMarkOrSpace < = upperValue50Percent ( TINY_RECEIVER_ONE_SPACE ) ) {
2021-03-25 21:25:51 +08:00
// We have a valid bit here
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ;
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > = 2 * TINY_RECEIVER_UNIT ) {
2021-01-04 09:54:10 +08:00
// we received a 1
2023-02-20 10:22:15 +08:00
# if (TINY_RECEIVER_BITS > 16)
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . IRRawData . ULong | = TinyIRReceiverControl . IRRawDataMask ;
2022-11-12 02:53:54 +08:00
# else
TinyIRReceiverControl . IRRawData . UWord | = TinyIRReceiverControl . IRRawDataMask ;
# endif
2022-05-21 00:54:51 +08:00
} else {
2021-03-25 21:25:51 +08:00
// we received a 0 - empty code for documentation
2021-01-04 09:54:10 +08:00
}
2021-03-25 21:25:51 +08:00
// prepare for next bit
2021-01-04 09:54:10 +08:00
TinyIRReceiverControl . IRRawDataMask = TinyIRReceiverControl . IRRawDataMask < < 1 ;
TinyIRReceiverControl . IRRawDataBitCounter + + ;
2022-05-21 00:54:51 +08:00
} else {
2021-01-04 09:54:10 +08:00
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
2022-05-21 00:54:51 +08:00
} else {
2021-03-28 17:35:56 +08:00
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
}
2022-05-21 00:54:51 +08:00
else {
2021-01-04 09:54:10 +08:00
/*
2021-03-25 21:25:51 +08:00
* We have a space here
2021-01-04 09:54:10 +08:00
*/
2022-05-21 00:54:51 +08:00
if ( tState = = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE ) {
2021-03-25 21:25:51 +08:00
/*
* Check length of header mark here
*/
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > = lowerValue25Percent ( TINY_RECEIVER_HEADER_MARK )
& & tMicrosOfMarkOrSpace < = upperValue25Percent ( TINY_RECEIVER_HEADER_MARK ) ) {
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK ;
2022-05-21 00:54:51 +08:00
} else {
2021-03-25 21:25:51 +08:00
// Wrong length of header mark -> reset state
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
}
2022-05-21 00:54:51 +08:00
else if ( tState = = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ) {
2021-03-25 21:25:51 +08:00
// Check data mark length
2023-02-20 10:22:15 +08:00
if ( tMicrosOfMarkOrSpace > = lowerValue50Percent ( TINY_RECEIVER_BIT_MARK )
& & tMicrosOfMarkOrSpace < = upperValue50Percent ( TINY_RECEIVER_BIT_MARK ) ) {
2021-03-25 21:25:51 +08:00
/*
2022-07-27 07:19:00 +08:00
* We have a valid mark here , check for transmission complete , i . e . the mark of the stop bit
2021-03-25 21:25:51 +08:00
*/
2023-02-20 10:22:15 +08:00
if ( TinyIRReceiverControl . IRRawDataBitCounter > = TINY_RECEIVER_BITS
# if !defined(ENABLE_NEC2_REPEATS)
2022-11-12 02:53:54 +08:00
| | ( TinyIRReceiverControl . Flags & IRDATA_FLAGS_IS_REPEAT ) // Do not check for full length received, if we have a short repeat frame
# endif
2022-11-14 22:00:43 +08:00
) {
2021-01-04 09:54:10 +08:00
/*
2023-02-20 10:22:15 +08:00
* Code complete - > optionally check parity
2021-01-04 09:54:10 +08:00
*/
2021-03-25 21:25:51 +08:00
// Reset state for new start
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
2023-02-12 07:23:11 +08:00
2023-02-20 10:22:15 +08:00
# if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
2021-01-18 20:44:30 +08:00
/*
2022-11-12 02:53:54 +08:00
* Check address parity
* Address is sent first and contained in the lower word
2021-01-18 20:44:30 +08:00
*/
2022-11-12 02:53:54 +08:00
if ( TinyIRReceiverControl . IRRawData . UBytes [ 0 ] ! = ( uint8_t ) ( ~ TinyIRReceiverControl . IRRawData . UBytes [ 1 ] ) ) {
2023-02-24 09:40:21 +08:00
# if defined(ENABLE_NEC2_REPEATS)
2023-11-03 05:03:25 +08:00
TinyIRReceiverControl . Flags | = IRDATA_FLAGS_PARITY_FAILED ; // here we can have the repeat flag already set
2023-02-24 09:40:21 +08:00
# else
TinyIRReceiverControl . Flags = IRDATA_FLAGS_PARITY_FAILED ; // here we do not check anything, if we have a repeat
# endif
2021-01-18 20:44:30 +08:00
}
2022-11-12 02:53:54 +08:00
# endif
2023-02-20 10:22:15 +08:00
# if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
2022-11-12 02:53:54 +08:00
/*
* Check command parity
*/
2023-02-20 10:22:15 +08:00
# if (TINY_RECEIVER_ADDRESS_BITS > 0)
2022-11-12 02:53:54 +08:00
if ( TinyIRReceiverControl . IRRawData . UBytes [ 2 ] ! = ( uint8_t ) ( ~ TinyIRReceiverControl . IRRawData . UBytes [ 3 ] ) ) {
2023-02-24 09:40:21 +08:00
# if defined(ENABLE_NEC2_REPEATS)
2023-11-03 05:03:25 +08:00
TinyIRReceiverControl . Flags | = IRDATA_FLAGS_PARITY_FAILED ;
2023-02-24 09:40:21 +08:00
# else
TinyIRReceiverControl . Flags = IRDATA_FLAGS_PARITY_FAILED ;
# endif
2022-11-12 02:53:54 +08:00
# if defined(LOCAL_DEBUG)
2023-11-03 05:03:25 +08:00
Serial . print ( F ( " Parity check for command failed. Command= " ) ) ;
Serial . print ( TinyIRReceiverControl . IRRawData . UBytes [ 2 ] , HEX ) ;
Serial . print ( F ( " parity= " ) ) ;
Serial . println ( TinyIRReceiverControl . IRRawData . UBytes [ 3 ] , HEX ) ;
2022-11-12 02:53:54 +08:00
# endif
# else
// No address, so command and parity are in the lowest bytes
if ( TinyIRReceiverControl . IRRawData . UBytes [ 0 ] ! = ( uint8_t ) ( ~ TinyIRReceiverControl . IRRawData . UBytes [ 1 ] ) ) {
TinyIRReceiverControl . Flags | = IRDATA_FLAGS_PARITY_FAILED ;
# if defined(LOCAL_DEBUG)
Serial . print ( F ( " Parity check for command failed. Command= " ) ) ;
Serial . print ( TinyIRReceiverControl . IRRawData . UBytes [ 0 ] , HEX ) ;
Serial . print ( F ( " parity= " ) ) ;
Serial . println ( TinyIRReceiverControl . IRRawData . UBytes [ 1 ] , HEX ) ;
# endif
# endif
}
# endif
2021-03-25 21:25:51 +08:00
/*
* Call user provided callback here
2023-02-12 07:23:11 +08:00
* The parameter size is dependent of the code variant used in order to save program memory .
2022-11-12 02:53:54 +08:00
* We have 6 cases : 0 , 8 bit or 16 bit address , each with 8 or 16 bit command
2021-03-25 21:25:51 +08:00
*/
2023-02-12 07:23:11 +08:00
# if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. in callback for ESP -> no interrupt required, WDT is running!
interrupts ( ) ; // enable interrupts, so delay() etc. works in callback
# endif
2023-11-03 05:03:25 +08:00
TinyIRReceiverData . justWritten = true ;
TinyIRReceiverData . Flags = TinyIRReceiverControl . Flags ;
2023-02-20 10:22:15 +08:00
# if (TINY_RECEIVER_ADDRESS_BITS > 0)
# if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY
2023-11-03 05:03:25 +08:00
// Here we have 8 bit address
TinyIRReceiverData . Address = TinyIRReceiverControl . IRRawData . UBytes [ 0 ] ;
2022-11-12 02:53:54 +08:00
# else
2023-11-03 05:03:25 +08:00
// Here we have 16 bit address
TinyIRReceiverData . Address = TinyIRReceiverControl . IRRawData . UWord . LowWord ;
2022-11-12 02:53:54 +08:00
# endif
2023-02-20 10:22:15 +08:00
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
2023-11-03 05:03:25 +08:00
// Here we have 8 bit command
TinyIRReceiverData . Command = TinyIRReceiverControl . IRRawData . UBytes [ 2 ] ;
2022-11-12 02:53:54 +08:00
# else
// Here we have 16 bit command
2023-11-03 05:03:25 +08:00
TinyIRReceiverData . Command = TinyIRReceiverControl . IRRawData . UWord . HighWord ;
2022-11-12 02:53:54 +08:00
# endif
2023-11-03 05:03:25 +08:00
# else
// Here we have NO address
2023-02-20 10:22:15 +08:00
# if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY
2023-11-03 05:03:25 +08:00
// Here we have 8 bit command
TinyIRReceiverData . Command = TinyIRReceiverControl . IRRawData . UBytes [ 0 ] ;
2022-11-12 02:53:54 +08:00
# else
2023-11-03 05:03:25 +08:00
// Here we have 16 bit command
TinyIRReceiverData . Command = TinyIRReceiverControl . IRRawData . UWord ;
2022-11-12 02:53:54 +08:00
# endif
2022-07-27 07:19:00 +08:00
# endif
2023-11-03 05:03:25 +08:00
# if defined(USE_CALLBACK_FOR_TINY_RECEIVER)
handleReceivedTinyIRData ( ) ;
# endif
2021-01-04 09:54:10 +08:00
2022-05-21 00:54:51 +08:00
} else {
2021-03-25 21:25:51 +08:00
// not finished yet
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK ;
}
2022-05-21 00:54:51 +08:00
} else {
2021-01-04 09:54:10 +08:00
// Wrong length -> reset state
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
2022-05-21 00:54:51 +08:00
} else {
2021-03-28 17:35:56 +08:00
// error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
2021-01-04 09:54:10 +08:00
tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ;
}
}
TinyIRReceiverControl . IRReceiverState = tState ;
2021-10-24 18:38:35 +08:00
# ifdef _IR_MEASURE_TIMING
digitalWriteFast ( _IR_TIMING_TEST_PIN , LOW ) ; // 2 clock cycles
2021-03-28 17:35:56 +08:00
# endif
2021-01-04 09:54:10 +08:00
}
2022-05-21 00:54:51 +08:00
bool isTinyReceiverIdle ( ) {
2021-10-07 15:25:36 +08:00
return ( TinyIRReceiverControl . IRReceiverState = = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ) ;
}
2024-02-13 22:46:48 +08:00
/*
* Checks if IR_RECEIVE_PIN is connected and high
* @ return true , if IR Receiver is attached
*/
bool isIRReceiverAttachedForTinyReceiver ( ) {
pinModeFast ( IR_RECEIVE_PIN , OUTPUT ) ;
digitalWriteFast ( IR_RECEIVE_PIN , LOW ) ; // discharge pin capacity
pinModeFast ( IR_RECEIVE_PIN , INPUT ) ;
return digitalRead ( IR_RECEIVE_PIN ) ; // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast.
}
2021-03-22 21:44:53 +08:00
/**
2023-02-12 07:23:11 +08:00
* Sets IR_RECEIVE_PIN mode to INPUT , and if IR_FEEDBACK_LED_PIN is defined , sets feedback LED output mode .
2022-11-08 07:36:44 +08:00
* Then call enablePCIInterruptForTinyReceiver ( )
2021-03-22 21:44:53 +08:00
*/
2022-07-30 16:26:04 +08:00
bool initPCIInterruptForTinyReceiver ( ) {
2023-02-12 07:23:11 +08:00
pinModeFast ( IR_RECEIVE_PIN , INPUT ) ;
2021-01-04 09:54:10 +08:00
2021-12-08 21:14:04 +08:00
# if !defined(NO_LED_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN)
2021-01-05 00:15:03 +08:00
pinModeFast ( IR_FEEDBACK_LED_PIN , OUTPUT ) ;
2021-01-04 09:54:10 +08:00
# endif
2022-07-30 16:26:04 +08:00
return enablePCIInterruptForTinyReceiver ( ) ;
2021-08-08 03:25:44 +08:00
}
2023-11-03 05:03:25 +08:00
void printTinyReceiverResultMinimal ( Print * aSerial ) {
2022-11-12 02:53:54 +08:00
// Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
// Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon
2023-02-12 07:23:11 +08:00
# if defined(USE_FAST_PROTOCOL)
2022-11-12 02:53:54 +08:00
aSerial - > print ( F ( " C=0x " ) ) ;
# else
aSerial - > print ( F ( " A=0x " ) ) ;
2023-11-03 05:03:25 +08:00
aSerial - > print ( TinyIRReceiverData . Address , HEX ) ;
2022-11-12 02:53:54 +08:00
aSerial - > print ( F ( " C=0x " ) ) ;
# endif
2023-11-03 05:03:25 +08:00
aSerial - > print ( TinyIRReceiverData . Command , HEX ) ;
if ( TinyIRReceiverData . Flags = = IRDATA_FLAGS_IS_REPEAT ) {
2022-11-12 02:53:54 +08:00
aSerial - > print ( F ( " R " ) ) ;
}
# if !defined(DISABLE_PARITY_CHECKS)
2023-11-03 05:03:25 +08:00
if ( TinyIRReceiverData . Flags = = IRDATA_FLAGS_PARITY_FAILED ) {
2022-11-12 02:53:54 +08:00
aSerial - > print ( F ( " P " ) ) ;
}
# endif
aSerial - > println ( ) ;
}
2022-07-25 21:09:53 +08:00
# if defined (LOCAL_DEBUG_ATTACH_INTERRUPT) && !defined(STR)
2021-11-29 20:41:03 +08:00
// Helper macro for getting a macro definition as string
# define STR_HELPER(x) #x
# define STR(x) STR_HELPER(x)
# endif
2021-01-04 09:54:10 +08:00
2022-07-30 16:26:04 +08:00
/**************************************************
* Pin to interrupt mapping for different platforms
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2022-09-30 06:20:21 +08:00
# if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
2022-07-30 16:26:04 +08:00
# define USE_ATTACH_INTERRUPT_DIRECT
2021-01-18 20:44:30 +08:00
2021-03-23 01:04:04 +08:00
# elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
2022-07-30 16:26:04 +08:00
// Default for all NON AVR platforms
# define USE_ATTACH_INTERRUPT
2021-01-04 09:54:10 +08:00
# else
# if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
2022-07-30 16:26:04 +08:00
# define USE_PCIE
2021-01-04 09:54:10 +08:00
# elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
# if defined(ARDUINO_AVR_DIGISPARKPRO)
2023-02-12 07:23:11 +08:00
# if (IR_RECEIVE_PIN == 3)
2022-07-30 16:26:04 +08:00
# define USE_INT0
2023-02-12 07:23:11 +08:00
# elif (IR_RECEIVE_PIN == 9)
2022-07-30 16:26:04 +08:00
# define USE_INT1
2021-01-04 09:54:10 +08:00
# else
2023-02-12 07:23:11 +08:00
# error "IR_RECEIVE_PIN must be 9 or 3."
# endif // if (IR_RECEIVE_PIN == 9)
2021-01-04 09:54:10 +08:00
# else // defined(ARDUINO_AVR_DIGISPARKPRO)
2023-02-12 07:23:11 +08:00
# if (IR_RECEIVE_PIN == 14)
2022-07-30 16:26:04 +08:00
# define USE_INT0
2023-02-12 07:23:11 +08:00
# elif (IR_RECEIVE_PIN == 3)
2022-07-30 16:26:04 +08:00
# define USE_INT1
2021-01-04 09:54:10 +08:00
# else
2023-02-12 07:23:11 +08:00
# error "IR_RECEIVE_PIN must be 14 or 3."
# endif // if (IR_RECEIVE_PIN == 14)
2021-01-04 09:54:10 +08:00
# endif
2022-07-30 16:26:04 +08:00
# elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
2023-02-12 07:23:11 +08:00
# if (IR_RECEIVE_PIN == 21)
2022-07-30 16:26:04 +08:00
# define USE_INT0
2023-02-12 07:23:11 +08:00
# elif (IR_RECEIVE_PIN == 20)
2022-07-30 16:26:04 +08:00
# define USE_INT1
2022-08-06 20:39:28 +08:00
# else
2023-02-12 07:23:11 +08:00
# warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
2022-08-06 20:39:28 +08:00
# define USE_ATTACH_INTERRUPT
2022-07-30 16:26:04 +08:00
# endif
2021-01-04 09:54:10 +08:00
# else // defined(__AVR_ATtiny25__)
2022-07-30 16:26:04 +08:00
/*
* ATmegas + ATtiny88 here
*/
2023-02-12 07:23:11 +08:00
# if (IR_RECEIVE_PIN == 2)
2022-07-30 16:26:04 +08:00
# define USE_INT0
2023-02-12 07:23:11 +08:00
# elif (IR_RECEIVE_PIN == 3)
2022-07-30 16:26:04 +08:00
# define USE_INT1
2023-02-12 07:23:11 +08:00
# elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7
2021-01-04 09:54:10 +08:00
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7)
2022-07-30 16:26:04 +08:00
# define USE_PCINT2
2023-02-12 07:23:11 +08:00
# 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
2021-01-04 09:54:10 +08:00
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13)
2022-07-30 16:26:04 +08:00
# define USE_PCINT0
2023-02-12 07:23:11 +08:00
# 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
2021-01-04 09:54:10 +08:00
//ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5)
2022-07-30 16:26:04 +08:00
# define USE_PCINT1
2021-01-04 09:54:10 +08:00
# else
2023-02-12 07:23:11 +08:00
# warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now."
2022-07-30 16:26:04 +08:00
# define USE_ATTACH_INTERRUPT
2023-02-12 07:23:11 +08:00
# endif // if (IR_RECEIVE_PIN == 2)
2021-01-04 09:54:10 +08:00
# endif // defined(__AVR_ATtiny25__)
2021-03-23 01:04:04 +08:00
# endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT)
2021-01-04 09:54:10 +08:00
2022-07-30 16:26:04 +08:00
/**
2023-02-12 07:23:11 +08:00
* Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt ( ) function .
2022-09-28 17:17:04 +08:00
* @ return true if interrupt was successfully enabled
2022-07-30 16:26:04 +08:00
*/
bool enablePCIInterruptForTinyReceiver ( ) {
2021-10-24 18:38:35 +08:00
# if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast ( _IR_TIMING_TEST_PIN , OUTPUT ) ;
2021-08-08 03:25:44 +08:00
# endif
2022-07-30 16:26:04 +08:00
# if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
# if defined(USE_ATTACH_INTERRUPT)
# if defined(NOT_AN_INTERRUPT)
2023-02-12 07:23:11 +08:00
if ( digitalPinToInterrupt ( IR_RECEIVE_PIN ) = = NOT_AN_INTERRUPT ) {
2022-07-30 16:26:04 +08:00
return false ;
}
# endif
2022-11-14 22:00:43 +08:00
// costs 112 bytes program memory + 4 bytes RAM
2023-02-12 07:23:11 +08:00
attachInterrupt ( digitalPinToInterrupt ( IR_RECEIVE_PIN ) , IRPinChangeInterruptHandler , CHANGE ) ;
2022-07-30 16:26:04 +08:00
# else
// 2.2 us more than version configured with macros and not compatible
2023-02-12 07:23:11 +08:00
attachInterrupt ( IR_RECEIVE_PIN , IRPinChangeInterruptHandler , CHANGE ) ; // no extra pin mapping here
2022-07-30 16:26:04 +08:00
# endif
2021-08-08 03:25:44 +08:00
2022-07-30 16:26:04 +08:00
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
2023-02-12 07:23:11 +08:00
Serial . println ( F ( " Use attachInterrupt for pin= " STR ( IR_RECEIVE_PIN ) ) ) ;
2022-07-30 16:26:04 +08:00
# endif
2021-08-08 03:25:44 +08:00
2022-07-30 16:26:04 +08:00
# else
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
2023-02-12 07:23:11 +08:00
Serial . println ( F ( " Use static interrupt for pin= " STR ( IR_RECEIVE_PIN ) ) ) ;
2022-07-30 16:26:04 +08:00
# endif
# if defined(USE_INT0)
// interrupt on any logical change
EICRA | = _BV ( ISC00 ) ;
2021-08-08 03:25:44 +08:00
// clear interrupt bit
EIFR | = 1 < < INTF0 ;
2022-07-30 16:26:04 +08:00
// enable interrupt on next change
EIMSK | = 1 < < INT0 ;
# elif defined(USE_INT1)
EICRA | = _BV ( ISC10 ) ;
// clear interrupt bit
2021-08-08 03:25:44 +08:00
EIFR | = 1 < < INTF1 ;
2022-07-30 16:26:04 +08:00
// enable interrupt on next change
EIMSK | = 1 < < INT1 ;
2021-08-08 03:25:44 +08:00
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCIE) // For ATtiny85 etc.
// use PinChangeInterrupt no INT0 for pin PB2
2023-02-12 07:23:11 +08:00
PCMSK = _BV ( IR_RECEIVE_PIN ) ;
2022-07-30 16:26:04 +08:00
// clear interrupt bit
GIFR | = 1 < < PCIF ;
// enable interrupt on next change
GIMSK | = 1 < < PCIE ;
# elif defined(USE_PCINT0)
PCICR | = _BV ( PCIE0 ) ;
2023-02-12 07:23:11 +08:00
PCMSK0 = digitalPinToBitMask ( IR_RECEIVE_PIN ) ;
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCINT1)
PCICR | = _BV ( PCIE1 ) ;
2023-02-12 07:23:11 +08:00
PCMSK1 = digitalPinToBitMask ( IR_RECEIVE_PIN ) ;
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCINT2)
PCICR | = _BV ( PCIE2 ) ;
2023-02-12 07:23:11 +08:00
PCMSK2 = digitalPinToBitMask ( IR_RECEIVE_PIN ) ;
2022-07-30 16:26:04 +08:00
# else
return false ;
# endif
# endif // defined(USE_ATTACH_INTERRUPT)
return true ;
}
void disablePCIInterruptForTinyReceiver ( ) {
# if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN)
pinModeFast ( _IR_TIMING_TEST_PIN , OUTPUT ) ;
# endif
# if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)
# if defined(USE_ATTACH_INTERRUPT)
2023-02-12 07:23:11 +08:00
detachInterrupt ( digitalPinToInterrupt ( IR_RECEIVE_PIN ) ) ;
2022-07-30 16:26:04 +08:00
# else
2023-02-12 07:23:11 +08:00
detachInterrupt ( IR_RECEIVE_PIN ) ;
2022-07-30 16:26:04 +08:00
# endif
# else
# if defined(USE_INT0)
2021-08-08 03:25:44 +08:00
// clear interrupt bit
EIFR | = 1 < < INTF0 ;
// disable interrupt on next change
EIMSK & = ~ ( 1 < < INT0 ) ;
2022-07-30 16:26:04 +08:00
# elif defined(USE_INT1)
2021-08-08 03:25:44 +08:00
// clear interrupt bit
EIFR | = 1 < < INTF1 ;
// disable interrupt on next change
EIMSK & = ~ ( 1 < < INT1 ) ;
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCIE) // For ATtiny85 etc.
2021-08-08 03:25:44 +08:00
// clear interrupt bit
2022-07-30 16:26:04 +08:00
GIFR | = 1 < < PCIF ;
2021-08-08 03:25:44 +08:00
// disable interrupt on next change
2022-07-30 16:26:04 +08:00
GIMSK & = ~ ( 1 < < PCIE ) ;
# elif defined(USE_PCINT0)
PCICR & = ~ ( _BV ( PCIE0 ) ) ;
# elif defined(USE_PCINT1)
PCICR & = ~ ( _BV ( PCIE1 ) ) ;
# elif defined(USE_PCINT2)
PCICR & = ~ ( _BV ( PCIE2 ) ) ;
# endif
# endif // defined(USE_ATTACH_INTERRUPT)
2021-08-08 03:25:44 +08:00
}
2021-03-11 18:28:41 +08:00
/*
2021-03-23 01:04:04 +08:00
* Specify the right INT0 , INT1 or PCINT0 interrupt vector according to different pins and cores .
* The default value of TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT is set in TinyIRReceiver . h
2021-03-11 18:28:41 +08:00
*/
2022-07-30 16:26:04 +08:00
# if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
# if defined(USE_INT0)
ISR ( INT0_vect )
2021-01-04 09:54:10 +08:00
2022-07-30 16:26:04 +08:00
# elif defined(USE_INT1)
2021-01-04 09:54:10 +08:00
ISR ( INT1_vect )
2021-03-11 18:28:41 +08:00
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCIE) // For ATtiny85 etc.
2021-03-11 18:28:41 +08:00
// on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect
ISR ( PCINT0_vect )
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCINT0)
2021-01-04 09:54:10 +08:00
ISR ( PCINT0_vect )
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCINT1)
2021-01-04 09:54:10 +08:00
ISR ( PCINT1_vect )
2022-07-30 16:26:04 +08:00
# elif defined(USE_PCINT2)
ISR ( PCINT2_vect )
2022-08-06 20:39:28 +08:00
# else
void dummyFunctionToAvoidCompilerErrors ( )
2021-03-11 18:28:41 +08:00
# endif
2021-01-04 09:54:10 +08:00
{
IRPinChangeInterruptHandler ( ) ;
}
2022-07-30 16:26:04 +08:00
# endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT))
2021-01-20 05:27:07 +08:00
2021-03-18 04:52:41 +08:00
/** @}*/
2021-01-20 05:27:07 +08:00
2022-07-25 21:09:53 +08:00
# if defined(LOCAL_DEBUG_ATTACH_INTERRUPT)
# undef LOCAL_DEBUG_ATTACH_INTERRUPT
# endif
# if defined(LOCAL_TRACE_STATE_MACHINE)
# undef LOCAL_TRACE_STATE_MACHINE
# endif
2022-11-12 02:53:54 +08:00
# if defined(LOCAL_DEBUG)
# undef LOCAL_DEBUG
# endif
2022-03-30 17:55:04 +08:00
# endif // _TINY_IR_RECEIVER_HPP