Infrarot/Remote2/SimpleIRReceiver.h
void IRPinChangeInterruptHandler(void) {
    /*
     * Save IR input level
     * Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark.
     */
    uint_fast8_t tIRLevel = digitalReadFast(ir_input_pin);

    /*
     * 1. compute microseconds after last change
     */
    uint32_t tCurrentMicros = micros();
    uint16_t tMicrosOfMarkOrSpace = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros;
    TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;

    uint8_t tState = TinyIRReceiverControl.IRReceiverState;

    if (tIRLevel == LOW) {
        /*
         * We have a mark here
         */
        if (tMicrosOfMarkOrSpace > 2 * NEC_HEADER_MARK) {
            // timeout -> must reset state machine
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
        if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) {
            // We are at the beginning of the header mark, check timing at the next transition
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
        }

        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) {
            if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_SPACE)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_SPACE)) {
                /*
                 * We have a valid data header space here -> initialize data
                 */
                TinyIRReceiverControl.IRRawDataBitCounter = 0;
                TinyIRReceiverControl.IRRawData.ULong = 0;
                TinyIRReceiverControl.IRRawDataMask = 1;
                TinyIRReceiverControl.IRRepeatDetected = false;
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
            } else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
                    && TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS) {
                /*
                 * We have a repeat header here and no broken receive before -> set repeat flag
                 */
                TinyIRReceiverControl.IRRepeatDetected = true;
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
            } else {
                // This parts are optimized by the compiler into jumps to one code :-)
                // Wrong length -> reset state
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        }

        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
            // Check data space length
            if (tMicrosOfMarkOrSpace >= lowerValue(NEC_ZERO_SPACE) && tMicrosOfMarkOrSpace <= upperValue(NEC_ONE_SPACE)) {
                // We have a valid bit here
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
                if (tMicrosOfMarkOrSpace >= 2 * NEC_UNIT) {
                    // we received a 1
                    TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
                } else {
                    // we received a 0 - empty code for documentation
                }
                // prepare for next bit
                TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1;
                TinyIRReceiverControl.IRRawDataBitCounter++;
            } else {
                // Wrong length -> reset state
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        } else {
            // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
    }

    else {
        /*
         * We have a space here
         */
        if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
            /*
             * Check length of header mark here
             */
            if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_MARK)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_MARK)) {
                tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK;
            } else {
                // Wrong length of header mark -> reset state
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        }

        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) {
            // Check data mark length
            if (tMicrosOfMarkOrSpace >= lowerValue(NEC_BIT_MARK) && tMicrosOfMarkOrSpace <= upperValue(NEC_BIT_MARK)) {
                /*
                 * We have a valid mark here, check for transmission complete
                 */
                if (TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS || TinyIRReceiverControl.IRRepeatDetected) {
                    /*
                     * Code complete -> call callback, no parity check!
                     */
                    // Reset state for new start
                    tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
                    
#if !defined(ARDUINO_ARCH_MBED)
                    interrupts();
#endif
                    /*
                     * Address reduction to 8 bit
                     */
                    if (TinyIRReceiverControl.IRRawData.UByte.LowByte
                            == (uint8_t) (~TinyIRReceiverControl.IRRawData.UByte.MidLowByte)) {
                        // standard 8 bit address NEC protocol
                        TinyIRReceiverControl.IRRawData.UByte.MidLowByte = 0; // Address is the first 8 bit
                    }

                    /*
                     * Call user provided callback here
                     */
                    handleReceivedTinyIRData(TinyIRReceiverControl.IRRawData.UWord.LowWord,
                            TinyIRReceiverControl.IRRawData.UByte.MidHighByte, TinyIRReceiverControl.IRRepeatDetected);

                } else {
                    // not finished yet
                    tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK;
                }
            } else {
                // Wrong length -> reset state
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        } else {
            // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
    }

    TinyIRReceiverControl.IRReceiverState = tState;
}
/**
 * The ISR of TinyIRRreceiver.
 * It handles the NEC protocol decoding and calls the user callback function on complete.
 * 5 us + 3 us for push + pop for a 16MHz ATmega
 */
