#defineCLOCKS_PER_MICRO48// just a guess if F_CPU is not specified
#endif
/*
* For backwards compatibility
*/
#if defined(SYSCLOCK) // allow for processor specific code to define F_CPU
#undef F_CPU
#defineF_CPUSYSCLOCK// Clock frequency to be used for timing.
#endif
//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
//#define TRACE // Activate this for more debug output.
/**
* The RAW_BUFFER_LENGTH determines the length of the byte buffer where the received IR timing data is stored before decoding.
* 100 is sufficient for standard protocols up to 48 bits, with 1 bit consisting of one mark and space plus 1 byte for initial gap, 2 bytes for header and 1 byte for stop bit.
* 48 bit protocols are PANASONIC, KASEIKYO, SAMSUNG48, RC6.
* 32 bit protocols like NEC, SAMSUNG, WHYNTER, SONY(20), LG(28) requires a buffer length of 68.
* 16 bit protocols like BOSEWAVE, DENON, FAST, JVC, LEGO_PF, RC5, SONY(12 or 15) requires a buffer length of 36.
* MAGIQUEST requires a buffer length of 112.
* Air conditioners often send a longer protocol data stream up to 750 bits.
* Default is 100 for 512 bytes RAM, 200 for 2k RAM and 750 for more than 2k RAM
*/
#if !defined(RAW_BUFFER_LENGTH)
# if (defined(RAMSIZE) && RAMSIZE <= 0x200) || (defined(RAMEND) && RAMEND <= 0x2FF) // assuming RAMSTART at 0x100
// For RAMSIZE <= 512 bytes
#defineRAW_BUFFER_LENGTH100///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
#defineRAW_BUFFER_LENGTH200///< Length of raw duration buffer. Must be even. 100 supports up to 48 bit codings inclusive 1 start and 1 stop bit.
# else
// For undefined or bigger RAMsize
#defineRAW_BUFFER_LENGTH750// The value required for air condition remotes.
# endif
#endif
#if RAW_BUFFER_LENGTH % 2 == 1
#error RAW_BUFFER_LENGTH must be even, since the array consists of space / mark pairs.
#endif
#if RAW_BUFFER_LENGTH <= 254 // saves around 75 bytes program memory and speeds up ISR
typedefuint_fast8_t IRRawlenType;
#else
typedefunsignedint IRRawlenType;
#endif
/*
* We store IR timing values in an 8-bit buffer, where each unit represents 50 ticks.
* Since 8 bits can hold values from 0 to 255, the maximum measurable timing is 255 × 50 ticks = 12750 us.
*
* This means:
* - Any timing up to 12750 us is stored accurately.
* - Any timing greater than 12750 us is clipped and stored as 12750 us.
* - Therefore, you can detect that a timing exceeded 12750 us (because it appears as 12750 us).
* - However, you cannot distinguish between two different timings if both are greater than 12750 us — they will both appear as the same maximum value.
*
* For decoding purposes, 8 bits are acceptable as long as the protocol does not require distinguishing between two different timings
* that are both longer than 12750 us.
* As I am not currently (02/2026) aware of any protocols that require this, we use 8 bits.
* Use a 16-bit buffer if raw timing capture is required and exact values above 12750 us must be preserved.
*/
#if !defined(USE_16_BIT_TIMING_BUFFER) // Use uint16_t buffer for timing. Doubles the RAM requirement. this can be used to override our selection of 8 the bit array
typedefuint8_t IRRawbufType; // all timings up to 12750 us fit into 8 bit (for MICROS_PER_TICK == 50).
#defineIR_REC_STATE_IDLE0// Counting the gap time and waiting for the start bit to arrive
#defineIR_REC_STATE_MARK1// A mark was received and we are counting the duration of it.
#defineIR_REC_STATE_SPACE2// A space was received and we are counting the duration of it. If space is too long, we assume end of frame.
#defineIR_REC_STATE_STOP3// Stopped until set to IR_REC_STATE_IDLE which can only be done by resume()
/**
* This struct contains the data and control used for receiver functions and the ISR (interrupt service routine)
* Only StateForISR needs to be volatile. All the other fields are not written by ISR after available() == true and before start() / resume().
*/
structirparams_struct {
// The fields are ordered to reduce memory overflow caused by struct-padding
volatileuint8_t StateForISR; ///< State Machine state
uint_fast8_t IRReceivePin; ///< Pin connected to IR data from detector
#if defined(__AVR__)
volatileuint8_t *IRReceivePinPortInputRegister;
uint8_t IRReceivePinMask;
#endif
volatileuint_fast16_t TickCounterForISR; ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition. Counting is independent of state or resume().
void (*ReceiveCompleteCallbackFunction)(void); ///< The function to call if a protocol message has arrived, i.e. StateForISR changed to IR_REC_STATE_STOP
// Static variables for the getBiphaselevel() function
uint_fast8_t RawbuffOffsetForNextBiphaseLevel; // Index into raw timing array
uint16_t NumberOfTimingIntervalsInCurrentInterval; // 1, 2 or 3. Number of aBiphaseTimeUnit intervals of the current rawbuf[RawbuffOffsetForNextBiphaseLevel] timing.
uint_fast8_t AlreadyUsedTimingIntervalsOfCurrentInterval; // Number of already used intervals of sCurrentTimingIntervals.
uint16_t BiphaseTimeUnit;
#endif
bool OverflowFlag; ///< Raw buffer OverflowFlag occurred
IRRawlenType rawlen; ///< counter of entries in rawbuf
uint16_t initialGapTicks; ///< Tick counts of the length of the gap between previous and current IR frame. Pre 4.4: rawbuf[0].
IRRawbufType rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space. With 8 bit we can only store up to 12.7 ms. First entry is empty to be backwards compatible.
};
#if (__INT_WIDTH__ < 32)
typedefuint32_t IRDecodedRawDataType;
#defineBITS_IN_DECODED_RAW_DATA_TYPE32
#else
typedefuint64_t IRDecodedRawDataType;
#defineBITS_IN_DECODED_RAW_DATA_TYPE64
#endif
typedef IRDecodedRawDataType IRRawDataType; // Define old IRRawDataType (removed in 4.6.0) for backward compatibility
#defineDECODED_RAW_DATA_ARRAY_SIZE ((((RAW_BUFFER_LENGTH - 2) - 1) / (2 * BITS_IN_DECODED_RAW_DATA_TYPE)) + 1) // The -2 is for initial gap + stop bit mark, 128 mark + spaces for 64 bit.
/**
* Data structure for the user application, available as decodedIRData.
* Filled by decoders and read by print functions or user application.
IRDecodedRawDataType decodedRawDataArray[DECODED_RAW_DATA_ARRAY_SIZE]; ///< 32/64 bit decoded raw data, to be used for sendPulseDistanceWidthFromArray functions.
#endif
uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
uint8_t flags; ///< IRDATA_FLAGS_IS_REPEAT, IRDATA_FLAGS_WAS_OVERFLOW etc. See IRDATA_FLAGS_* definitions above
/*
* These 2 variables allow to call resume() directly after decode.
* After resume(), irparams.initialGapTicks and irparams.rawlen are
* the first variables, which are overwritten by the next received frame.
* since 4.3.0.
*/
IRRawlenType rawlen; ///< Counter of entries in rawbuf of last received frame.
uint16_t initialGapTicks; ///< Contains the initial gap (pre 4.4: the value in rawbuf[0]) of the last received frame.
#defineTOLERANCE_FOR_DECODERS_MARK_OR_SPACE_MATCHING_PERCENT25// Relative tolerance (in percent) for matchTicks(), matchMark() and matchSpace() functions used for protocol decoding.
#defineSEND_REPEAT_COMMANDtrue///< used for e.g. NEC, where a repeat is different from just repeating the data.
/**
* Main class for sending IR signals
*/
classIRsend {
public:
IRsend();
/*
* IR_SEND_PIN is defined or fixed by timer, value of IR_SEND_PIN is then "DeterminedByTimer"
*/
#if defined(IR_SEND_PIN)
voidbegin();
// The default parameter allowed to specify IrSender.begin(7); without errors, if IR_SEND_PIN was defined. But the semantics is not the one the user expect.
voidbegin(uint_fast8_t aFeedbackLEDPin);
#else
IRsend(uint_fast8_t aSendPin);
voidbegin(uint_fast8_t aSendPin);
voidsetSendPin(uint_fast8_t aSendPin); // required if we use IRsend() as constructor
#endif
voidbegin(uint_fast8_t aSendPin, uint_fast8_t aFeedbackLEDPin); // aFeedbackLEDPin is by default USE_DEFAULT_FEEDBACK_LED_PIN
__attribute__ ((deprecated ("The function sendDenon(data, nbits) is deprecated and may not work as expected! Use sendDenonRaw(data, NumberOfRepeats) or better sendDenon(Address, Command, NumberOfRepeats).")));
voidsendDish(uint16_t aData);
voidsendJVC(unsignedlong data, int nbits,
bool repeat)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendJVC(aAddress, aCommand, aNumberOfRepeats)."))) {
sendJVCMSB(data, nbits, repeat);
}
voidsendJVCMSB(unsignedlong data, int nbits, bool repeat = false);
voidsendLG(unsignedlong data,
int nbits)
__attribute__ ((deprecated ("The function sendLG(data, nbits) is deprecated and may not work as expected! Use sendLGRaw(data, NumberOfRepeats) or better sendLG(Address, Command, NumberOfRepeats).")));
voidsendNEC(uint32_t aRawData,
uint8_t nbits)
__attribute__ ((deprecated ("This old function sends MSB first! Please use sendNECMSB() or sendNEC(aAddress, aCommand, aNumberOfRepeats)."))) {