The ISR of TinyIRRreceiver.
It handles the NEC protocol decoding and calls the user callback function on complete.
5 us + 3 us for push + pop for a 16MHz ATmega
The ISR of TinyIRRreceiver . It handles the NEC protocol decoding and calls the user callback function on complete . 5 us + 3 us for push + pop for a 16MHz ATmega
void IRPinChangeInterruptHandler(void) {
    uint_fast8_t tIRLevel = digitalReadFast(ir_input_pin);
    uint32_t tCurrentMicros = micros();
    uint16_t tMicrosOfMarkOrSpace = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros;
    TinyIRReceiverControl.LastChangeMicros = tCurrentMicros;
    uint8_t tState = TinyIRReceiverControl.IRReceiverState;
    if (tIRLevel == LOW) {
        if (tMicrosOfMarkOrSpace > 2 * NEC_HEADER_MARK) {
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
        if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) {
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE;
        }
        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) {
            if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_SPACE)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_SPACE)) {
                TinyIRReceiverControl.IRRawDataBitCounter = 0;
                TinyIRReceiverControl.IRRawData.ULong = 0;
                TinyIRReceiverControl.IRRawDataMask = 1;
                TinyIRReceiverControl.IRRepeatDetected = false;
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
            } else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE)
                    && TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS) {
                TinyIRReceiverControl.IRRepeatDetected = true;
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
            } else {
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        }
        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) {
            if (tMicrosOfMarkOrSpace >= lowerValue(NEC_ZERO_SPACE) && tMicrosOfMarkOrSpace <= upperValue(NEC_ONE_SPACE)) {
                tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE;
                if (tMicrosOfMarkOrSpace >= 2 * NEC_UNIT) {
                    TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask;
                } else {
                }
                TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1;
                TinyIRReceiverControl.IRRawDataBitCounter++;
            } else {
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        } else {
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
    }
    else {
        if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) {
            if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_HEADER_MARK)
                    && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_HEADER_MARK)) {
                tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK;
            } else {
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        }
        else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) {
            if (tMicrosOfMarkOrSpace >= lowerValue(NEC_BIT_MARK) && tMicrosOfMarkOrSpace <= upperValue(NEC_BIT_MARK)) {
                if (TinyIRReceiverControl.IRRawDataBitCounter >= NEC_BITS || TinyIRReceiverControl.IRRepeatDetected) {
                    tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
#if !defined(ARDUINO_ARCH_MBED)
                    interrupts();
#endif
                    if (TinyIRReceiverControl.IRRawData.UByte.LowByte
                            == (uint8_t) (~TinyIRReceiverControl.IRRawData.UByte.MidLowByte)) {
                        TinyIRReceiverControl.IRRawData.UByte.MidLowByte = 0; 
                    }
                    handleReceivedTinyIRData(TinyIRReceiverControl.IRRawData.UWord.LowWord,
                            TinyIRReceiverControl.IRRawData.UByte.MidHighByte, TinyIRReceiverControl.IRRepeatDetected);
                } else {
                    tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK;
                }
            } else {
                tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
            }
        } else {
            tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK;
        }
    }
    TinyIRReceiverControl.IRReceiverState = tState;
}
void IRPinChangeInterruptHandler ( void ) { uint_fast8_t tIRLevel = digitalReadFast ( ir_input_pin ) ; uint32_t tCurrentMicros = micros ( ) ; uint16_t tMicrosOfMarkOrSpace = tCurrentMicros - TinyIRReceiverControl . LastChangeMicros ; TinyIRReceiverControl . LastChangeMicros = tCurrentMicros ; uint8_t tState = TinyIRReceiverControl . IRReceiverState ; if ( tIRLevel == LOW ) { if ( tMicrosOfMarkOrSpace > 2 * NEC_HEADER_MARK ) { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } if ( tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK ) { tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE ; } else if ( tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK ) { if ( tMicrosOfMarkOrSpace >= lowerValue25Percent ( NEC_HEADER_SPACE ) && tMicrosOfMarkOrSpace <= upperValue25Percent ( NEC_HEADER_SPACE ) ) { TinyIRReceiverControl . IRRawDataBitCounter = 0 ; TinyIRReceiverControl . IRRawData . ULong = 0 ; TinyIRReceiverControl . IRRawDataMask = 1 ; TinyIRReceiverControl . IRRepeatDetected = false ; tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ; } else if ( tMicrosOfMarkOrSpace >= lowerValue25Percent ( NEC_REPEAT_HEADER_SPACE ) && tMicrosOfMarkOrSpace <= upperValue25Percent ( NEC_REPEAT_HEADER_SPACE ) && TinyIRReceiverControl . IRRawDataBitCounter >= NEC_BITS ) { TinyIRReceiverControl . IRRepeatDetected = true ; tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ; } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } else if ( tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK ) { if ( tMicrosOfMarkOrSpace >= lowerValue ( NEC_ZERO_SPACE ) && tMicrosOfMarkOrSpace <= upperValue ( NEC_ONE_SPACE ) ) { tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ; if ( tMicrosOfMarkOrSpace >= 2 * NEC_UNIT ) { TinyIRReceiverControl . IRRawData . ULong |= TinyIRReceiverControl . IRRawDataMask ; } else { } TinyIRReceiverControl . IRRawDataMask = TinyIRReceiverControl . IRRawDataMask << 1 ; TinyIRReceiverControl . IRRawDataBitCounter ++ ; } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } else { if ( tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE ) { if ( tMicrosOfMarkOrSpace >= lowerValue25Percent ( NEC_HEADER_MARK ) && tMicrosOfMarkOrSpace <= upperValue25Percent ( NEC_HEADER_MARK ) ) { tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK ; } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } else if ( tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE ) { if ( tMicrosOfMarkOrSpace >= lowerValue ( NEC_BIT_MARK ) && tMicrosOfMarkOrSpace <= upperValue ( NEC_BIT_MARK ) ) { if ( TinyIRReceiverControl . IRRawDataBitCounter >= NEC_BITS || TinyIRReceiverControl . IRRepeatDetected ) { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; #if ! defined ( ARDUINO_ARCH_MBED ) interrupts ( ) ; #endif if ( TinyIRReceiverControl . IRRawData . UByte . LowByte == ( uint8_t ) ( ~ TinyIRReceiverControl . IRRawData . UByte . MidLowByte ) ) { TinyIRReceiverControl . IRRawData . UByte . MidLowByte = 0 ; } handleReceivedTinyIRData ( TinyIRReceiverControl . IRRawData . UWord . LowWord , TinyIRReceiverControl . IRRawData . UByte . MidHighByte , TinyIRReceiverControl . IRRepeatDetected ) ; } else { tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK ; } } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } else { tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK ; } } TinyIRReceiverControl . IRReceiverState = tState ; }
The ISR of TinyIRRreceiver.
The ISR of TinyIRRreceiver .
/*
     * Save IR input level
     * Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark.
     */ /*
     * 1. compute microseconds after last change
     */ /*
         * We have a mark here
         */ // timeout -> must reset state machine // We are at the beginning of the header mark, check timing at the next transition /*
                 * We have a valid data header space here -> initialize data
                 */ /*
                 * We have a repeat header here and no broken receive before -> set repeat flag
                 */ // This parts are optimized by the compiler into jumps to one code :-) // Wrong length -> reset state // Check data space length // We have a valid bit here // we received a 1 // we received a 0 - empty code for documentation // prepare for next bit // Wrong length -> reset state // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state /*
         * We have a space here
         */ /*
             * Check length of header mark here
             */ // Wrong length of header mark -> reset state // Check data mark length /*
                 * We have a valid mark here, check for transmission complete
                 */ /*
                     * Code complete -> call callback, no parity check!
                     */ // Reset state for new start /*
                     * Address reduction to 8 bit
                     */ // standard 8 bit address NEC protocol // Address is the first 8 bit /*
                     * Call user provided callback here
                     */ // not finished yet // Wrong length -> reset state // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state