Full Code of ukw100/IRMP for AI

master 66371efe5477 cached
76 files
1.3 MB
347.8k tokens
185 symbols
1 requests
Download .txt
Showing preview only (1,427K chars total). Download the full file or copy to clipboard to get everything.
Repository: ukw100/IRMP
Branch: master
Commit: 66371efe5477
Files: 76
Total size: 1.3 MB

Directory structure:
gitextract_kbf87dk0/

├── .github/
│   ├── issue_template.md
│   └── workflows/
│       ├── LibraryBuild.yml
│       └── PlatformIoPublish.yml
├── LICENSE.txt
├── README.md
├── examples/
│   ├── AllProtocols/
│   │   ├── ADCUtils.h
│   │   ├── ADCUtils.hpp
│   │   ├── AllProtocols.ino
│   │   ├── LiquidCrystal_I2C.h
│   │   ├── LiquidCrystal_I2C.hpp
│   │   └── PinDefinitionsAndMore.h
│   ├── Callback/
│   │   ├── Callback.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── IRDispatcherDemo/
│   │   ├── DemoIRCommandMapping.h
│   │   ├── IRDispatcherDemo.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── Interrupt/
│   │   ├── Interrupt.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── OneProtocol/
│   │   ├── OneProtocol.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── RFProtocols/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── RFProtocols.ino
│   ├── ReceiveAndSend/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── ReceiveAndSend.ino
│   ├── ReceiveAndSendDynamicPins/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── ReceiveAndSendDynamicPins.ino
│   ├── ReceiverTimingAnalysis/
│   │   └── ReceiverTimingAnalysis.ino
│   ├── SendAllProtocols/
│   │   ├── PinDefinitionsAndMore.h
│   │   ├── SendAllProtocols.ino
│   │   └── SendAllProtocols.log
│   ├── SimpleReceiver/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── SimpleReceiver.ino
│   ├── SimpleSender/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── SimpleSender.ino
│   ├── TinyReceiver/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── TinyReceiver.ino
│   └── TinySender/
│       ├── PinDefinitionsAndMore.h
│       └── TinySender.ino
├── extras/
│   ├── IRMP_UNO.fzz
│   └── IRMP_UNO_LCD.fzz
├── keywords.txt
├── library.json
├── library.properties
└── src/
    ├── IRCommandDispatcher.h
    ├── IRCommandDispatcher.hpp
    ├── IRFeedbackLED.h
    ├── IRFeedbackLED.hpp
    ├── IRTimer.h
    ├── IRTimer.hpp
    ├── LocalDebugLevelEnd.h
    ├── LocalDebugLevelStart.h
    ├── LongUnion.h
    ├── TinyIR.h
    ├── TinyIRReceiver.hpp
    ├── TinyIRSender.hpp
    ├── digitalWriteFast.h
    ├── irmp.h
    ├── irmp.hpp
    ├── irmpArduinoExt.h
    ├── irmpArduinoExt.hpp
    ├── irmpPinChangeInterrupt.hpp
    ├── irmpSelectAllProtocols.h
    ├── irmpSelectAllRFProtocols.h
    ├── irmpSelectMain15Protocols.h
    ├── irmpVersion.h
    ├── irmpconfig.h
    ├── irmpprotocols.h
    ├── irmpprotocols.hpp
    ├── irmpsystem.h
    ├── irsnd.h
    ├── irsnd.hpp
    ├── irsndArduinoExt.h
    ├── irsndArduinoExt.hpp
    ├── irsndSelectAllProtocols.h
    ├── irsndSelectMain15Protocols.h
    └── irsndconfig.h

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/issue_template.md
================================================
---
name: 🐛 Bug Report
about: Only if something isn't working as expected 🤔, otherwise please open a discussion.
assignees: ArminJo
---

If you have handling problems or questions, consider to open a discussion https://github.com/IRMP-org/IRMP/discussions instead of an issue.

## Bug Report

### Board
* [ ] Arduino ATmega328* board (UNO, Nano)
* [ ] Arduino ATmega2560 board (Mega)
* [ ] Arduino ATmega32U4 board (Leonardo)
* [ ] Arduino megaAVR board (NanoEvery)
* [ ] Arduino SAM board (Due)
* [ ] Arduino SAMD board (Zero, MKR*)
* [ ] ATtiny85 board (ATTinyCore by Spence Conde)
* [ ] Digispark board
* [ ] ATtiny3217 board (TinyCore)
* [ ] ATmega8 board
* [ ] ESP8266 board
* [ ] ESP32 board
* [ ] STM32 board with "STM32 Boards (selected from submenu)" core
* [ ] STM32 board with "STM32F1 Boards (STM32duino.com)" core
* [ ] Apollo3 board
* [ ] Teensy board
* [ ] Other - please specify

<!-- Please specify board name if not included in board selection -->

### IDE
* [ ] Arduino IDE
* [ ] Arduino Web Editor
* [ ] Arduino Pro IDE
* [ ] Sloeber IDE
* [ ] PlatformIO IDE
* [ ] Other - please specify

### IR-Protocol
* [ ] Unknown
* [ ] Sony
* [ ] NEC
* [ ] Samsung
* [ ] RC5, RC6
* [ ] Kaseikyo
* [ ] Denon
* [ ] JVC
* [ ] Lego
* [ ] Matsushita
* [ ] Mitsubishi
* [ ] Panasonic
* [ ] Sanyo
* [ ] Sharp
* [ ] Telefunken
* [ ] Other - please specify

### Example to reproduce the issue
* [ ] AllProtocols
* [ ] Callback
* [ ] Interrupt
* [ ] OneProtocol
* [ ] ReceiveAndSend
* [ ] ReceiveAndSendDynamicPins
* [ ] RFProtocols
* [ ] SimpleReceiver
* [ ] SimpleSender
* [ ] Other

### Version
* [ ] Yes I use the [latest repo version](https://github.com/Arduino-IRremote/Arduino-IRremote/archive/master.zip) and verified this!
* [ ] Other - please specify

Please delete all unchecked lines above :-)

### Pin(s) used for IR-receive, if not default

### Current behavior
<!-- Paste the code or repository link, if applicable. -->

<!-- Add a the serial output which indicates the error happened. -->

<!-- Add a clear and concise description of the behavior. -->

### Expected behavior
<!-- Add a clear and concise description of what you expected to happen. -->

### Additional context
<!-- (Optional) Add any other context about the problem here. -->

**checklist:**
- [] I have **read** the README.md file thoroughly.
- [] I have searched existing issues to see if there is anything I have missed.
- [] I have browsed the examples for one, that matches my use case.
- [] Any code referenced is provided and if over 30 lines a gist is linked INSTEAD of it being pasted in here.
- [] The title of the issue is helpful and relevant.
- [] I checked, if at least one of the examples was working.

** We will start to close or delete issues that do not follow these guidelines as it doesn't help the contributors who spend time trying to solve issues if the community ignores guidelines!**


================================================
FILE: .github/workflows/LibraryBuild.yml
================================================
# LibraryBuild.yml
# Github workflow script to test compile all examples of an Arduino library repository.
#
# Copyright (C) 2020  Armin Joachimsmeyer
# https://github.com/ArminJo/Github-Actions
#

# This is the name of the workflow, visible on GitHub UI.
name: LibraryBuild
on:
  workflow_dispatch: # To run it manually
    description: 'manual build check'
  push: # see: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
    paths:
    - '**.ino'
    - '**.cpp'
    - '**.hpp'
    - '**.h'
    - '**LibraryBuild.yml'
  pull_request:
    paths:
    - '**.ino'
    - '**.cpp'
    - '**.h'
    - '**.hpp'
    - '**LibraryBuild.yml'

jobs:
  build:
    name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples

    runs-on: ubuntu-latest # I picked Ubuntu to use shell scripts.

    strategy:
      matrix:
        # The matrix will produce one job for each configuration parameter of type `arduino-boards-fqbn`
        # In the Arduino IDE, the fqbn is printed in the first line of the verbose output for compilation as parameter -fqbn=... for the "arduino-builder -dump-prefs" command
        #
        # Examples: arduino:avr:uno, arduino:avr:leonardo, arduino:avr:nano, arduino:avr:mega
        # arduino:sam:arduino_due_x, arduino:samd:arduino_zero_native"
        # ATTinyCore:avr:attinyx5:chip=85,clock=1internal, digistump:avr:digispark-tiny, digistump:avr:digispark-pro
        # STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
        # esp8266:esp8266:huzzah:eesz=4M3M,xtal=80, esp32:esp32:featheresp32:FlashFreq=80
        # You may add a suffix behind the fqbn with "|" to specify one board for e.g. different compile options like arduino:avr:uno|trace
        #############################################################################################################
        arduino-boards-fqbn:
          - arduino:avr:uno
          - arduino:avr:leonardo
          - arduino:avr:mega
          - arduino:megaavr:nona4809:mode=off
          - arduino:samd:arduino_zero_native
          - arduino:mbed:nano33ble
          - arduino:mbed_rp2040:pico
          - rp2040:rp2040:arduino_nano_connect
#          - digistump:avr:digispark-tiny:clock=clock16
#          - ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=8pll
#          - ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
#          - ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled  # ATtiny88 China clone board @16 MHz
#          - megaTinyCore:megaavr:atxy6:chip=1616,clock=16internal
#          - megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
          - MiniCore:avr:8:bootloader=uart0,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=16MHz_external # ATmega8
          - MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os,clock=8MHz_internal # ATmega128
          - esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
          - esp32:esp32:featheresp32:FlashFreq=80
          - STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
          - STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
          - stm32duino:STM32F1:genericSTM32F103C
#          - SparkFun:apollo3:sfe_artemis_nano

        # Specify parameters for each board.
        # With sketches-exclude you may exclude specific examples for a board. Use a comma separated list.
        #############################################################################################################
        include:
          - arduino-boards-fqbn: arduino:avr:uno
            required-libraries: LiquidCrystal I2C
            build-properties: # the flags were put in compiler.cpp.extra_flags
              AllProtocols: -DUSE_SERIAL_LCD

          - arduino-boards-fqbn: arduino:avr:leonardo
            build-properties: # the flags were put in compiler.cpp.extra_flags
              AllProtocols: -DUSE_NO_LCD

          - arduino-boards-fqbn: arduino:megaavr:nona4809:mode=off
            sketches-exclude: TinyReceiver,IRDispatcherDemo
            build-properties: # the flags were put in compiler.cpp.extra_flags
              All: -DNO_LED_FEEDBACK_CODE

#          - arduino-boards-fqbn: digistump:avr:digispark-tiny:clock=clock16
#            platform-url: https://raw.githubusercontent.com/ArminJo/DigistumpArduino/master/package_digistump_index.json
#            required-libraries: ATtinySerialOut
#            sketches-exclude: AllProtocols,SendAllProtocols,ReceiveAndSendDynamicPins,ReceiverTimingAnalysis # Does not fit in FLASH # Comma separated list of example names to exclude in build

#
# ATTinyCore
#
          - arduino-boards-fqbn: ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=8pll
            platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json
            required-libraries: ATtinySerialOut
            sketches-exclude: AllProtocols,SendAllProtocols,ReceiveAndSendDynamicPins # Does not fit in FLASH

          - arduino-boards-fqbn: ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled
            platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json
            required-libraries: ATtinySerialOut
            sketches-exclude: AllProtocols,SendAllProtocols,ReceiveAndSendDynamicPins # Does not fit in FLASH

          - arduino-boards-fqbn: ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
            platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json
            required-libraries: ATtinySerialOut
            sketches-exclude: AllProtocols,ReceiveAndSendDynamicPins # No Serial.available() function in ATtinySerialOut

#
# megaTinyCore
#
#          - arduino-boards-fqbn: megaTinyCore:megaavr:atxy6:chip=1616,clock=16internal
#            arduino-platform: megaTinyCore:megaavr
#            platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json
#            sketches-exclude: TinySender,TinyReceiver # PIN_PA6' was not declared etc.

#          - arduino-boards-fqbn: megaTinyCore:megaavr:atxy7:chip=3217,clock=16internal
#            arduino-platform: megaTinyCore:megaavr
#            platform-url: https://felias-fogg.github.io/downloads/package_debug_enabled_index.json
#            sketches-exclude: TinySender,TinyReceiver # PIN_PA6' was not declared etc.


          - arduino-boards-fqbn: arduino:mbed_rp2040:pico

          - arduino-boards-fqbn: rp2040:rp2040:arduino_nano_connect
            platform-url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

          - arduino-boards-fqbn: MiniCore:avr:8:bootloader=uart0,eeprom=keep,BOD=2v7,LTO=Os_flto,clock=16MHz_external
            platform-url: https://mcudude.github.io/MiniCore/package_MCUdude_MiniCore_index.json
            arduino-platform: MiniCore:avr,arduino:avr # gcc is taken from arduino:avr
            sketches-exclude: AllProtocols,ReceiveAndSendDynamicPins,SendAllProtocols,TinyReceiver,IRDispatcherDemo,Interrupt  # Does not fit in FLASH

          - arduino-boards-fqbn: MegaCore:avr:128:bootloader=no_bootloader,eeprom=keep,BOD=2v7,LTO=Os,clock=8MHz_internal
            platform-url: https://mcudude.github.io/MegaCore/package_MCUdude_MegaCore_index.json
            arduino-platform: MegaCore:avr,arduino:avr # gcc is taken from arduino:avr
            sketches-exclude: AllProtocols,ReceiveAndSendDynamicPins # Does not fit in FLASH
#
# ESP
#
          - arduino-boards-fqbn: esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
            platform-url: https://arduino.esp8266.com/stable/package_esp8266com_index.json
            sketches-exclude: TinyReceiver,AllProtocols # error ".text1' will not fit in region `iram1_0_seg'"

          - arduino-boards-fqbn: esp32:esp32:featheresp32:FlashFreq=80
            platform-url: https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
            sketches-exclude: TinyReceiver

          - arduino-boards-fqbn: STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
            platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json
            sketches-exclude: TinyReceiver

          - arduino-boards-fqbn: STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
            platform-url: https://raw.githubusercontent.com/stm32duino/BoardManagerFiles/main/package_stmicroelectronics_index.json
            sketches-exclude: TinyReceiver,IRDispatcherDemo
            build-properties: # the flags were put in compiler.cpp.extra_flags
              All: -DNO_LED_FEEDBACK_CODE

          - arduino-boards-fqbn: stm32duino:STM32F1:genericSTM32F103C # Roger Clark version
            platform-url: http://dan.drown.org/stm32duino/package_STM32duino_index.json
            sketches-exclude: TinyReceiver

#          - arduino-boards-fqbn: SparkFun:apollo3:sfe_artemis_nano
#            platform-url: https://raw.githubusercontent.com/sparkfun/Arduino_Apollo3/master/package_sparkfun_apollo3_index.json
#            sketches-exclude: TinyReceiver

      # Do not cancel all jobs / architectures if one job fails
#      fail-fast: false

    steps:
      - name: Checkout
        uses: actions/checkout@master

# gives ERROR: library.properties includes field item(s) Arduino.h not found in library.
#      - name: Arduino Lint
#        uses: arduino/arduino-lint-action@v1
#        with:
#          library-manager: update

      - name: Compile all examples
        uses: ArminJo/arduino-test-compile@master
        with:
          arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }}
          platform-url: ${{ matrix.platform-url }}
#          arduino-platform: ${{ matrix.arduino-platform }}
          required-libraries: 'LiquidCrystal,${{ matrix.required-libraries }}'
          sketches-exclude: ${{ matrix.sketches-exclude }}
          build-properties: ${{ toJson(matrix.build-properties) }}
#          debug-install: true


================================================
FILE: .github/workflows/PlatformIoPublish.yml
================================================
# PlatformIoPublish.yml
# Github workflow script to publish a release to PlatformIo.
#
# Copyright (C) 2021-2023  Armin Joachimsmeyer
# https://github.com/ArminJo/Github-Actions
#

# This is the name of the workflow, visible on GitHub UI.
name: PlatformIo publishing
on:
  workflow_dispatch: # To run it manually
    description: manual PlatformIo publishing
  release: # see: https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows#example-using-multiple-events-with-activity-types-or-configuration
    types:
      - created

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:

    - name: Checkout
      uses: actions/checkout@master

    - name: Set up Python
      uses: actions/setup-python@master
      with:
        python-version: '3.x'

    - name: Install dependencies
      run: |
        python -m pip install --upgrade pip
        pip install platformio

    - name: Build and publish
      env:
        PLATFORMIO_AUTH_TOKEN: ${{ secrets.PLATFORMIO_TOKEN }}
      run: |
        pio package publish --owner IRMP-org --non-interactive
#      run: |
#        pio package pack
#        pio package publish --owner IRMP-org --non-interactive


================================================
FILE: LICENSE.txt
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
<div align = center>

# [IRMP](https://github.com/IRMP-org/IRMP) - Infrared Multi Protocol Decoder + Encoder
A library enabling the sending & receiving of infra-red signals with a low memory footprint.<br/>
Supports 50 different protocols.

[![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0)
 &nbsp; &nbsp; 
[![Badge Version](https://img.shields.io/github/v/release/IRMP-org/IRMP?include_prereleases&color=yellow&logo=DocuSign&logoColor=white)](https://github.com/IRMP-org/IRMP/releases/latest)
 &nbsp; &nbsp; 
[![Badge Commits since latest](https://img.shields.io/github/commits-since/IRMP-org/IRMP/latest?color=yellow)](https://github.com/IRMP-org/IRMP/commits/master)
 &nbsp; &nbsp; 
[![Badge Build Status](https://github.com/IRMP-org/IRMP/workflows/LibraryBuild/badge.svg)](https://github.com/IRMP-org/IRMP/actions)
 &nbsp; &nbsp; 
![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=IRMP-org_IRMP)
<br/>
<br/>
[![Stand With Ukraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://stand-with-ukraine.pp.ua)

Available as [Arduino library "IRMP"](https://www.arduinolibraries.info/libraries/irmp).

[![Button Install](https://img.shields.io/badge/Install-brightgreen?logoColor=white&logo=GitBook)](https://www.ardu-badge.com/IRMP)
 &nbsp; &nbsp; 
[![Button Changelog](https://img.shields.io/badge/Changelog-blue?logoColor=white&logo=AzureArtifacts)](https://github.com/IRMP-org/IRMP?tab=readme-ov-file#revision-history)

</div>

#### If you find this library useful, please give it a star.

&#x1F30E; [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/IRMP-org/IRMP)

<br/>

# Features
- Total of 50 IR protocols supported.
- Up to 39 protocols can be enabled for receive at the same time, because some of the 50 protocols are quite similar and conflicts with each other.
- 39 protocols are available for send.
- Low memory footprint. FLASH usage in bytes: 1500 for one protocol, 4300 for 15 main and 8000 for all 39 protocols.
- RAM usage in bytes: 52, 73 and 100.

<br/>

| Nano running AllProtocol example | YouTube Video | Instructable |
|-|-|-|
| ![Nano running AllProtocol example](pictures/NEC.jpg) | ![YouTube Video](pictures/KASEIKYO+Remote.jpg) | [![Instructable](https://github.com/ArminJo/Arduino-OpenWindowAlarm/blob/master/pictures/instructables-logo-v2.png)](https://www.instructables.com/id/IR-Remote-Analyzer-Receiver-With-Arduino) |

<br/>

# List of protocols
` Sony SIRCS ` &nbsp; &nbsp; ` NEC + APPLE + ONKYO ` &nbsp; &nbsp; ` Samsung + Samsg32 ` &nbsp; &nbsp; ` Kaseikyo `

` JVC ` &nbsp; &nbsp; ` NEC16 + NEC42 ` &nbsp; &nbsp; ` Matsushita ` &nbsp; &nbsp; ` DENON `
&nbsp; &nbsp; ` Sharp ` &nbsp; &nbsp; ` RC5 ` &nbsp; &nbsp; ` RC6 & RC6A ` &nbsp; &nbsp; ` IR60 (SDA2008) Grundig `
&nbsp; &nbsp; ` Siemens Gigaset ` &nbsp; &nbsp; ` Nokia `

` BOSE ` &nbsp; &nbsp; ` Kathrein ` &nbsp; &nbsp; ` NUBERT ` &nbsp; &nbsp; ` FAN (ventilator) `
&nbsp; &nbsp; ` SPEAKER (~NUBERT) ` &nbsp; &nbsp; ` Bang & Olufsen ` &nbsp; &nbsp; ` RECS80 (SAA3004) `<br/>
&nbsp; &nbsp; ` RECS80EXT (SAA3008) ` &nbsp; &nbsp; ` Thomson ` &nbsp; &nbsp; ` NIKON camera `
&nbsp; &nbsp; ` Netbox keyboard ` &nbsp; &nbsp; ` ORTEK (Hama) ` &nbsp; &nbsp; ` Telefunken 1560 `<br/>
&nbsp; &nbsp; ` FDC3402 keyboard ` &nbsp; &nbsp; ` RC Car ` &nbsp; &nbsp; ` iRobot Roomba `
&nbsp; &nbsp; ` RUWIDO ` &nbsp; &nbsp; ` T-Home ` &nbsp; &nbsp; ` A1 TV BOX ` &nbsp; &nbsp;` LEGO Power RC `<br/>
&nbsp; &nbsp; ` RCMM 12,24, or 32 ` &nbsp; &nbsp; ` LG Air Condition ` &nbsp; &nbsp; ` Samsung48 `
&nbsp; &nbsp; ` Merlin ` &nbsp; &nbsp; ` Pentax ` &nbsp; &nbsp; ` S100 ` &nbsp; &nbsp; ` ACP24 ` &nbsp; &nbsp; ` TECHNICS `<br/>
&nbsp; &nbsp; ` PANASONIC Beamer ` &nbsp; &nbsp; ` Mitsubishi Aircond ` &nbsp; &nbsp; ` VINCENT `
&nbsp; &nbsp; ` SAMSUNG AH ` &nbsp; &nbsp; ` GREE CLIMATE `  &nbsp; &nbsp; ` RCII T+A `<br/>
 &nbsp; &nbsp; ` RADIO e.g. TEVION ` &nbsp; &nbsp; ` METZ `

` NEC ` &nbsp; &nbsp; ` Kaseiko ` &nbsp; &nbsp; ` Denon ` &nbsp; &nbsp; ` RC6 ` &nbsp; &nbsp; ` Samsung + Samsg32 ` &nbsp; were successfully tested in **interrupt mode**, but there are many protocols which **in principle cannot be decoded** in this mode.

<br/>

# Features
- You may use **every pin for input or output**.
- Interrupt mode for major protocols.
- Callback after successful receive of a command.
- Support for inverted feedback LED (for send and receive feedback).
- Support for inverted IR output for LED connected to VCC.
- Unmodulated IR signal output enables direct replacment of an IR receiver circuit.
- Compatible with Arduino tone library.
- Send can also also wait for trailing space/gap.

# Restrictions
- Send IR frequency is fixed at 38 kHz.
<br/>

# Minimal version
For applications only requiring NEC protocol, there is a receiver which has very **small codesize of 500 bytes and does NOT require any timer**. See the MinimalReceiver and IRDispatcherDemo example how to use it. Mapping of pins to interrupts can be found [here](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/src/TinyIRReceiver.hpp#L259).
<br/>

# Schematic for Arduino Uno
The VS1838B is used as receiver for all examples and tests. This module has a 120 &micro;s on/low and a 100 &micro;s off/high delay between received signal and output. So it shortens the mark and extends the space by 20 &micro;s.
| IR-Receiver connection | Serial LCD connection |
|---|---|
![Fritzing schematic for Arduino Uno](extras/IRMP_UNO_Steckplatine.png) | ![Fritzing schematic for Arduino Uno + LCD](extras/IRMP_UNO_LCD_Steckplatine.png)
<br/>

# Supported Arduino architectures / CPU's / boards
For **ESP8266/ESP32**, [this library](https://github.com/crankyoldgit/IRremoteESP8266) supports an [impressive set of protocols and a lot of air conditioners](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)<br/>
<br/>
ATtiny and Digispark boards are tested with the recommended [ATTinyCore](https://github.com/SpenceKonde/ATTinyCore) using `New Style` pin mapping for the pro board.
| Architecture | CPU | Board |
|-|-:|-:|
| avr     | ATmega16, ATmega328P, ATmega32U4, ATtinyX5, ATtinyX7 | Uno, Nano, Leonardo, Sparkfun Pro Micro, Digispark etc. |
| megaavr | ATmega4809 | Uno WiFi Rev 2, Nano Every |
| samd    | SAMD21G18A | Zero, MKR*, etc. **but not DUE, which is sam architecture** |
| esp8266 | All protocols does not fit in IRAM | all |
| esp32   | % | all |
| stm32   | STM32F1xx     | BluePill |
| STM32F1 | STM32F1xx     | BluePill |
| apollo3 | Ambiq Apollo3 | Sparkfun Apollo3 + Artemis |
| mbed    | nRF528x       | Nano 33 BLE |
| Teensiduino | all  - but [limited support](https://forum.pjrc.com/threads/65912-Enable-Continuous-Integration-with-arduino-cli-for-3-party-libraries) | >= Teensy 3 |
<br/>

# Quick comparison of 5 Arduino IR receiving libraries
**This is a short comparison and may not be complete or correct.**

I created this comparison matrix for [myself](https://github.com/ArminJo) in order to choose a small IR lib for my project and to have a quick overview, when to choose which library.<br/>
It is dated from **24.06.2022** and updated 10/2023. If you have complains about the data or request for extensions, please send a PM or open a discussion.

[Here](https://github.com/crankyoldgit/IRremoteESP8266) you find an **ESP8266/ESP32** version of IRremote with an **[impressive list of supported protocols](https://github.com/crankyoldgit/IRremoteESP8266/blob/master/SupportedProtocols.md)**.

| Subject | [IRMP](https://github.com/IRMP-org/IRMP) | [IRLremote](https://github.com/NicoHood/IRLremote) | [IRLib2](https://github.com/cyborg5/IRLib2)<br/>**mostly unmaintained** | [IRremote](https://github.com/Arduino-IRremote/Arduino-IRremote) | [TinyIR](https://github.com/Arduino-IRremote/Arduino-IRremote/tree/master/examples/TinyReceiver/TinyReceiver.ino) | [IRsmallDecoder](https://github.com/LuisMiCa/IRsmallDecoder)
|-|-|-|-|-|-|-|
| Number of protocols | **50** | Nec + Panasonic + Hash \* | 12 + Hash \* | 17 + PulseDistance + Hash \* | NEC + FAST | NEC + RC5 + Sony + Samsung |
| Timing method receive | Timer2 or interrupt for pin 2 or 3 | **Interrupt** | Timer2 or interrupt for pin 2 or 3 | Timer2 | **Interrupt** | **Interrupt** |
| Timing method send | PWM and timing with Timer2 interrupts | Timer2 interrupts | Timer2 and blocking wait | PWM with Timer2 and/or blocking wait with delay<br/>Microseconds() | blocking wait with delay<br/>Microseconds() | % |
| Send pins| All | All | All ? | Timer dependent | All | % |
| Decode method | OnTheFly | OnTheFly | RAM | RAM | OnTheFly | OnTheFly |
| Encode method | OnTheFly | OnTheFly | OnTheFly | OnTheFly or RAM | OnTheFly | % |
| Callback suppport | x | % | % | x | x | % |
| Repeat handling | Receive + Send (partially) | % | ? | Receive + Send | Receive + Send | Receive |
| LED feedback | x | % | x | x | Receive | % |
| FLASH usage (simple NEC example with 5 prints) | 1820<br/>(4300 for 15 main / 8000 for all 40 protocols)<br/>(+200 for callback)<br/>(+80 for interrupt at pin 2+3)| 1270<br/>(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? |
| RAM usage | 52<br/>(73 / 100 for 15 (main) / 40 protocols) | 62 | 334 | 227 | **19** | 29 |
| Supported platforms | **avr, megaavr, attiny, Digispark (Pro), esp8266, ESP32, STM32, SAMD 21, Apollo3<br/>(plus arm and pic for non Arduino IDE)** | avr, esp8266 | avr, SAMD 21, SAMD 51 | avr, attiny, [esp8266](https://github.com/crankyoldgit/IRremoteESP8266), esp32, SAM, SAMD | **All platforms with attach<br/>Interrupt()** | **All platforms with attach<br/>Interrupt()** |
| Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 |
| Remarks | Decodes 40 protocols concurrently.<br/>39 Protocols to send.<br/>Work in progress. | Only one protocol at a time. | Consists of 5 libraries. **Project containing bugs - 63 issues, 10 pull requests.* | Universal decoder and encoder.<br/>Supports **Pronto** codes and sending of raw timing values. | Requires no timer. | Requires no timer. |

\* The Hash protocol gives you a hash as code, which may be sufficient to distinguish your keys on the remote, but may not work with some protocols like Mitsubishi

<br/>

# Pin usage
You may use **every pin for input or output**, just define it like `#define IRMP_INPUT_PIN 2` and `#define IRSND_OUTPUT_PIN 3`. The PWM of the output pin is generated by software bit banging.

# Dynamic pins numbers
If you want to use pin numbers for input, output and LED feedback specified at runtime, you must define `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. See [ReceiveAndSendDynamicPins example](examples/ReceiveAndSendDynamicPins/ReceiveAndSendDynamicPins.ino).<br/>
The `irmp_init` and `irsnd_init` function then allows up to 3 parameters `uint_fast8_t aIrmpInputPin/aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow`.<br/>
Be aware, only one pin and enable flag for receive and send feedback LED is supported.

<br/>

# Receiving and sending simultaneously
Receiving and sending is possible with this library, but since we use only 1 timer, receiving is inhibited while sending the IR signal.<br/>
Sending the IR signal starts with saving current timer configuration, setting the timer to the send configuration / frequency, sending the signal (and waiting for the gap after the signal) and then automatically reset the timer to its previous (receiving) configuration.

<br/>

# API
### IRMP

```c++
// Init functions
void irmp_init (void);
void irmp_init(uint_fast8_t aIrmpInputPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin);
void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);
void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void));

// Info function
bool irmp_IsBusy();
void irmp_print_active_protocols(Print *aSerial);

// Main check for result function used in loop()
bool irmp_get_data (IRMP_DATA *)

// Result print functions
void irmp_result_print(Print *aSerial, IRMP_DATA * aIRMPDataPtr);
void irmp_result_print(IRMP_DATA *aIRMPDataPtr);
```
### IRSND

```c++
// Init functions
void irsnd_init (void);
// 3 additional init functions if IRMP_IRSND_ALLOW_DYNAMIC_PINS is defined
void irsnd_init(uint_fast8_t aIrsndOutputPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin);
void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow);

// Send function - sends frame AND trailing space
bool irsnd_send_data (IRMP_DATA *, uint8_t);

// Info functions
bool irsnd_is_busy (void);

void irsnd_stop (void);
```
### IRMP and IRSND

```c++
// LED feedback function
void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed);

// Timer management functions for 
void disableIRTimerInterrupt(void);
void enableIRTimerInterrupt(void);
void storeIRTimer(void);
void restoreIRTimer(void);
```
<br/>

# Examples
These examples can be found in the Arduino IDE under File > Examples > Examples from Custom Libraries / IRMP.

In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.

### AllProtocols
Receives up to 40 protocols concurrently and **displays the short result on a 1602 LCD**. The LCD can be connected parallel or serial (I2C).<br/>

### SimpleReceiver + SimpleSender
This examples are a good starting point.<br/>
SimpleReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/298945438795432456).
Click on the receiver while simulation is running to specify individual IR codes.

#### MinimalReceiver + MinimalSender
If **code size** matters, look at these examples.<br/>
The **MinimalReceiver** example uses the **TinyReceiver** library  which can **only receive NEC and FAST codes, but does not require any timer**.<br/>
MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/339264565653013075).
Click on the receiver while simulation is running to specify individual IR codes.

### SmallReceiver
If the protocol is not NEC and code size matters, look at this example.<br/>
MinimalReceiver can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299034264157028877).
Click on the receiver while simulation is running to specify individual IR codes.

### ReceiverTimingAnalysis
This example analyzes the signal delivered by your IR receiver module.
Values can be used to determine the stability of the received signal as well as a hint for determining the protocol.<br/>
It also computes the MARK_EXCESS_MICROS value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.<br/>
It can be tested online with [WOKWI](https://wokwi.com/arduino/projects/299033930562011656).
Click on the receiver while simulation is running to specify individual IR codes.

<br/>

# Tips and tricks
- To port the library to another device, you merely have to extend *IRTimer.hpp*.
- The minimal CPU clock required for receiving is 8MHz.
- To save power, you can use the interrupt mode or polling mode with no-sending detection and power down sleep.
 This is **not available** for ATtiny85 running with the High Speed PLL clock (as on  Digispark boards) 
 because of the high startup time from sleep of 4 to 5 ms for this clock. You have to use the ISP to [rewrite the CKSEL fuses](https://github.com/ArminJo/micronucleus-firmware/blob/master/utils/Write%2085%20Fuses%20E2%20DF%20FF%20-%20ISP%20Mode%20%3D%208MHz%20without%20BOD%20and%20Pin5.cmd) and to load the program.
 - The best way to **increase the IR power** is to use 2 or 3 IR diodes in series. 
 One diode requires 1.1 to 1.5 volt so you can supply 3 diodes with a 5 volt output.To keep the current, 
 you must reduce the resistor by (5 - 1.3) / (5 - 2.6) = 1.5 e.g. from 150 &ohm; to 100 &ohm; for 25 mA and 2 diodes with 1.3 volt and a 5 volt supply.
 For 3 diodes it requires factor 2.5 e.g. from 150 &ohm; to 60 &ohm;.
- A lot of recent IR diodes can be powered with max. 200 mA at 50% duty cycle, but for this you will require an external driver / transistor / (mos)fet.
- In order to fit the examples to the 8K flash of ATtiny85 and ATtiny88, the [Arduino library ATtinySerialOut](https://github.com/ArminJo/ATtinySerialOut) is required for this CPU's.
- Sending `IRMP_NEC_PROTOCOL` requires a full 16 bit address. Thus for sending plain NEC with 8 bit address, the 16 bit address must be computed with
`address |= ~((address & 0xFF) << 8);`

<br/>


# Compile options / macros for this library
To customize the library to different requirements, there are some compile options / macros available, which must be set **before** including the library e.g. with `#include <irmp.hpp>`.<br/>
Modify it by setting the value to 1 or 0. Or define the macro with the -D compiler option for global compile (the latter is not possible with the Arduino IDE, so consider using [Sloeber](https://eclipse.baeyens.it).<br/>

| Name | Default value | Description |
|-|-:|-|
| `IRMP_INPUT_PIN` | 2 | The pin number which gets compiled in, if not using `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. See also [PinDefinitionsAndMore.h](https://github.com/IRMP-org/IRMP/master/examples/OneProtocol/PinDefinitionsAndMore.h#L32) |
| `IRMP_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for the feedback led which gets compiled in, if not using `IRMP_IRSND_ALLOW_DYNAMIC_PINS`. |
| `FEEDBACK_LED_IS_ACTIVE_LOW` | disabled | Required on some boards (like my like my BluePill and my ESP8266 board), where the feedback LED is active low. |
| `NO_LED_FEEDBACK_CODE` | disabled | Enable it to disable the feedback LED function. Saves 30 bytes program memory. |
| `IRMP_IRSND_ALLOW_DYNAMIC_PINS` | disabled | Allows to specify pin number at irmp_init() - see above. This requires additional program memory. |
| `IRMP_PROTOCOL_NAMES` | 0 / disabled | Enable protocol number mapping to protocol strings - needs some program memory. |
| `IRMP_USE_COMPLETE_CALLBACK` | 0 / disabled | Use Callback if complete data was received. Requires call to irmp_register_complete_callback_function(). |
| `IRMP_ENABLE_PIN_CHANGE_INTERRUPT` | disabled | Use [Arduino attachInterrupt()](https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/) and do **no polling with timer ISR**. This **restricts the available input pins and protocols**. The results are equivalent to results acquired with a sampling rate of 15625 Hz (chosen to avoid time consuming divisions). For AVR boards an own interrupt handler for  INT0 or INT1 is used instead of Arduino attachInterrupt().  |
| `IRMP_ENABLE_RELEASE_DETECTION` | 0 / disabled | If user releases a key on the remote control, last protocol/address/command will be returned with flag `IRMP_FLAG_RELEASE` set. |
| `IRMP_HIGH_ACTIVE` | 0 / disabled | Set to 1 if you use a RF receiver, which has an active HIGH output signal. |
| `IRMP_32_BIT` | 0 / disabled | This enables MERLIN protocol, but decreases performance for AVR. Enabled by default for 32 bit platforms. |
| `F_INTERRUPTS` | 15000 | The IRMP sampling frequency.|
| `USE_ONE_TIMER_FOR_IRMP_AND_IRSND` | disabled | **Must** be defined if you use receiving and sending simultaneously, since both use the same timer resource. **Must not** be enabled if you only use receiving. |
| `IRSND_USE_CALLBACK` | 0 / disabled | Calls a function if send output signal changes to active (sending the IR signal). |
| `IR_OUTPUT_IS_ACTIVE_LOW` | disabled | Output LOW for active IR signal. Use it if IR LED is connected between VCC and output pin. |
| `IRSND_GENERATE_NO_SEND_RF` | disabled | Do not generate the carrier frequency (of 38 kHz), just simulate an active low receiver signal. |
| `IRSND_IR_FREQUENCY` | 38000 | The modulation frequency for sent signal. The send signal is generated by bit banging, so the internal interrupt frequency is `IRSND_IR_FREQUENCY * 2`. The send control function is called at a rate of `IRSND_IR_FREQUENCY / 2`, resulting in a send packet signal resolution of 2 on/off periods. |
|-|-|-|
| `IRMP_MEASURE_TIMING` +  `IR_TIMING_TEST_PIN` | enabled | For development only. The test pin is switched high at the very beginning and low at the end of the ISR. |

These next macros for **TinyIRReceiver** must be defined in your program before the line `#include <TinyIRReceiver.hpp>` to take effect.
| Name | Default value | Description |
|-|-:|-|
| `IR_RECEIVE_PIN` | 2 | The pin number for TinyIRReceiver IR input, which gets compiled in. |
| `IR_FEEDBACK_LED_PIN` | `LED_BUILTIN` | The pin number for TinyIRReceiver feedback LED, which gets compiled in. |
| `NO_LED_FEEDBACK_CODE` | disabled | Enable it to disable the feedback LED function. Saves 14 bytes program memory. |


### Changing include (*.h) files with Arduino IDE
First, use *Sketch > Show Sketch Folder (Ctrl+K)*.<br/>
If you have not yet saved the example as your own sketch, then you are instantly in the right library folder.<br/>
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.<br/>
In both cases the library source and include files are located in the libraries `src` directory.<br/>
The modification must be renewed for each new library version!

### Modifying compile options with Sloeber IDE
If you are using [Sloeber](https://eclipse.baeyens.it) as your IDE, you can easily define global symbols with *Properties > Arduino > CompileOptions*.<br/>
![Sloeber settings](https://github.com/ArminJo/ServoEasing/blob/master/pictures/SloeberDefineSymbols.png)

<br/>

# [Timer usage](https://github.com/IRMP-org/IRMP/blob/master/src/IRTimer.hpp#L39)
The IRMP **receive** library works by polling the input pin at a rate of 10 to 20 kHz. Default is 15 kHz.<br/>
Some protocols (NEC, Kaseiko, Denon, RC6, Samsung + Samsg32) can be received **without timer usage**, just by using interrupts from the input pin by defining `IRMP_ENABLE_PIN_CHANGE_INTERRUPT`. There are many protocols which **in principle cannot be decoded** in this mode. See [Interrupt example](examples/Interrupt/Interrupt.ino).<br/>
**In interrupt mode, the `micros()` function is used as timebase.**

The IRMP **send** library works by bit banging the output pin at a frequency of 38 kHz. This **avoids blocking waits** and allows to choose an **arbitrary pin**, you are not restricted to PWM generating pins like pin 3 or 11. The interrupts for send pin bit banging require 50% CPU time on a 16 MHz AVR.<br/>
If both receiving and sending is required, the timer is set up for receiving and reconfigured for the duration of sending data, thus preventing receiving in polling mode while sending data.<br/>
The **tone library (using timer 2) is still available**. You can use it alternating with IR receive and send, see [ReceiveAndSend example](examples/ReceiveAndSend/ReceiveAndSend.ino).<br/>

- For AVR **timer 2 (Tone timer)** is used for receiving **and** sending.
 For variants, which have no timer 2 like ATtiny85 or ATtiny167, **timer 1** (or timer 0 for digispark core) is used.
- For SAMD **TC3** is used.
- For Apollo3 **Timer 3 segment B** is used.
- For ESP8266 and ESP32 **timer1** is used.
- For STM32 (BluePill) **timer 3 (Servo timer) channel 1** is used as default.<br/>

<br/>

# [AllProtocols](examples/AllProtocols/AllProtocols.ino) example
| Serial LCD output | Arduino Serial Monitor output |
|-|-|
| ![LCD start](pictures/Start.jpg) | ![Serial Monitor](pictures/AllProtocol_SerialMonitor.png) |

## Sample Protocols
| | | | |
|-|-|-|-|
| ![NEC](pictures/NEC_Parallel.jpg) | ![NEC42](pictures/NEC42.jpg) |![RC5](pictures/RC5.jpg) |![KASEIKYO](pictures/KASEIKYO.jpg) |
| ![DENON](pictures/DENON.jpg) |![GRUNDIG](pictures/GRUNDIG.jpg) |![IR60](pictures/IR60.jpg) |![MATSUSHITA](pictures/MATSUSHITA.jpg) |
| ![NUBERT](pictures/NUBERT.jpg) |![ONKYO](pictures/ONKYO.jpg) |![RECS80](pictures/RECS80.jpg) |![RUWIDO](pictures/RUWIDO.jpg) |
| ![SAMSUNG](pictures/SAMSUNG.jpg) |![SIEMENS](pictures/SIEMENS.jpg) |![TELEFUNKEN](pictures/TELEFUNKEN.jpg) |![TELEFUNKEN](pictures/TELEFUNKEN.jpg) |

<br/>

# Documentation at mikrocontroller.net
### English
   http://www.mikrocontroller.net/articles/IRMP_-_english<br/>
   http://www.mikrocontroller.net/articles/IRSND_-_english
### German
   http://www.mikrocontroller.net/articles/IRMP<br/>
   http://www.mikrocontroller.net/articles/IRSND
### German Forum
   https://www.mikrocontroller.net/topic/irmp-infrared-multi-protocol-decoder?goto=6996113#6996137

<br/>

# Revision History
### Version 3.7.0 - Major content contribution by Jörg Riechardt
- Support RC6A20 and RC6A28.
- Sending S100 is not supported.
- Enable repetition for IR60.
- Fix for sending on STM32 with standard peripheral library.
- Includes and initialization for RP2040
- Allow Lego with 19 kHz.

### Version 3.6.4
- Support for ESP32 core 3.x.
- Improved code for MegaTinyCore.

### Version 3.6.3
- Fixed ESP32 send timer bug.

### Version 3.6.2
- Fixed FEEDBACK_LED_IS_ACTIVE_LOW bug.
- Added Kaseikyo Panasonic decode.
- Added ATtiny88 / AVR timer1 timer support.
- Fixed unexpected leading space for irsnd_send_data(...,false).

### Version 3.6.1
- Fixed NO_LED_FEEDBACK_CODE bug.

### Version 3.6.0
- Improved timings by J�rg R.
- Support for NEC 8 bit address.
- Fixed ATmega4809 bug.
- RP2040 support added.

### Version 3.5.1
- Fixed ESP8266 `F_CPU` error introduced with 3.4.1.

### Version 3.5.0
- Renamed *.c.h and *.cpp.h to .hpp. **You must change: #include <irmp.c.h> to: #include <irmp.hpp>!**
- Fix Timer1 initialization for ATtinyX7 parts for ATTinyCore.
- Modifying *digitalWriteFast.h* to be compatible with ATTinyCore Digispark Pro default pin mapping.
- Renamed `initPCIInterrupt()` to `enablePCIInterrupt()` and added `disablePCIInterrupt()`.
- Changed return value for `irsnd_send_data()` to be false on error conditions.
- Fixed `ICACHE_RAM_ATTR` error introduced with 3.4.1.

### Version 3.4.1
- Changed default pins for ATmega328 platform from 3,4,5 to 2,3,4.
- Adapted to TinyCore 0.0.7.
- Renamed macro IRMP_TIMING_TEST_PIN to IR_TIMING_TEST_PIN.
- Changed pins in PinDefinitionsAndMore.h.
- Never send a trailing space for Arduino.
- ATTiny88 support.

### Version 3.4.0
- Added ATtiny3217 / TinyCore support.
- Added Melinera protocol and single repeat for NEC from upstream.

### Version 3.3.5
- Added TinyIRReceiver and updated IRDispatcherDemo examples.
- Fixed "enabling OUTPUT for dynamic pin" bug.
- Improved Apollo3 and MegaCore support.

### Version 3.3.4
- Removed convenience function `irmp_tone()`, since it statically allocates the tone interrupt vector 7.

### Version 3.3.3
- Added ATmega8 support.
- Added `IRSND_GENERATE_NO_SEND_RF` compile switch.
- Added function `irsnd_data_print()`.
- New SendAllProtocols example.
- New DispatcherDemo example.
- Added `IRMP_FEEDBACK_LED_PIN` compile switch.
- Removed `IRMP16` protocol from the all list.
- Added missing Leonardo support.

### Version 3.3.2
- Added missing Medion entry in `irmp_protocol_names`.
- Added function `irmp_print_protocol_name()`.
- Added Teensyduino support.
- Fixed macro redefinitions in IRSND.

### Version 3.3.1
- Fix for function `bool irmp_IsBusy()` if `IRMP_ENABLE_PIN_CHANGE_INTERRUPT` is defined.

### Version 3.3.0
- Added function `bool irmp_IsBusy()`.

### Version 3.2.3
- Fixed warning for missing `USE_ONE_TIMER_FOR_IRMP_AND_IRSND` macro.

### Version 3.2.2
- Removed blocking wait for ATmega32U4 Serial in examples.
- Restored missing line `reset interrupt flags` found by user yumkam.
- Fixed bug for sending only on no AVR platforms.

### Version 3.2.1
- Fixed bug in feedback LED handling for dynamic pins for send and receive.
- Fixed wrong timer selection for STM32F1xx / ARDUINO_ARCH_STM32.

### Version 3.2.0
- MBED support for Arduino Nano 33 BLE.
- Added ARDUINO_ARCH_STM32 definition.
- Fixed ESP8266 wrong memcpy_p definition introduced in 3.0.0.

### Version 3.1.2
- Fixed interrupt mode bug introduced by merging upstream code for version 3.1.0.
- Fixed ESP8266 wrong memcpy_p definition introduced in 3.0.0. - Fix was not complete :-(. Use 3.2.0.

### Version 3.1.1
- Added `MinimalReceiver` example.

### Version 3.1.0
- Added RF_MEDION protocol
- IRAM attribute etc.
- Fixed bug irmp_init used instead of irsnd_init
- New function irmp_print_active_protocols().
- Use timer3 for ESP32.
- Fix missing check for LED pin == 0.
- Merged upstream v3.2.2 + IRMP_ENABLE_RELEASE_DETECTION.
- Dynamic pin for feedback LED added.

### Version 3.0.0
- Support of RF (433MHz) remotes. 2 protocols **Generic 24 bit format** and **X10 format** added.
- MegaAVR (ATmega4809) support.
- Added `IRMP_IRSND_ALLOW_DYNAMIC_PINS` and extended `irmp_init()` and `irsnd_init()`to allow input, output and LED feedback pin selection at runtime.
- Support more protocols simultaneously on 32 bit CPUs.
- Use same pin and enable flag for receive and send feedback LED.
- New function `irmp_print_active_protocols()`.

### Version 2.2.1
- Improved pin layout.
- Fixed bug with stm32duino 1.9.
- Version number.
- Blink13 -> LEDFeedback.

### Version 2.2.0
- Supported **Apollo3** platform.
- Fixed DigisparkPro bug.

### Version 2.1.0
- Supported **SAMD** platform.
- IRSND enabled for non AVR platforms.

### Version 2.0.0
- Added IR send functionality (IRSND).
- Use `TIMER2_COMPB_vect` to be compatible with tone library.
- No longer required to call initPCIInterrupt() manually if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is set.
- Separated code for timer to IRTimer.hpp.
- Separated code for Pin change interrupt to irmpPinChangeInterrupt.hpp.
- Fixed wrong pin numbers for BluePill.

### Version 1.2.2
- Fixed bugs introduced in 1.2.1.
 
### Version 1.2.1
- Bug for AVR architecture fixed.
- ATtiny85 + ATtiny167 support for ATTinyCore and Digistump core.
- Support for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager.

### Version 1.2.0 - This version contains a bug for the AVR architecture
- Added STM32 M3 (BluePill) support.

### Version 1.1.0
- Added functions `irmp_disable_timer_interrupt()` and `irmp_enable_timer_interrupt()`.
- Added function `irmp_result_print(Print *aSerial)`.
- Improved examples.

### Version 1.0.1
- Added ESP8266 + ESP32 support.

# CI
The library examples are tested with GitHub Actions for the following boards:

- arduino:avr:uno
- arduino:avr:leonardo
- arduino:avr:mega
- arduino:megaavr:nona4809:mode=off
- arduino:samd:arduino_zero_native
- arduino:mbed:nano33ble
- arduino:mbed_rp2040:pico
- rp2040:rp2040:arduino_nano_connect
- digistump:avr:digispark-tiny:clock=clock16
- ATTinyCore:avr:attinyx5micr:LTO=enable,sketchclock=8pll
- ATTinyCore:avr:attinyx7micr:LTO=enable,sketchclock=16external,pinmapping=new,millis=enabled
- ATTinyCore:avr:attinyx8micr:LTO=enable,sketchclock=16external,pinmapping=mhtiny,millis=enabled  # ATtiny88 China clone board @16 MHz
- TinyCore:avr:tiny32
- esp8266:esp8266:d1_mini:eesz=4M3M,xtal=80
- esp32:esp32:featheresp32:FlashFreq=80
- STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8
- STMicroelectronics:stm32:GenL0:pnum=THUNDERPACK_L072
- stm32duino:STM32F1:genericSTM32F103C
- SparkFun:apollo3:sfe_artemis_nano

================================================
FILE: examples/AllProtocols/ADCUtils.h
================================================
/*
 * ADCUtils.h
 *
 *  Copyright (C) 2016-2022  Armin Joachimsmeyer
 *  Email: armin.joachimsmeyer@gmail.com
 *
 *  This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
 *
 *  ArduinoUtils is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#ifndef _ADC_UTILS_H
#define _ADC_UTILS_H

#include <Arduino.h>

#if defined(__AVR__) && defined(ADCSRA) && defined(ADATE) && (!defined(__AVR_ATmega4809__))
#define ADC_UTILS_ARE_AVAILABLE

// External Reference Current is 150 uA for 5 V and 100 uA for 3.5 V
#define READING_FOR_AREF 1024 // Datasheet 24.2: The minimum value represents GND and the maximum value represents the voltage on the AREF pin minus 1 LSB
#define MAX_ADC_VALUE    1023

// PRESCALE4 => 13 * 4 = 52 microseconds per ADC conversion at 1 MHz Clock => 19,2 kHz
#define ADC_PRESCALE2    1 // 26 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE4    2 // 52 microseconds per ADC conversion at 1 MHz
// PRESCALE8 => 13 * 8 = 104 microseconds per ADC sample at 1 MHz Clock => 9,6 kHz
#define ADC_PRESCALE8    3 // 104 microseconds per ADC conversion at 1 MHz
#define ADC_PRESCALE16   4 // 13/208 microseconds per ADC conversion at 16/1 MHz - degradations in linearity at 16 MHz
#define ADC_PRESCALE32   5 // 26/416 microseconds per ADC conversion at 16/1 MHz - very good linearity at 16 MHz
#define ADC_PRESCALE64   6 // 52 microseconds per ADC conversion at 16 MHz
#define ADC_PRESCALE128  7 // 104 microseconds per ADC conversion at 16 MHz --- Arduino default

// definitions for 0.1 ms conversion time
#if (F_CPU == 1000000)
#define ADC_PRESCALE ADC_PRESCALE8
#elif (F_CPU == 8000000)
#define ADC_PRESCALE ADC_PRESCALE64
#elif (F_CPU == 16000000)
#define ADC_PRESCALE ADC_PRESCALE128
#endif

/*
 * Reference shift values are complicated for ATtinyX5 since we have the extra register bit REFS2
 * in ATTinyCore, this bit is handled programmatical and therefore the defines are different.
 * To keep my library small, I use the changed defines.
 * After including this file you can not call the ATTinyCore readAnalog functions reliable, if you specify references other than default!
 */
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
// defines are for ADCUtils.cpp, they can be used WITHOUT bit reordering
#undef DEFAULT
#undef EXTERNAL
#undef INTERNAL1V1
#undef INTERNAL
#undef INTERNAL2V56
#undef INTERNAL2V56_EXTCAP

#define DEFAULT 0
#define EXTERNAL 4
#define INTERNAL1V1 8
#define INTERNAL INTERNAL1V1
#define INTERNAL2V56 9
#define INTERNAL2V56_EXTCAP 13

#define SHIFT_VALUE_FOR_REFERENCE REFS2
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1) | _BV(REFS2))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#else // AVR_ATtiny85

#define SHIFT_VALUE_FOR_REFERENCE REFS0
#define MASK_FOR_ADC_REFERENCE (_BV(REFS0) | _BV(REFS1))
#define MASK_FOR_ADC_CHANNELS (_BV(MUX0) | _BV(MUX1) | _BV(MUX2) | _BV(MUX3))
#endif

// Temperature channel definitions - 1 LSB / 1 degree Celsius
#if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#define ADC_TEMPERATURE_CHANNEL_MUX 15
#define ADC_1_1_VOLT_CHANNEL_MUX    12
#define ADC_GND_CHANNEL_MUX         13
#define ADC_CHANNEL_MUX_MASK        0x0F

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define ADC_ISCR_CHANNEL_MUX         3
#define ADC_TEMPERATURE_CHANNEL_MUX 11
#define ADC_1_1_VOLT_CHANNEL_MUX    12
#define ADC_GND_CHANNEL_MUX         14
#define ADC_VCC_4TH_CHANNEL_MUX     13
#define ADC_CHANNEL_MUX_MASK        0x1F

#elif defined(__AVR_ATmega328P__)
#define ADC_TEMPERATURE_CHANNEL_MUX  8
#define ADC_1_1_VOLT_CHANNEL_MUX    14
#define ADC_GND_CHANNEL_MUX         15
#define ADC_CHANNEL_MUX_MASK        0x0F

#elif defined(__AVR_ATmega644P__)
#define ADC_TEMPERATURE_CHANNEL_MUX  // not existent
#define ADC_1_1_VOLT_CHANNEL_MUX    0x1E
#define ADC_GND_CHANNEL_MUX         0x1F
#define ADC_CHANNEL_MUX_MASK        0x0F

#elif defined(__AVR_ATmega32U4__)
#define ADC_TEMPERATURE_CHANNEL_MUX 0x27
#define ADC_1_1_VOLT_CHANNEL_MUX    0x1E
#define ADC_GND_CHANNEL_MUX         0x1F
#define ADC_CHANNEL_MUX_MASK        0x3F

#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define ADC_1_1_VOLT_CHANNEL_MUX    0x1E
#define ADC_GND_CHANNEL_MUX         0x1F
#define ADC_CHANNEL_MUX_MASK        0x1F

#define INTERNAL INTERNAL1V1

#else
#error "No temperature channel definitions specified for this AVR CPU"
#endif

/*
 * Thresholds for OVER and UNDER voltage and detection of kind of power supply (USB or Li-ion)
 *
 * Default values are suitable for Li-ion batteries.
 * We normally have voltage drop at the connectors, so the battery voltage is assumed slightly higher, than the Arduino VCC.
 * But keep in mind that the ultrasonic distance module HC-SR04 may not work reliable below 3.7 volt.
 */
#if !defined(LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT             3400 // Do not stress your battery and we require some power for standby
#endif
#if !defined(LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT   3000 // Many Li-ions are specified down to 3.0 volt
#endif

#if !defined(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT            LI_ION_VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT  LI_ION_VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif
#if !defined(VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT             5250 // + 5 % operation voltage
#endif
#if !defined(VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT)
#define VCC_EMERGENCY_OVERVOLTAGE_THRESHOLD_MILLIVOLT   5500 // +10 %. Max recommended operation voltage
#endif
#if !defined(VCC_CHECK_PERIOD_MILLIS)
#define VCC_CHECK_PERIOD_MILLIS                         10000L // 10 seconds period of VCC checks
#endif
#if !defined(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP)
#define VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP     6 // Shutdown after 6 times (60 seconds) VCC below VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT or 1 time below VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT
#endif

#if !defined(VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT   4300 // Assume USB powered above this voltage
#endif

#if !defined(VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT)
#define VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT   4950 // Assume USB powered below this voltage, because of the loss in USB cable. If we have > 4950, we assume to be powered by VIN.
// In contrast to e.g. powered by VIN, which results in almost perfect 5 volt supply
#endif

extern long sLastVCCCheckMillis;
extern uint8_t sVCCTooLowCounter;

uint16_t readADCChannel();
uint16_t readADCChannel(uint8_t aADCChannelNumber);
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber);
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent);
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference);
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples);
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples);
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
        uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples);
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire);
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
        uint8_t aAllowedDifference, uint8_t aMaxRetries);

void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber);
void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber);
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference);

/*
 * readVCC*() functions store the result in sVCCVoltageMillivolt or sVCCVoltage
 */
float getVCCVoltageSimple(void);
void readVCCVoltageSimple(void);
void readVCCVoltageMillivoltSimple(void);
void readVCCVoltage(void);
uint16_t getVCCVoltageMillivolt(void);
void readVCCVoltageMillivolt(void);
uint16_t getVCCVoltageReadingFor1_1VoltReference(void);
uint16_t printVCCVoltageMillivolt(Print *aSerial);
void readAndPrintVCCVoltageMillivolt(Print *aSerial);

uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement);
uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement);
float getCPUTemperatureSimple(void);
float getCPUTemperature(void);
float getTemperature(void) __attribute__ ((deprecated ("Renamed to getCPUTemperature()"))); // deprecated

bool isVCCUSBPowered();
bool isVCCUSBPowered(Print *aSerial);
bool isVCCUndervoltageMultipleTimes();
void resetCounterForVCCUndervoltageMultipleTimes();
bool isVCCUndervoltage();
bool isVCCEmergencyUndervoltage();
bool isVCCOvervoltage();
bool isVCCOvervoltageSimple();  // Version using readVCCVoltageMillivoltSimple()
bool isVCCTooHighSimple();      // Version not using readVCCVoltageMillivoltSimple()

#endif //  defined(__AVR__) ...

/*
 * The next variables and functions are defined as stubs on non-AVR platforms to allow for seamless compiling
 */
extern float sVCCVoltage;
extern uint16_t sVCCVoltageMillivolt;

uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent);

uint16_t getVCCVoltageMillivoltSimple(void);
float getVCCVoltage(void);
float getCPUTemperature(void);

#endif // _ADC_UTILS_H


================================================
FILE: examples/AllProtocols/ADCUtils.hpp
================================================
/*
 * ADCUtils.hpp
 *
 * ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in ADCUtils.h.
 *
 *  Copyright (C) 2016-2023  Armin Joachimsmeyer
 *  Email: armin.joachimsmeyer@gmail.com
 *
 *  This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils.
 *
 *  ArduinoUtils is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 */

#ifndef _ADC_UTILS_HPP
#define _ADC_UTILS_HPP

#include "ADCUtils.h"
#if defined(ADC_UTILS_ARE_AVAILABLE) // set in ADCUtils.h, if supported architecture was detected
#define ADC_UTILS_ARE_INCLUDED

// Helper macro for getting a macro definition as string
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif
#if !defined(BITS_PER_BYTE)
#define BITS_PER_BYTE 8
#endif

/*
 * By replacing this value with the voltage you measured a the AREF pin after a conversion
 * with INTERNAL you can calibrate your ADC readout. For my Nanos I measured e.g. 1060 mV and 1093 mV.
 */
#if !defined(ADC_INTERNAL_REFERENCE_MILLIVOLT)
#define ADC_INTERNAL_REFERENCE_MILLIVOLT    1100 // Change to value measured at the AREF pin. If value > real AREF voltage, measured values are > real values
#endif

// Union to speed up the combination of low and high bytes to a word
// it is not optimal since the compiler still generates 2 unnecessary moves
// but using  -- value = (high << 8) | low -- gives 5 unnecessary instructions
union WordUnionForADCUtils {
    struct {
        uint8_t LowByte;
        uint8_t HighByte;
    } UByte;
    uint16_t UWord;
    int16_t Word;
    uint8_t *BytePointer;
};

/*
 * Enable this to see information on each call.
 * Since there should be no library which uses Serial, it should only be enabled for development purposes.
 */
#if defined(DEBUG)
#define LOCAL_DEBUG
#else
//#define LOCAL_DEBUG // This enables debug output only for this file
#endif
#if defined(INFO)
#define LOCAL_INFO
#else
//#define LOCAL_INFO // This enables debug output only for this file
#endif

/*
 * Persistent storage for VCC value
 */
float sVCCVoltage;
uint16_t sVCCVoltageMillivolt;

// for isVCCTooLowMultipleTimes()
long sLastVCCCheckMillis;
uint8_t sVCCTooLowCounter = 0;

/*
 * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
 * Use previous settings
 */
uint16_t readADCChannel() {
    WordUnionForADCUtils tUValue;

    // ADCSRB = 0; // Only active if ADATE is set to 1.
    // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);

    // wait for single conversion to finish
    loop_until_bit_is_clear(ADCSRA, ADSC);

    // Get value
    tUValue.UByte.LowByte = ADCL;
    tUValue.UByte.HighByte = ADCH;
    return tUValue.UWord;
    //    return ADCL | (ADCH <<8); // needs 4 bytes more
}

/*
 * Use new channel aADCChannelNumber, but do not wait for channel switching
 */
uint16_t readADCChannel(uint8_t aADCChannelNumber) {
    WordUnionForADCUtils tUValue;
    ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);

    // ADCSRB = 0; // Only active if ADATE is set to 1.
    // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);

    // wait for single conversion to finish
    loop_until_bit_is_clear(ADCSRA, ADSC);

    // Get value
    tUValue.UByte.LowByte = ADCL;
    tUValue.UByte.HighByte = ADCH;
    return tUValue.UWord;
    //    return ADCL | (ADCH <<8); // needs 4 bytes more
}
/*
 * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
 */
uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
    WordUnionForADCUtils tUValue;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    // ADCSRB = 0; // Only active if ADATE is set to 1.
    // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);

    // wait for single conversion to finish
    loop_until_bit_is_clear(ADCSRA, ADSC);

    // Get value
    tUValue.UByte.LowByte = ADCL;
    tUValue.UByte.HighByte = ADCH;
    return tUValue.UWord;
}

uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCChannelNumber) {
    WordUnionForADCUtils tUValue;
    ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE);

    // ADCSRB = 0; // Only active if ADATE is set to 1.
    // ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE);

    // wait for single conversion to finish
    loop_until_bit_is_clear(ADCSRA, ADSC);

    // Get value
    tUValue.UByte.LowByte = ADCL;
    tUValue.UByte.HighByte = ADCH;
    return tUValue.UWord;
}
/*
 * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
 * Does NOT restore ADMUX after reading
 */
uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t aReference) {
    checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
    return readADCChannelWithReference(aADCChannelNumber, aReference);
}

/*
 * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
 * Restores ADMUX after reading
 */
uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(uint8_t aADCChannelNumber, uint8_t aReference) {
    uint8_t tOldADMUX = checkAndWaitForReferenceAndChannelToSwitch(aADCChannelNumber, aReference);
    uint16_t tResult = readADCChannelWithReference(aADCChannelNumber, aReference);
    checkAndWaitForReferenceAndChannelToSwitch(tOldADMUX & MASK_FOR_ADC_CHANNELS, tOldADMUX >> SHIFT_VALUE_FOR_REFERENCE);
    return tResult;
}

/*
 * To prepare reference and ADMUX for next measurement
 */
void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumber, uint8_t aReference) {
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);
}

/*
 * 100 kOhm requires < 100 us, 1 MOhm requires 120 us S&H switching time
 */
void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t aADCChannelNumber) {
    ADMUX = aADCChannelNumber | (INTERNAL << SHIFT_VALUE_FOR_REFERENCE);
    delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
}

void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t aADCChannelNumber) {
    ADMUX = aADCChannelNumber | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
    delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
}

/*
 * @return original ADMUX register content for optional later restoring values
 * All experimental values are acquired by using the ADCSwitchingTest example from this library
 */
uint8_t checkAndWaitForReferenceAndChannelToSwitch(uint8_t aADCChannelNumber, uint8_t aReference) {
    uint8_t tOldADMUX = ADMUX;
    /*
     * Must wait >= 7 us if reference has to be switched from 1.1 volt/INTERNAL to VCC/DEFAULT (seen on oscilloscope)
     * This is done after the 2 ADC clock cycles required for Sample & Hold :-)
     *
     * Must wait >= 7600 us for Nano board  >= 6200 for Uno board if reference has to be switched from VCC/DEFAULT to 1.1 volt/INTERNAL
     * Must wait >= 200 us if channel has to be switched to 1.1 volt internal channel if S&H was at 5 Volt
     */
    uint8_t tNewReference = (aReference << SHIFT_VALUE_FOR_REFERENCE);
    ADMUX = aADCChannelNumber | tNewReference;
#if defined(INTERNAL2V56)
    if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && (aReference == INTERNAL || aReference == INTERNAL2V56)) {
#else
    if ((tOldADMUX & MASK_FOR_ADC_REFERENCE) != tNewReference && aReference == INTERNAL) {
#endif
#if defined(LOCAL_DEBUG)
        Serial.println(F("Switch from DEFAULT to INTERNAL"));
#endif
        /*
         * Switch reference from DEFAULT to INTERNAL
         */
        delayMicroseconds(8000); // experimental value is >= 7600 us for Nano board and 6200 for Uno board
    } else if ((tOldADMUX & ADC_CHANNEL_MUX_MASK) != aADCChannelNumber) {
        if (aADCChannelNumber == ADC_1_1_VOLT_CHANNEL_MUX) {
            /*
             * Internal 1.1 Volt channel requires  <= 200 us for Nano board
             */
            delayMicroseconds(350); // 350 was ok and 300 was too less for UltimateBatteryTester - result was 226 instead of 225
        } else {
            /*
             * 100 kOhm requires < 100 us, 1 MOhm requires 120 us S&H switching time
             */
            delayMicroseconds(120); // experimental value is <= 1100 us for Nano board
        }
    }
    return tOldADMUX;
}

/*
 * Oversample and multiple samples only makes sense if you expect a noisy input signal
 * It does NOT increase the precision of the measurement, since the ADC has insignificant noise
 */
uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t aOversampleExponent) {
    return readADCChannelWithReferenceOversample(aADCChannelNumber, DEFAULT, aOversampleExponent);
}

/*
 * Conversion time is defined as 0.104 milliseconds by ADC_PRESCALE in ADCUtils.h.
 */
uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
    uint16_t tSumValue = 0;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE);

    uint8_t tCount = _BV(aOversampleExponent);
    for (uint8_t i = 0; i < tCount; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // Add value
        tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
        // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    // return rounded value
    return ((tSumValue + (tCount >> 1)) >> aOversampleExponent);
}

/*
 * Use ADC_PRESCALE32 which gives 26 us conversion time and good linearity for 16 MHz Arduino
 */
uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aOversampleExponent) {
    uint16_t tSumValue = 0;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE32);

    uint8_t tCount = _BV(aOversampleExponent);
    for (uint8_t i = 0; i < tCount; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // Add value
        tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
        // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    return ((tSumValue + (tCount >> 1)) >> aOversampleExponent);
}

/*
 * Returns sum of all sample values
 * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino by ADC_PRESCALE (=ADC_PRESCALE128) in ADCUtils.h.
 * @ param aNumberOfSamples If > 64 an overflow may occur.
 */
uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aNumberOfSamples) {
    uint16_t tSumValue = 0;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE);

    for (uint8_t i = 0; i < aNumberOfSamples; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // Add value
        tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
        // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    return tSumValue;
}

/*
 * Returns sum of all sample values
 * Conversion time is defined as 0.104 milliseconds for 16 MHz Arduino for ADC_PRESCALE128 in ADCUtils.h.
 * @ param aPrescale can be one of ADC_PRESCALE2, ADC_PRESCALE4, 8, 16, 32, 64, 128.
 *                   ADC_PRESCALE32 is recommended for excellent linearity and fast readout of 26 microseconds
 * @ param aNumberOfSamples If > 16k an overflow may occur.
 */
uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aPrescale,
        uint16_t aNumberOfSamples) {
    uint32_t tSumValue = 0;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);

    for (uint16_t i = 0; i < aNumberOfSamples; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // Add value
        tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
        // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    return tSumValue;
}

/*
 * Returns sum of all sample values
 * Assumes, that channel and reference are still set to the right values
 * @ param aNumberOfSamples If > 16k an overflow may occur.
 */
uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberOfSamples) {
    uint32_t tSumValue = 0;

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | aPrescale);

    for (uint16_t i = 0; i < aNumberOfSamples; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // Add value
        tSumValue += ADCL | (ADCH << 8); // using WordUnionForADCUtils does not save space here
        // tSumValue += (ADCH << 8) | ADCL; // this does NOT work!
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    return tSumValue;
}
/*
 * use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
 * @return the maximum value of aNumberOfSamples samples.
 */
uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aNumberOfSamples) {
    uint16_t tADCValue = 0;
    uint16_t tMaximum = 0;
    ADMUX = aADCChannelNumber | (aReference << SHIFT_VALUE_FOR_REFERENCE);

    ADCSRB = 0; // Free running mode. Only active if ADATE is set to 1.
    // ADSC-StartConversion ADATE-AutoTriggerEnable ADIF-Reset Interrupt Flag
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE) | _BV(ADIF) | ADC_PRESCALE32);

    for (uint16_t i = 0; i < aNumberOfSamples; i++) {
        /*
         * wait for free running conversion to finish.
         * Do not wait for ADSC here, since ADSC is only low for 1 ADC Clock cycle on free running conversion.
         */
        loop_until_bit_is_set(ADCSRA, ADIF);

        ADCSRA |= _BV(ADIF); // clear bit to enable recognizing next conversion has finished
        // check value
        tADCValue = ADCL | (ADCH << 8);
        if (tADCValue > tMaximum) {
            tMaximum = tADCValue;
        }
    }
    ADCSRA &= ~_BV(ADATE); // Disable auto-triggering (free running mode)
    return tMaximum;
}

/*
 * use ADC_PRESCALE32 which gives 26 us conversion time and good linearity
 * @return the maximum value during aMicrosecondsToAquire measurement.
 */
uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber, uint8_t aReference, uint16_t aMicrosecondsToAquire) {
    uint16_t tNumberOfSamples = aMicrosecondsToAquire / 26;
    return readADCChannelWithReferenceMax(aADCChannelNumber, aReference, tNumberOfSamples);
}

/*
 * aMaxRetries = 255 -> try forever
 * @return (tMax + tMin) / 2
 */
uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, uint8_t aReference, uint8_t aDelay,
        uint8_t aAllowedDifference, uint8_t aMaxRetries) {
    int tValues[4]; // last value is in tValues[3]
    int tMin;
    int tMax;

    /*
     * Initialize first 4 values before checking
     */
    tValues[0] = readADCChannelWithReference(aADCChannelNumber, aReference);
    for (int i = 1; i < 4; ++i) {
        if (aDelay != 0) {
            delay(aDelay); // Minimum is only 3 delays!
        }
        tValues[i] = readADCChannelWithReference(aADCChannelNumber, aReference);
    }

    do {
        /*
         * Get min and max of the last 4 values
         */
        tMin = READING_FOR_AREF;
        tMax = 0;
        for (uint_fast8_t i = 0; i < 4; ++i) {
            if (tValues[i] < tMin) {
                tMin = tValues[i];
            }
            if (tValues[i] > tMax) {
                tMax = tValues[i];
            }
        }
        /*
         * check for terminating condition
         */
        if ((tMax - tMin) <= aAllowedDifference) {
            break;
        } else {
            /*
             * Get next value
             */
//            Serial.print("Difference=");
//            Serial.println(tMax - tMin);
            // Move values to front
            for (int i = 0; i < 3; ++i) {
                tValues[i] = tValues[i + 1];
            }
            // and wait before getting next value
            if (aDelay != 0) {
                delay(aDelay);
            }
            tValues[3] = readADCChannelWithReference(aADCChannelNumber, aReference);
        }
        if (aMaxRetries != 255) {
            aMaxRetries--;
        }
    } while (aMaxRetries > 0);

#if defined(LOCAL_DEBUG)
    if(aMaxRetries == 0) {
        Serial.print(F("No 4 equal values for difference "));
        Serial.print(aAllowedDifference);
        Serial.print(F(" found "));
        Serial.print(tValues[0]);
        Serial.print(' ');
        Serial.print(tValues[1]);
        Serial.print(' ');
        Serial.print(tValues[2]);
        Serial.print(' ');
        Serial.println(tValues[3]);
    } else {
        Serial.print(aMaxRetries);
        Serial.println(F(" retries left"));
    }
#endif

    return (tMax + tMin) / 2;
}

/*
 * !!! Function without handling of switched reference and channel.!!!
 * Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
 * !!! Resolution is only 20 millivolt !!!
 * Raw reading of 1.1 V is 225 at 5 V.
 * Raw reading of 1.1 V is 221 at 5.1 V.
 * Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
 * Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
 */
float getVCCVoltageSimple(void) {
    // use AVCC with (optional) external capacitor at AREF pin as reference
    float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
    return ((READING_FOR_AREF * 1.1 * 4) / tVCC);
}

/*
 * !!! Function without handling of switched reference and channel.!!!
 * Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
 * !!! Resolution is only 20 millivolt !!!
 */
uint16_t getVCCVoltageMillivoltSimple(void) {
    // use AVCC with external capacitor at AREF pin as reference
    uint16_t tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
    return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCC);
}

/*
 * Gets the hypothetical 14 bit reading of VCC using 1.1 volt reference
 * Similar to getVCCVoltageMillivolt() * 1024 / 1100
 */
uint16_t getVCCVoltageReadingFor1_1VoltReference(void) {
    uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
    /*
     * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
     */
    return (((uint32_t)READING_FOR_AREF * READING_FOR_AREF) / tVCC);
}

/*
 * !!! Resolution is only 20 millivolt !!!
 */
float getVCCVoltage(void) {
    return (getVCCVoltageMillivolt() / 1000.0);
}

/*
 * Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference.
 * Handles reference and channel switching by introducing the appropriate delays.
 * !!! Resolution is only 20 millivolt !!!
 * Raw reading of 1.1 V is 225 at 5 V.
 * Raw reading of 1.1 V is 221 at 5.1 V.
 * Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
 * Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
 */
uint16_t getVCCVoltageMillivolt(void) {
    uint16_t tVCC = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
    /*
     * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
     */
    return (((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCC);
}

/*
 * Does not set sVCCVoltageMillivolt
 */
uint16_t printVCCVoltageMillivolt(Print *aSerial) {
    aSerial->print(F("VCC="));
    uint16_t tVCCVoltageMillivolt = getVCCVoltageMillivolt();
    aSerial->print(tVCCVoltageMillivolt);
    aSerial->println(" mV");
    return tVCCVoltageMillivolt;
}

void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
    aSerial->print(F("VCC="));
    sVCCVoltageMillivolt = getVCCVoltageMillivolt();
    aSerial->print(sVCCVoltageMillivolt);
    aSerial->println(" mV");
}
/*
 * !!! Function without handling of switched reference and channel.!!!
 * Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
 * !!! Resolution is only 20 millivolt !!!
 */
void readVCCVoltageSimple(void) {
    // use AVCC with (optional) external capacitor at AREF pin as reference
    float tVCC = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
    sVCCVoltage = (READING_FOR_AREF * (((float) ADC_INTERNAL_REFERENCE_MILLIVOLT) / 1000) * 4) / tVCC;
}

/*
 * !!! Function without handling of switched reference and channel.!!!
 * Use it ONLY if you only call getVCCVoltageSimple() or getVCCVoltageMillivoltSimple() in your program.
 * !!! Resolution is only 20 millivolt !!!
 */
void readVCCVoltageMillivoltSimple(void) {
    // use AVCC with external capacitor at AREF pin as reference
    uint16_t tVCCVoltageMillivoltRaw = readADCChannelMultiSamplesWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT, 4);
    sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT * 4) / tVCCVoltageMillivoltRaw;
}

/*
 * !!! Resolution is only 20 millivolt !!!
 */
void readVCCVoltage(void) {
    sVCCVoltage = getVCCVoltageMillivolt() / 1000.0;
}

/*
 * Read value of 1.1 volt internal channel using VCC (DEFAULT) as reference.
 * Handles reference and channel switching by introducing the appropriate delays.
 * !!! Resolution is only 20 millivolt !!!
 * Sets also the sVCCVoltageMillivolt variable.
 */
void readVCCVoltageMillivolt(void) {
    uint16_t tVCCVoltageMillivoltRaw = waitAndReadADCChannelWithReference(ADC_1_1_VOLT_CHANNEL_MUX, DEFAULT);
    /*
     * Do not switch back ADMUX to enable checkAndWaitForReferenceAndChannelToSwitch() to work correctly for the next measurement
     */
    sVCCVoltageMillivolt = ((uint32_t)READING_FOR_AREF * ADC_INTERNAL_REFERENCE_MILLIVOLT) / tVCCVoltageMillivoltRaw;
}

/*
 * Get voltage at ADC channel aADCChannelForVoltageMeasurement
 * aVCCVoltageMillivolt is assumed as reference voltage
 */
uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADCChannelForVoltageMeasurement) {
    uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
    return (aVCCVoltageMillivolt * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}

/*
 * Get voltage at ADC channel aADCChannelForVoltageMeasurement
 * Reference voltage VCC is determined just before
 */
uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
    uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, DEFAULT);
    return (getVCCVoltageMillivolt() * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}

uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelForVoltageMeasurement) {
    uint16_t tInputVoltageRaw = waitAndReadADCChannelWithReference(aADCChannelForVoltageMeasurement, INTERNAL);
    return (ADC_INTERNAL_REFERENCE_MILLIVOLT * (uint32_t) tInputVoltageRaw) / READING_FOR_AREF;
}

/*
 * Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
 * This does not really work for the UNO board, because it has no series Diode in the USB VCC
 * and therefore a very low voltage drop.
 */
bool isVCCUSBPowered() {
    readVCCVoltageMillivolt();
    return (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT < sVCCVoltageMillivolt
            && sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT);
}

/*
 * Return true if sVCCVoltageMillivolt is > 4.3 V and < 4.95 V
 */
bool isVCCUSBPowered(Print *aSerial) {
    readVCCVoltageMillivolt();
    aSerial->print(F("USB powered is "));
    bool tReturnValue;
    if (VOLTAGE_USB_POWERED_LOWER_THRESHOLD_MILLIVOLT
            < sVCCVoltageMillivolt&& sVCCVoltageMillivolt < VOLTAGE_USB_POWERED_UPPER_THRESHOLD_MILLIVOLT) {
        tReturnValue = true;
        aSerial->print(F("true "));
    } else {
        tReturnValue = false;
        aSerial->print(F("false "));
    }
    printVCCVoltageMillivolt(aSerial);
    return tReturnValue;
}

/*
 * It checks every 10 seconds for 6 times, and then returns once true if the undervoltage condition ( <3.4V ) still applies.
 * @ return true only once, when VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times voltage too low -> shutdown
 */
bool isVCCUndervoltageMultipleTimes() {
    /*
     * Check VCC every VCC_CHECK_PERIOD_MILLIS - default is 10 seconds
     */
    if (millis() - sLastVCCCheckMillis >= VCC_CHECK_PERIOD_MILLIS) {
        sLastVCCCheckMillis = millis();

#  if defined(INFO)
        readAndPrintVCCVoltageMillivolt(&Serial);
#  else
        readVCCVoltageMillivolt();
#  endif

        /*
         * Do not check again if shutdown signaling (sVCCTooLowCounter >= 6) has happened
         */
        if (sVCCTooLowCounter < VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) { // VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP = 6
            if (sVCCVoltageMillivolt > VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
                sVCCTooLowCounter = 0; // reset counter
            } else {
                /*
                 * Voltage too low, wait VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP (6) times and then signal shut down.
                 */
                if (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) {
                    // emergency shutdown
                    sVCCTooLowCounter = VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP;
#  if defined(LOCAL_INFO)
                    Serial.println(
                            F(
                                    "Undervoltage < " STR(VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV detected -> emergency shutdown"));
#  endif
                } else {
                    sVCCTooLowCounter++;
#  if defined(LOCAL_INFO)
                    Serial.print(sVCCVoltageMillivolt);
                    Serial.print(F(" mV < " STR(VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT) " mV -> undervoltage detected: "));

                    Serial.print(VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP - sVCCTooLowCounter);
                    Serial.println(F(" attempts left"));
#  endif
                }
                if (sVCCTooLowCounter == VCC_UNDERVOLTAGE_CHECKS_BEFORE_STOP) {
                    /*
                     * 6 times voltage too low -> return signal for shutdown etc.
                     */
                    return true;
                }
            }
        }
    }
    return false;
}

/*
 * Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached
 */
bool isVCCUndervoltage() {
    readVCCVoltageMillivolt();
    return (sVCCVoltageMillivolt < VCC_UNDERVOLTAGE_THRESHOLD_MILLIVOLT);
}

/*
 * Return true if VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT (3 V) reached
 */
bool isVCCEmergencyUndervoltage() {
    readVCCVoltageMillivolt();
    return (sVCCVoltageMillivolt < VCC_EMERGENCY_UNDERVOLTAGE_THRESHOLD_MILLIVOLT);
}

void resetCounterForVCCUndervoltageMultipleTimes() {
    sVCCTooLowCounter = 0;
}

/*
 * Recommended VCC is 1.8 V to 5.5 V, absolute maximum VCC is 6.0 V.
 * Check for 5.25 V, because such overvoltage is quite unlikely to happen during regular operation.
 * Raw reading of 1.1 V is 225 at 5 V.
 * Raw reading of 1.1 V is 221 at 5.1 V.
 * Raw reading of 1.1 V is 214 at 5.25 V (+5 %).
 * Raw reading of 1.1 V is 204 at 5.5 V (+10 %).
 * Raw reading of 1.1 V is 1126000 / VCC_MILLIVOLT
 * @return true if 5 % overvoltage reached
 */
bool isVCCOvervoltage() {
    readVCCVoltageMillivolt();
    return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}
bool isVCCOvervoltageSimple() {
    readVCCVoltageMillivoltSimple();
    return (sVCCVoltageMillivolt > VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT);
}

// Version not using readVCCVoltageMillivoltSimple()
bool isVCCTooHighSimple() {
    ADMUX = ADC_1_1_VOLT_CHANNEL_MUX | (DEFAULT << SHIFT_VALUE_FOR_REFERENCE);
// ADCSRB = 0; // Only active if ADATE is set to 1.
// ADSC-StartConversion ADIF-Reset Interrupt Flag - NOT free running mode
    ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADIF) | ADC_PRESCALE128); //  128 -> 104 microseconds per ADC conversion at 16 MHz --- Arduino default
// wait for single conversion to finish
    loop_until_bit_is_clear(ADCSRA, ADSC);

// Get value
    uint16_t tRawValue = ADCL | (ADCH << 8);

    return tRawValue < 1126000 / VCC_OVERVOLTAGE_THRESHOLD_MILLIVOLT;
}

/*
 * Temperature sensor is enabled by selecting the appropriate channel.
 * Different formula for 328P and 328PB!
 * !!! Function without handling of switched reference and channel.!!!
 * Use it ONLY if you only use INTERNAL reference (e.g. only call getTemperatureSimple()) in your program.
 */
float getCPUTemperatureSimple(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    return 0.0;
#else
    // use internal 1.1 volt as reference. 4 times oversample. Assume the signal has noise, but never verified :-(
    uint16_t tTemperatureRaw = readADCChannelWithReferenceOversample(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL, 2);
#if defined(LOCAL_DEBUG)
    Serial.print(F("TempRaw="));
    Serial.println(tTemperatureRaw);
#endif

#if defined(__AVR_ATmega328PB__)
    tTemperatureRaw -= 245;
    return (float)tTemperatureRaw;
#elif defined(__AVR_ATtiny85__)
    tTemperatureRaw -= 273; // 273 and 1.1666 are values from the datasheet
    return (float)tTemperatureRaw / 1.1666;
#else
    tTemperatureRaw -= 317;
    return (float) tTemperatureRaw / 1.22;
#endif
#endif
}

/*
 * Handles usage of 1.1 V reference and channel switching by introducing the appropriate delays.
 */
float getTemperature(void) {
    return getCPUTemperature();
}
float getCPUTemperature(void) {
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    return 0.0;
#else
    // use internal 1.1 volt as reference
    checkAndWaitForReferenceAndChannelToSwitch(ADC_TEMPERATURE_CHANNEL_MUX, INTERNAL);
    return getCPUTemperatureSimple();
#endif
}

#else // defined(ADC_UTILS_ARE_AVAILABLE)
// Dummy definition of functions defined in ADCUtils to compile examples for non AVR platforms without errors
/*
 * Persistent storage for VCC value
 */
float sVCCVoltage;
uint16_t sVCCVoltageMillivolt;

uint16_t getVCCVoltageMillivoltSimple(void){
    return 3300;
}

uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber __attribute__((unused)),
        uint8_t aReference __attribute__((unused)), uint8_t aOversampleExponent __attribute__((unused))) {
    return 0;
}
float getCPUTemperature() {
    return 20.0;
}
float getVCCVoltage() {
    return 3.3;
}
#endif // defined(ADC_UTILS_ARE_AVAILABLE)

#if defined(LOCAL_DEBUG)
#undef LOCAL_DEBUG
#endif
#if defined(LOCAL_INFO)
#undef LOCAL_INFO
#endif
#endif // _ADC_UTILS_HPP


================================================
FILE: examples/AllProtocols/AllProtocols.ino
================================================
/*
 *  AllProtocols.cpp
 *
 *  Accepts 40 protocols concurrently
 *  If you specify F_INTERRUPTS to 20000 at line 86 (default is 15000) it supports LEGO + RCMM protocols, but disables PENTAX and GREE protocols.
 *  if you see performance issues, you can disable MERLIN Protocol at line 88.
 *
 *  Uses a callback function which is called every time a complete IR command was received.
 *  Prints data to LCD connected parallel at pin 4-9 or serial at pin A4, A5
 *
 *  Copyright (C) 2019-2022  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#include <Arduino.h>

#include "PinDefinitionsAndMore.h"

/*
 * Set input pin and output pin definitions etc.
 */
#define IRMP_PROTOCOL_NAMES              1 // Enable protocol number mapping to protocol strings - needs some program memory ~ 420 bytes here
#define IRMP_USE_COMPLETE_CALLBACK       1 // Enable callback functionality
//#define NO_LED_FEEDBACK_CODE   // Activate this if you want to suppress LED feedback or if you do not have a LED. This saves 14 bytes code and 2 clock cycles per interrupt.

#if __SIZEOF_INT__ == 4
#define F_INTERRUPTS                     20000 // Instead of default 15000 to support LEGO + RCMM protocols
#else
//#define F_INTERRUPTS                     20000 // Instead of default 15000 to support LEGO + RCMM protocols, but this in turn disables PENTAX and GREE protocols :-(
//#define IRMP_32_BIT                       1 // This enables MERLIN protocol, but decreases performance for AVR.
#endif

#include <irmpSelectAllProtocols.h>  // This enables all possible protocols
//#define IRMP_SUPPORT_SIEMENS_PROTOCOL 1

/*
 * After setting the definitions we can include the code and compile it.
 */
#include <irmp.hpp>

IRMP_DATA irmp_data;

/*
 * Activate the type of LCD you use
 * Default is parallel LCD with 2 rows of 16 characters (1602).
 * Serial LCD has the disadvantage, that the first repeat is not detected,
 * because of the long lasting serial communication.
 */
//#define USE_NO_LCD
//#define USE_SERIAL_LCD
/*
 * Define the size of your LCD
 */
//#define USE_2004_LCD
#if defined(USE_2004_LCD)
// definitions for a 2004 LCD
#define LCD_COLUMNS 20
#define LCD_ROWS 4
#else
#define USE_1602_LCD
// definitions for a 1602 LCD
#define LCD_COLUMNS 16
#define LCD_ROWS 2
#endif

#if defined(USE_SERIAL_LCD)
#include "LiquidCrystal_I2C.hpp" // Use an up to date library version, which has the init method
LiquidCrystal_I2C myLCD(0x27, LCD_COLUMNS, LCD_ROWS);  // set the LCD address to 0x27 for a 16 chars and 2 line display

#elif !defined(USE_NO_LCD)
#include "LiquidCrystal.h"
#define USE_PARALLEL_LCD
//LiquidCrystal myLCD(4, 5, 6, 7, 8, 9);
LiquidCrystal myLCD(7, 8, 3, 4, 5, 6);
#endif

#if defined(USE_SERIAL_LCD) || defined(USE_PARALLEL_LCD)
#define USE_LCD
#  if defined(ADC_UTILS_ARE_AVAILABLE)
// For cyclically display of VCC
#include "ADCUtils.hpp"
#define MILLIS_BETWEEN_VOLTAGE_PRINT 5000
uint32_t volatile sMillisOfLastVoltagePrint;
#  endif

void printIRResultOnLCD();
size_t printHex(uint16_t aHexByteValue);
#endif

void handleReceivedIRData();

bool volatile sIRMPDataAvailable = false;

void setup()
{
    Serial.begin(115200);
#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
    || defined(SERIALUSB_PID)  || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217) \
    || defined(__AVR_ATtiny1616__)  || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
    delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));

    irmp_init();
    irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN
    irmp_register_complete_callback_function(&handleReceivedIRData);

    Serial.print(F("Ready to receive IR signals of protocols: "));
    irmp_print_active_protocols(&Serial);
    Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
#if defined(USE_SERIAL_LCD)
    Serial.println(F("With serial LCD connection, the first repeat is not detected, because of the long lasting serial communication!"));
#endif

#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
    getVCCVoltageMillivoltSimple(); // to initialize ADC mux and reference
#endif

#if defined(USE_SERIAL_LCD)
    myLCD.init();
    myLCD.clear();
    myLCD.backlight(); // Switch backlight LED on
#endif
#if defined(USE_PARALLEL_LCD)
    myLCD.begin(LCD_COLUMNS, LCD_ROWS); // This also clears display
#endif

#if defined(USE_LCD)
    myLCD.setCursor(0, 0);
    myLCD.print(F("IRMP all  v" VERSION_IRMP));
    myLCD.setCursor(0, 1);
    myLCD.print(F(__DATE__));
#endif
}

void loop()
{
    if (sIRMPDataAvailable)
    {
        sIRMPDataAvailable = false;

        /*
         * Serial output
         * takes 2 milliseconds at 115200
         */
        irmp_result_print(&irmp_data);

#if defined(USE_LCD)
#  if defined(USE_SERIAL_LCD)
        // This suppresses the receive of the 1. NEC repeat
        disableIRTimerInterrupt(); // disable timer interrupt, since it disturbs the LCD serial output
#  endif
        printIRResultOnLCD();
#  if defined(USE_SERIAL_LCD)
        enableIRTimerInterrupt();
#  endif
#endif
    }

#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
    /*
     * Periodically print VCC
     */
    if (millis() - sMillisOfLastVoltagePrint > MILLIS_BETWEEN_VOLTAGE_PRINT)
    {
        sMillisOfLastVoltagePrint = millis();
        uint16_t tVCC = getVCCVoltageMillivoltSimple();

        char tVoltageString[5];
        dtostrf(tVCC / 1000.0, 4, 2, tVoltageString);
        myLCD.setCursor(11, 0);
        myLCD.print(tVoltageString);
        myLCD.print('V');
    }
#endif
}

/*
 * Here we know, that data is available.
 * Since this function is executed in Interrupt handler context, make it short and do not use delay() etc.
 * In order to enable other interrupts you can call interrupts() (enable interrupt again) after getting data.
 */
#if defined(ESP8266) || defined(ESP32)
void IRAM_ATTR handleReceivedIRData()
#else
void handleReceivedIRData()
#endif
{

#if defined(USE_LCD) && defined(ADC_UTILS_ARE_AVAILABLE)
    // reset voltage display timer
    sMillisOfLastVoltagePrint = millis();
#endif

    /*
     * Just print the data to Serial and LCD
     */
    irmp_get_data(&irmp_data);
    sIRMPDataAvailable = true;
}

#if defined(USE_LCD)
/*
 * LCD output for 1602 and 2004 LCDs
 * 40 - 55 Milliseconds per initial output for a 1602 LCD
 * for a 2004 LCD the initial clearing adds 55 ms.
 * The expander runs at 100 kHz :-(
 * 8 milliseconds for 8 bit; 10 ms for 16 bit code output
 * 3 milliseconds for repeat output
 *
 */
void printIRResultOnLCD()
{
    static uint8_t sLastProtocolIndex;
    static uint16_t sLastProtocolAddress;

#  if (LCD_ROWS >= 4)
    static uint8_t sLastCommandPrintPosition = 13;
    const uint8_t tStartRow = 2;

#  else
    static uint16_t sLastCommand;
    static uint8_t sLastCommandPrintPosition;

    const uint8_t tStartRow = 0;
    bool tDisplayWasCleared = false;
#  endif

    /*
     * Print only if protocol or address has changed
     */
    if (sLastProtocolIndex != irmp_data.protocol || sLastProtocolAddress != irmp_data.address)
    {
        sLastProtocolIndex = irmp_data.protocol;
        sLastProtocolAddress = irmp_data.address;
#  if (LCD_ROWS >= 4)
        // clear data lines
        myLCD.setCursor(0, tStartRow);
        myLCD.print(F("                    "));
        myLCD.setCursor(0, tStartRow + 1);
        myLCD.print(F("                    "));
#  else
        myLCD.clear();
        tDisplayWasCleared = true;
#  endif

        /*
         * Show protocol name
         */
        myLCD.setCursor(0, tStartRow);
#  if defined(__AVR__)
        const char *tProtocolStringPtr = (char*) pgm_read_word(&irmp_protocol_names[irmp_data.protocol]);
        myLCD.print((__FlashStringHelper*) (tProtocolStringPtr));
#  else
        myLCD.print(irmp_protocol_names[irmp_data.protocol]);
#  endif

        /*
         * Show address
         */
        myLCD.setCursor(0, tStartRow + 1);
        myLCD.print(F("A="));
        printHex(irmp_data.address);

#  if (LCD_COLUMNS > 16)
        /*
         * Print prefix of command here, since it is constant string
         */
        myLCD.setCursor(9, tStartRow + 1);
        myLCD.print(F("C="));
#  endif
    }
    else
    {
        /*
         * Show or clear repetition flag
         */
#  if (LCD_COLUMNS > 16)
        myLCD.setCursor(18, tStartRow + 1);
#  else
        myLCD.setCursor(15, tStartRow + 1);
#  endif
        if (irmp_data.flags & IRMP_FLAG_REPETITION)
        {
            myLCD.print('R');
            return; // Since it is a repetition, printed data has not changed
        }
        else
        {
            myLCD.print(' ');
        }
    }

    /*
     * Command prefix
     */
    uint16_t tCommand = irmp_data.command;

#  if (LCD_COLUMNS <= 16)
    // check if prefix position must change
    if (tDisplayWasCleared || (sLastCommand > 0x100 && tCommand < 0x100) || (sLastCommand < 0x100 && tCommand > 0x100))
    {
        sLastCommand = tCommand;
        /*
         * Print prefix for 8/16 bit commands
         */
        if (tCommand >= 0x100)
        {
            sLastCommandPrintPosition = 9;
        }
        else
        {
            myLCD.setCursor(9, tStartRow + 1);
            myLCD.print(F("C="));
            sLastCommandPrintPosition = 11;
        }
    }
#  endif

    /*
     * Command data
     */
    myLCD.setCursor(sLastCommandPrintPosition, tStartRow + 1);
    printHex(tCommand);
}

size_t printHex(uint16_t aHexByteValue) {
    myLCD.print(F("0x"));
    size_t tPrintSize = 2;
    if (aHexByteValue < 0x10 || (aHexByteValue > 0x100 && aHexByteValue < 0x1000)) {
        myLCD.print('0'); // leading 0
        tPrintSize++;
    }
    return myLCD.print(aHexByteValue, HEX) + tPrintSize;
}
#endif // defined(USE_LCD)


================================================
FILE: examples/AllProtocols/LiquidCrystal_I2C.h
================================================
//YWROBOT
#ifndef LiquidCrystal_I2C_h
#define LiquidCrystal_I2C_h

#include <inttypes.h>
#include "Print.h"
#if !defined(USE_SOFT_I2C_MASTER) && !defined(USE_SOFT_WIRE)
#include <Wire.h>
#endif

// commands
#define LCD_CLEARDISPLAY 0x01
#define LCD_RETURNHOME 0x02
#define LCD_ENTRYMODESET 0x04
#define LCD_DISPLAYCONTROL 0x08
#define LCD_CURSORSHIFT 0x10
#define LCD_FUNCTIONSET 0x20
#define LCD_SETCGRAMADDR 0x40
#define LCD_SETDDRAMADDR 0x80

// flags for display entry mode
#define LCD_ENTRYRIGHT 0x00
#define LCD_ENTRYLEFT 0x02
#define LCD_ENTRYSHIFTINCREMENT 0x01
#define LCD_ENTRYSHIFTDECREMENT 0x00

// flags for display on/off control
#define LCD_DISPLAYON 0x04
#define LCD_DISPLAYOFF 0x00
#define LCD_CURSORON 0x02
#define LCD_CURSOROFF 0x00
#define LCD_BLINKON 0x01
#define LCD_BLINKOFF 0x00

// flags for display/cursor shift
#define LCD_DISPLAYMOVE 0x08
#define LCD_CURSORMOVE 0x00
#define LCD_MOVERIGHT 0x04
#define LCD_MOVELEFT 0x00

// flags for function set
#define LCD_8BITMODE 0x10
#define LCD_4BITMODE 0x00
#define LCD_2LINE 0x08
#define LCD_1LINE 0x00
#define LCD_5x10DOTS 0x04
#define LCD_5x8DOTS 0x00

// flags for backlight control
#define LCD_BACKLIGHT 0x08
#define LCD_NOBACKLIGHT 0x00

#define En 0b00000100  // Enable bit
#define Rw 0b00000010  // Read/Write bit
#define Rs 0b00000001  // Register select bit

class LiquidCrystal_I2C : public Print {
public:
  LiquidCrystal_I2C(uint8_t lcd_Addr,uint8_t lcd_cols,uint8_t lcd_rows);
  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS );
  void clear();
  void home();
  void noDisplay();
  void display();
  void noBlink();
  void blink();
  void noCursor();
  void cursor();
  void scrollDisplayLeft();
  void scrollDisplayRight();
  void printLeft();
  void printRight();
  void leftToRight();
  void rightToLeft();
  void shiftIncrement();
  void shiftDecrement();
  void noBacklight();
  void backlight();
  void autoscroll();
  void noAutoscroll();
  void createChar(uint8_t, uint8_t[]);
  void createChar(uint8_t location, const char *charmap);
  // Example: 	const char bell[8] PROGMEM = {B00100,B01110,B01110,B01110,B11111,B00000,B00100,B00000};

  void setCursor(uint8_t, uint8_t);
  size_t write(uint8_t);
  void command(uint8_t);
  void init();
  void oled_init();

////compatibility API function aliases
void blink_on();						// alias for blink()
void blink_off();       					// alias for noBlink()
void cursor_on();      	 					// alias for cursor()
void cursor_off();      					// alias for noCursor()
void setBacklight(uint8_t new_val);				// alias for backlight() and nobacklight()
void load_custom_character(uint8_t char_num, uint8_t *rows);	// alias for createChar()
void printstr(const char[]);

////Unsupported API functions (not implemented in this library)
uint8_t status();
void setContrast(uint8_t new_val);
uint8_t keypad();
void setDelay(int,int);
void on();
void off();
uint8_t init_bargraph(uint8_t graphtype);
void draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);
void draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len,  uint8_t pixel_col_end);


private:
  void init_priv();
  void send(uint8_t, uint8_t);
  void write4bits(uint8_t);
  void expanderWrite(uint8_t);
  void pulseEnable(uint8_t);
  uint8_t _Addr;
  uint8_t _displayfunction;
  uint8_t _displaycontrol;
  uint8_t _displaymode;
  uint8_t _numlines;
  bool _oled;
  uint8_t _cols;
  uint8_t _rows;
  uint8_t _backlightval;
};

#endif


================================================
FILE: examples/AllProtocols/LiquidCrystal_I2C.hpp
================================================
// LiquidCrystal_I2C.hpp
// Based on the work by DFRobot
/*
 * Extensions made by AJ 2023
 * Removed Arduino 0.x support
 * Added SoftI2CMaste support, which drastically reduces program size.
 * Added OLED stuff
 * Added createChar() with PROGMEM input
 * Added fast timing
 */
#ifndef _LIQUID_CRYSTAL_I2C_HPP
#define _LIQUID_CRYSTAL_I2C_HPP

#include "Arduino.h"

#if defined(__AVR__) && !defined(USE_SOFT_I2C_MASTER) && __has_include("SoftI2CMasterConfig.h")
#define USE_SOFT_I2C_MASTER // must be before #include "LiquidCrystal_I2C.hpp"
#endif

#include "LiquidCrystal_I2C.h"
#include <inttypes.h>

inline size_t LiquidCrystal_I2C::write(uint8_t value) {
    send(value, Rs);
    return 1;
}

#if defined(USE_SOFT_I2C_MASTER)
//#define USE_SOFT_I2C_MASTER_H_AS_PLAIN_INCLUDE
#include "SoftI2CMasterConfig.h"    // Include configuration for sources
#include "SoftI2CMaster.h"          // include sources
#elif defined(USE_SOFT_WIRE)
#define USE_SOFTWIRE_H_AS_PLAIN_INCLUDE
#include "SoftWire.h"
#endif

#if defined(__AVR__)
/*
 * The datasheet says: a command need > 37us to settle. Enable pulse must be > 450ns.
 * Use no delay for enable pulse after each command,
 * because the overhead of this library seems to be using the 37 us and 450 ns.
 * At least it works perfectly for all my LCD's connected to Uno, Nano etc.
 * and it saves a lot of time in realtime applications using LCD as display,
 * like https://github.com/ArminJo/Arduino-DTSU666H_PowerMeter
 */
#define USE_FAST_TIMING
#endif

// When the display powers up, it is configured as follows:
//
// 1. Display clear
// 2. Function set:
//    DL = 1; 8-bit interface data
//    N = 0; 1-line display
//    F = 0; 5x8 dot character font
// 3. Display on/off control:
//    D = 0; Display off
//    C = 0; Cursor off
//    B = 0; Blinking off
// 4. Entry mode set:
//    I/D = 1; Increment by 1
//    S = 0; No shift
//
// Note, however, that resetting the Arduino doesn't reset the LCD, so we
// can't assume that its in that state when a sketch starts (and the
// LiquidCrystal constructor is called).

LiquidCrystal_I2C::LiquidCrystal_I2C(uint8_t lcd_Addr, uint8_t lcd_cols, uint8_t lcd_rows) {
    _Addr = lcd_Addr;
    _cols = lcd_cols;
    _rows = lcd_rows;
    _backlightval = LCD_NOBACKLIGHT;
    _oled = false;
}

void LiquidCrystal_I2C::oled_init() {
    _oled = true;
    init_priv();
}

void LiquidCrystal_I2C::init() {
    init_priv();
}

void LiquidCrystal_I2C::init_priv() {
#if defined(USE_SOFT_I2C_MASTER)
    i2c_init();
#else
    Wire.begin();
#endif
    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
    begin(_cols, _rows);
}

void LiquidCrystal_I2C::begin(uint8_t cols __attribute__((unused)), uint8_t lines, uint8_t dotsize) {
    if (lines > 1) {
        _displayfunction |= LCD_2LINE;
    }
    _numlines = lines;

    // for some 1 line displays you can select a 10 pixel high font
    if ((dotsize != 0) && (lines == 1)) {
        _displayfunction |= LCD_5x10DOTS;
    }

    // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
    // according to datasheet, we need at least 40ms after power rises above 2.7V
    // before sending commands. Arduino can turn on way before 4.5V so we'll wait 50
    delay(50);

    // Now we pull both RS and R/W low to begin commands
    expanderWrite(_backlightval);	// reset expander and turn backlight off (Bit 8 =1)
    delay(1000);

    //put the LCD into 4 bit mode
    // this is according to the hitachi HD44780 datasheet
    // figure 24, pg 46

    // we start in 8bit mode, try to set 4 bit mode
    write4bits(0x03 << 4);
    delayMicroseconds(4500); // wait min 4.1ms

    // second try
    write4bits(0x03 << 4);
    delayMicroseconds(4500); // wait min 4.1ms

    // third go!
    write4bits(0x03 << 4);
    delayMicroseconds(150);

    // finally, set to 4-bit interface
    write4bits(0x02 << 4);

    // set # lines, font size, etc.
    command(LCD_FUNCTIONSET | _displayfunction);

    // turn the display on with no cursor or blinking default
    _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;
    display();

    // clear it off
    clear();

    // Initialize to default text direction (for roman languages)
    _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;

    // set the entry mode
    command(LCD_ENTRYMODESET | _displaymode);

    home();

}

/********** high level commands, for the user! */
void LiquidCrystal_I2C::clear() {
    command(LCD_CLEARDISPLAY); // clear display, set cursor position to zero
#if defined(USE_FAST_TIMING)
    delayMicroseconds(1500);  // this command takes a long time! // AJ 20.9.23 1200 is too short for my 2004 LCD's, 1400 is OK
#else
    delayMicroseconds(2000);  // this command takes a long time!
#endif
    if (_oled)
        setCursor(0, 0);
}

void LiquidCrystal_I2C::home() {
    command(LCD_RETURNHOME);  // set cursor position to zero
    delayMicroseconds(2000);  // this command takes a long time!
}

void LiquidCrystal_I2C::setCursor(uint8_t col, uint8_t row) {
    int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
    if (row > _numlines) {
        row = _numlines - 1;    // we count rows starting w/0
    }
    command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
}

// Turn the display on/off (quickly)
void LiquidCrystal_I2C::noDisplay() {
    _displaycontrol &= ~LCD_DISPLAYON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::display() {
    _displaycontrol |= LCD_DISPLAYON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turns the underline cursor on/off
void LiquidCrystal_I2C::noCursor() {
    _displaycontrol &= ~LCD_CURSORON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::cursor() {
    _displaycontrol |= LCD_CURSORON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// Turn on and off the blinking cursor
void LiquidCrystal_I2C::noBlink() {
    _displaycontrol &= ~LCD_BLINKON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}
void LiquidCrystal_I2C::blink() {
    _displaycontrol |= LCD_BLINKON;
    command(LCD_DISPLAYCONTROL | _displaycontrol);
}

// These commands scroll the display without changing the RAM
void LiquidCrystal_I2C::scrollDisplayLeft(void) {
    command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
}
void LiquidCrystal_I2C::scrollDisplayRight(void) {
    command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
}

// This is for text that flows Left to Right
void LiquidCrystal_I2C::leftToRight(void) {
    _displaymode |= LCD_ENTRYLEFT;
    command(LCD_ENTRYMODESET | _displaymode);
}

// This is for text that flows Right to Left
void LiquidCrystal_I2C::rightToLeft(void) {
    _displaymode &= ~LCD_ENTRYLEFT;
    command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'right justify' text from the cursor
void LiquidCrystal_I2C::autoscroll(void) {
    _displaymode |= LCD_ENTRYSHIFTINCREMENT;
    command(LCD_ENTRYMODESET | _displaymode);
}

// This will 'left justify' text from the cursor
void LiquidCrystal_I2C::noAutoscroll(void) {
    _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
    command(LCD_ENTRYMODESET | _displaymode);
}

// Allows us to fill the first 8 CGRAM locations
// with custom characters
void LiquidCrystal_I2C::createChar(uint8_t location, uint8_t charmap[]) {
    location &= 0x7; // we only have 8 locations 0-7
    command(LCD_SETCGRAMADDR | (location << 3));
    for (int i = 0; i < 8; i++) {
        write(charmap[i]);
    }
}

//createChar with PROGMEM input
void LiquidCrystal_I2C::createChar(uint8_t location, const char *charmap) {
    location &= 0x7; // we only have 8 locations 0-7
    command(LCD_SETCGRAMADDR | (location << 3));
    for (int i = 0; i < 8; i++) {
        write(pgm_read_byte_near(charmap++));
    }
}

// Turn the (optional) backlight off/on
void LiquidCrystal_I2C::noBacklight(void) {
    _backlightval = LCD_NOBACKLIGHT;
    expanderWrite(0);
}

void LiquidCrystal_I2C::backlight(void) {
    _backlightval = LCD_BACKLIGHT;
    expanderWrite(0);
}

/*********** mid level commands, for sending data/cmds */

inline void LiquidCrystal_I2C::command(uint8_t value) {
    send(value, 0);
}

/************ low level data pushing commands **********/

// write either command or data
void LiquidCrystal_I2C::send(uint8_t value, uint8_t mode) {
    uint8_t highnib = value & 0xf0;
    uint8_t lownib = (value << 4) & 0xf0;
    write4bits((highnib) | mode);
    write4bits((lownib) | mode);
}

void LiquidCrystal_I2C::write4bits(uint8_t value) {
    expanderWrite(value);
    pulseEnable(value);
}

void LiquidCrystal_I2C::expanderWrite(uint8_t _data) {
#if defined(USE_SOFT_I2C_MASTER)
    i2c_write_byte(_Addr << 1, _data | _backlightval);
#else
    Wire.beginTransmission(_Addr);
    Wire.write((int )(_data) | _backlightval);
    Wire.endTransmission();
#endif
}

void LiquidCrystal_I2C::pulseEnable(uint8_t _data) {
    expanderWrite(_data | En);	// En high
#if !defined(USE_FAST_TIMING)
    delayMicroseconds(1);		// enable pulse must be > 450ns // AJ 20.9.23 not required for my LCD's
#endif
    expanderWrite(_data & ~En);	// En low
#if !defined(USE_FAST_TIMING)
    delayMicroseconds(50);      // commands need > 37us to settle // AJ 20.9.23 not required for my LCD's
#endif
}

// Alias functions

void LiquidCrystal_I2C::cursor_on() {
    cursor();
}

void LiquidCrystal_I2C::cursor_off() {
    noCursor();
}

void LiquidCrystal_I2C::blink_on() {
    blink();
}

void LiquidCrystal_I2C::blink_off() {
    noBlink();
}

void LiquidCrystal_I2C::load_custom_character(uint8_t char_num, uint8_t *rows) {
    createChar(char_num, rows);
}

void LiquidCrystal_I2C::setBacklight(uint8_t new_val) {
    if (new_val) {
        backlight();		// turn backlight on
    } else {
        noBacklight();		// turn backlight off
    }
}

void LiquidCrystal_I2C::printstr(const char c[]) {
    //This function is not identical to the function used for "real" I2C displays
    //it's here so the user sketch doesn't have to be changed
    print(c);
}

// unsupported API functions
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
void LiquidCrystal_I2C::off() {
}
void LiquidCrystal_I2C::on() {
}
void LiquidCrystal_I2C::setDelay(int cmdDelay, int charDelay) {
}
uint8_t LiquidCrystal_I2C::status() {
    return 0;
}
uint8_t LiquidCrystal_I2C::keypad() {
    return 0;
}
uint8_t LiquidCrystal_I2C::init_bargraph(uint8_t graphtype) {
    return 0;
}
void LiquidCrystal_I2C::draw_horizontal_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_col_end) {
}
void LiquidCrystal_I2C::draw_vertical_graph(uint8_t row, uint8_t column, uint8_t len, uint8_t pixel_row_end) {
}
void LiquidCrystal_I2C::setContrast(uint8_t new_val) {
}
#pragma GCC diagnostic pop

#endif // _LIQUID_CRYSTAL_I2C_HPP


================================================
FILE: examples/AllProtocols/PinDefinitionsAndMore.h
================================================
/*
 *  PinDefinitionsAndMore.h
 *
 *  Contains pin definitions for IRMP examples for various platforms
 *  as well as definitions for feedback LED and tone() and includes
 *
 *  Copyright (C) 2020-2021  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

/*
 * Pin mapping table for different platforms
 *
 * Platform     IR input    IR output   Tone      Core/Pin schema
 * --------------------------------------------------------------
 * DEFAULT/AVR  2           3           4
 * ATtinyX5     0|PB0       4|PB4       3|PB3
 * ATtiny167    3|PA3       2|PA2       7|PA7     ATTinyCore
 * ATtiny167    9|PA3       8|PA2       5|PA7     Digispark pro
 * ATtiny3216  14|PA1      15|PA2      16|PA3     MegaTinyCore
 * SAMD21       3           4           5
 * ESP8266     14|D5       12|D6        %
 * ESP32       15           4           %
 * ESP32-C3     6           7          10
 * BluePill   PA6         PA7         PA3
 * APOLLO3     11          12           5
 * RP2040       3|GPIO15    4|GPIO16    5|GPIO17
 */
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN      14 // D5
#define IRSND_OUTPUT_PIN    12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN  13 // D7

#define tone(...) void()      // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN            42 // Dummy for examples using it

#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE   // The  WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN       6
#define IRSND_OUTPUT_PIN     7
#define TONE_PIN            10

#elif defined(ESP32)
#define IRMP_INPUT_PIN      15  // D15
#define IRSND_OUTPUT_PIN     4  // D4
#include <Arduino.h>
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
#  if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
#  endif
#  if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#  endif
#if ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
    delay(aDuration);
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN                27  // D27 25 & 26 are DAC0 and 1

#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN          PA6
#define IRSND_OUTPUT_PIN        PA7
#define TONE_PIN                PA3
#define IR_TIMING_TEST_PIN      PA5

#elif  defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN   0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN         3
//#define IR_TIMING_TEST_PIN 3

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
#  if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN   9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN  14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN         5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4

#  else
#define IRMP_INPUT_PIN   3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN         7
#  endif

#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN   3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN         9
#define IR_TIMING_TEST_PIN 8

#elif defined(__AVR_ATtiny1616__)  || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN   PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN         PIN_PA3 // 16, 20 for TinyCore32

#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN   11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN         5

#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN      3   // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN    4   // GPIO16
#define TONE_PIN            5

#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN      15  // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN    16
#define TONE_PIN            17

// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN          6

#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7

#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN      2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2

#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7

// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB

// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW

#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7
#endif // defined(ESP8266)


#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif

/*
 * Helper macro for getting a macro definition as string
 */
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif


================================================
FILE: examples/Callback/Callback.ino
================================================
/*
 *  Callback.cpp
 *
 *  Uses a callback function which is called every time a complete IR command was received.
 *  This example additionally filters commands from a remote control named WM010 sending NEC commands
 *
 *  Copyright (C) 2019-2022  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#include <Arduino.h>

/*
 * Set input pin and output pin definitions etc.
 */
#include "PinDefinitionsAndMore.h"

#define IRMP_PROTOCOL_NAMES         1 // Enable protocol number mapping to protocol strings - needs some FLASH. Must before #include <irmp*>
#define IRMP_USE_COMPLETE_CALLBACK  1 // Enable callback functionality

// Enables protocols manually
//#define IRMP_SUPPORT_SIRCS_PROTOCOL      1
#define IRMP_SUPPORT_NEC_PROTOCOL        1
//#define IRMP_SUPPORT_SAMSUNG_PROTOCOL    1
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL   1

//#define IRMP_SUPPORT_JVC_PROTOCOL        1
//#define IRMP_SUPPORT_NEC16_PROTOCOL      1
//#define IRMP_SUPPORT_NEC42_PROTOCOL      1
//#define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1
//#define IRMP_SUPPORT_DENON_PROTOCOL      1
//#define IRMP_SUPPORT_RC5_PROTOCOL        1
//#define IRMP_SUPPORT_RC6_PROTOCOL        1
//#define IRMP_SUPPORT_IR61_PROTOCOL       1
//#define IRMP_SUPPORT_GRUNDIG_PROTOCOL    1
//#define IRMP_SUPPORT_SIEMENS_PROTOCOL    1
//#define IRMP_SUPPORT_NOKIA_PROTOCOL      1

/*
 * After setting the modifiers we can include the code.
 */
#include <irmp.hpp>

IRMP_DATA irmp_data;

#define PROCESS_IR_RESULT_IN_MAIN_LOOP
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
volatile bool sIRDataJustReceived = false;
#endif

void handleReceivedIRData();
void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags);

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    Serial.begin(115200);

#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
    || defined(SERIALUSB_PID)  || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
    delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
    // Just to know which program is running on my Arduino
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP));

    //Enable auto resume and pass it the address of your extra buffer
    irmp_init();
    irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN
    irmp_register_complete_callback_function(&handleReceivedIRData);

    Serial.print(F("Ready to receive IR signals  of protocols: "));
    irmp_print_active_protocols(&Serial);
    Serial.println(F("at pin " STR(IRMP_INPUT_PIN)));
}

void loop()
{
#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
    if (sIRDataJustReceived)
    {
        sIRDataJustReceived = false;
        evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
        irmp_result_print(&irmp_data); // this is not allowed in ISR context for any kind of RTOS
    }
#endif
    /*
     * Put your code here
     */
}

/*
 * Callback function
 * Here we know, that data is available.
 * This function is executed in ISR (Interrupt Service Routine) context (interrupts are blocked here).
 * Make it short and fast and keep in mind, that you can not use delay(), prints longer than print buffer size etc.,
 * because they require interrupts enabled to return.
 * In order to enable other interrupts you can call sei() (enable interrupt again) after evaluating/copying data.
 * Good practice, but somewhat more complex, is to copy relevant data and signal receiving to main loop.
 */
#if defined(ESP8266) || defined(ESP32)
IRAM_ATTR
#endif
void handleReceivedIRData()
{
    irmp_get_data(&irmp_data);
#if !defined(ARDUINO_ARCH_MBED)
    interrupts(); // enable interrupts
#endif

#if defined(PROCESS_IR_RESULT_IN_MAIN_LOOP) || defined(ARDUINO_ARCH_MBED) || defined(ESP32)
    /*
     * Set flag to trigger printing of results in main loop,
     * since printing should not be done in a callback function
     * running in ISR (Interrupt Service Routine) context where interrupts are disabled.
     */
    sIRDataJustReceived = true;
#else
    interrupts(); // enable interrupts
    evaluateIRCommand(irmp_data.address, irmp_data.command, irmp_data.flags);
    irmp_result_print(&irmp_data); // This is not recommended, but simpler and works, except for any kind of RTOS like on ESP and MBED.
#endif
}

void evaluateIRCommand(uint16_t aAddress, uint16_t aCommand, uint8_t aFlags)
{
    /*
     * Filter for commands from the WM010 IR Remote
     */
    if (aAddress == 0xF708)
    {
        /*
         * Skip repetitions of command
         */
        if (!(aAddress & IRMP_FLAG_REPETITION))
        {
            /*
             * Evaluation of IR command
             */
            switch (aAddress)
            {
            case 0x48:
                digitalWrite(LED_BUILTIN, HIGH);
                break;
            case 0x0B:
                digitalWrite(LED_BUILTIN, LOW);
                break;
            default:
                break;
            }
        }
    }
}


================================================
FILE: examples/Callback/PinDefinitionsAndMore.h
================================================
/*
 *  PinDefinitionsAndMore.h
 *
 *  Contains pin definitions for IRMP examples for various platforms
 *  as well as definitions for feedback LED and tone() and includes
 *
 *  Copyright (C) 2020-2021  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

/*
 * Pin mapping table for different platforms
 *
 * Platform     IR input    IR output   Tone      Core/Pin schema
 * --------------------------------------------------------------
 * DEFAULT/AVR  2           3           4
 * ATtinyX5     0|PB0       4|PB4       3|PB3
 * ATtiny167    3|PA3       2|PA2       7|PA7     ATTinyCore
 * ATtiny167    9|PA3       8|PA2       5|PA7     Digispark pro
 * ATtiny3216  14|PA1      15|PA2      16|PA3     MegaTinyCore
 * SAMD21       3           4           5
 * ESP8266     14|D5       12|D6        %
 * ESP32       15           4           %
 * ESP32-C3     6           7          10
 * BluePill   PA6         PA7         PA3
 * APOLLO3     11          12           5
 * RP2040       3|GPIO15    4|GPIO16    5|GPIO17
 */
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN      14 // D5
#define IRSND_OUTPUT_PIN    12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN  13 // D7

#define tone(...) void()      // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN            42 // Dummy for examples using it

#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE   // The  WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN       6
#define IRSND_OUTPUT_PIN     7
#define TONE_PIN            10

#elif defined(ESP32)
#define IRMP_INPUT_PIN      15  // D15
#define IRSND_OUTPUT_PIN     4  // D4
#include <Arduino.h>
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
#  if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
#  endif
#  if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#  endif
#if ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
    delay(aDuration);
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN                27  // D27 25 & 26 are DAC0 and 1

#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN          PA6
#define IRSND_OUTPUT_PIN        PA7
#define TONE_PIN                PA3
#define IR_TIMING_TEST_PIN      PA5

#elif  defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN   0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN         3
//#define IR_TIMING_TEST_PIN 3

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
#  if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN   9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN  14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN         5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4

#  else
#define IRMP_INPUT_PIN   3
#define IRSND_OUTPUT_PIN 2
#define TONE_PIN         7
#  endif

#elif defined(__AVR_ATtiny88__) // MH-ET Tiny88 board
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// Pin 6 is TX pin 7 is RX
#define IRMP_INPUT_PIN   3 // INT1
#define IRSND_OUTPUT_PIN 4
#define TONE_PIN         9
#define IR_TIMING_TEST_PIN 8

#elif defined(__AVR_ATtiny1616__)  || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)
#define IRMP_INPUT_PIN   PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32
#define IRSND_OUTPUT_PIN PIN_PA2 // 15, 19 for TinyCore32
#define TONE_PIN         PIN_PA3 // 16, 20 for TinyCore32

#elif defined(ARDUINO_ARCH_APOLLO3)
#define IRMP_INPUT_PIN   11
#define IRSND_OUTPUT_PIN 12
#define TONE_PIN         5

#elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE, Arduino Nano RP2040 Connect
#define IRMP_INPUT_PIN      3   // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico
#define IRSND_OUTPUT_PIN    4   // GPIO16
#define TONE_PIN            5

#elif defined(ARDUINO_ARCH_RP2040) // Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico
#define IRMP_INPUT_PIN      15  // to be compatible with the Arduino Nano RP2040 Connect (pin3)
#define IRSND_OUTPUT_PIN    16
#define TONE_PIN            17

// If you program the Nano RP2040 Connect with this core, then you must redefine LED_BUILTIN
// and use the external reset with 1 kOhm to ground to enter UF2 mode
#undef LED_BUILTIN
#define LED_BUILTIN          6

#elif defined(TEENSYDUINO)
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7

#elif defined(__AVR__) // Standard AVR Boards like Uno, Nano
#define IRMP_INPUT_PIN      2 // To be compatible with interrupt example, pin 2 is chosen here.
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN 7
// You can alternatively specify the input pin with port and bit number if you do not have the Arduino pin number at hand
//#define IRMP_PORT_LETTER D
//#define IRMP_BIT_NUMBER 2

#elif defined(ARDUINO_ARCH_SAMD)
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7

// On the Zero and others we switch explicitly to SerialUSB
#define Serial SerialUSB

// Definitions for the Chinese SAMD21 M0-Mini clone, which has no led connected to D13/PA17.
// Attention!!! D2 and D4 are swapped on these boards!!!
// If you connect the LED, it is on pin 24/PB11. In this case activate the next two lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 24 // PB11
// As an alternative you can choose pin 25, it is the RX-LED pin (PB03), but active low.In this case activate the next 3 lines.
//#undef LED_BUILTIN
//#define LED_BUILTIN 25 // PB03
//#define FEEDBACK_LED_IS_ACTIVE_LOW // The RX LED on the M0-Mini is active LOW

#else
#warning Board / CPU is not detected using pre-processor symbols -> using default values for IRMP_INPUT_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h.
// Default valued for unidentified boards
#define IRMP_INPUT_PIN      2
#define IRSND_OUTPUT_PIN    3
#define TONE_PIN            4
#if !defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN)
#define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output.
#endif
#define IR_TIMING_TEST_PIN  7
#endif // defined(ESP8266)


#if defined(__AVR_ATmega4809__) // for standard AVR we manage hardware directly in void enablePCIInterrupt()
#define IRMP_USE_ARDUINO_ATTACH_INTERRUPT
#endif

/*
 * Helper macro for getting a macro definition as string
 */
#if !defined(STR_HELPER) && !defined(STR)
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#endif


================================================
FILE: examples/IRDispatcherDemo/DemoIRCommandMapping.h
================================================
/*
 * DemoIRCommandMapping.h
 *
 * Contains IR remote button codes, strings, and the mapping of codes to functions to call by the dispatcher
 *
 *  Copyright (C) 2019-2026  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#ifndef _IR_COMMAND_MAPPING_H
#define _IR_COMMAND_MAPPING_H

#include <Arduino.h>

#include "IRCommandDispatcher.h" // IRToCommandMappingStruct, IR_COMMAND_FLAG_BLOCKING etc. are defined here

/*
 * !!! Choose your remote !!!
 */
//#define USE_KEYES_REMOTE_CLONE With number pad and direction control swapped, will be taken as default
//#define USE_KEYES_REMOTE
#if !defined(USE_KEYES_REMOTE) && !defined(USE_KEYES_REMOTE_CLONE)
#define USE_KEYES_REMOTE_CLONE // the one you can buy at Aliexpress
#endif

#if (defined(USE_KEYES_REMOTE) && defined(USE_KEYES_REMOTE_CLONE))
#error "Please choose only one remote for compile"
#endif

#if defined(USE_KEYES_REMOTE_CLONE)
#define IR_REMOTE_NAME "KEYES_CLONE"
// Codes for the KEYES CLONE remote control with 17 keys with number pad above direction control
#define IR_ADDRESS 0x00

#define IR_UP    0x18
#define IR_DOWN  0x52
#define IR_RIGHT 0x5A
#define IR_LEFT  0x08
#define IR_OK    0x1C

#define IR_1    0x45
#define IR_2    0x46
#define IR_3    0x47
#define IR_4    0x44
#define IR_5    0x40
#define IR_6    0x43
#define IR_7    0x07
#define IR_8    0x15
#define IR_9    0x09
#define IR_0    0x19

#define IR_STAR 0x16
#define IR_HASH 0x0D
/*
 * SECOND:
 * IR button to command mapping for better reading. IR buttons should only referenced here.
 */
#define COMMAND_ON              IR_UP
#define COMMAND_OFF             IR_DOWN
#define COMMAND_INCREASE_BLINK  IR_RIGHT
#define COMMAND_DECREASE_BLINK  IR_LEFT

#define COMMAND_START           IR_OK
#define COMMAND_STOP            IR_HASH
#define COMMAND_RESET           IR_STAR
#define COMMAND_BLINK           IR_0
#define COMMAND_TONE1           IR_1

#define COMMAND_TONE2           IR_2
#define COMMAND_TONE3           IR_3
//#define            IR_4
//#define            IR_5
//#define            IR_6
//#define            IR_7
//#define            IR_8
//#define            IR_9

#endif

#if defined(USE_KEYES_REMOTE)
#define IR_REMOTE_NAME "KEYES"
/*
 * FIRST:
 * IR code to button mapping for better reading. IR codes should only referenced here.
 */
// Codes for the KEYES remote control with 17 keys and direction control above number pad
#define IR_ADDRESS 0x00

#define IR_UP    0x46
#define IR_DOWN  0x15
#define IR_RIGHT 0x43
#define IR_LEFT  0x44
#define IR_OK    0x40

#define IR_1    0x16
#define IR_2    0x19
#define IR_3    0x0D
#define IR_4    0x0C
#define IR_5    0x18
#define IR_6    0x5E
#define IR_7    0x08
#define IR_8    0x1C
#define IR_9    0x5A
#define IR_0    0x52

#define IR_STAR 0x42
#define IR_HASH 0x4A

/*
 * SECOND:
 * IR button to command mapping for better reading. IR buttons should only referenced here.
 */
#define COMMAND_ON              IR_UP
#define COMMAND_OFF             IR_DOWN
#define COMMAND_INCREASE_BLINK  IR_RIGHT
#define COMMAND_DECREASE_BLINK  IR_LEFT

#define COMMAND_RESET           IR_OK
#define COMMAND_STOP            IR_HASH
#define COMMAND_STOP            IR_STAR
#define COMMAND_BLINK           IR_0
#define COMMAND_TONE2           IR_1

#define COMMAND_TONE1           IR_2
#define COMMAND_TONE2           IR_3
#define COMMAND_TONE2           IR_4
#define COMMAND_TONE2           IR_5
#define COMMAND_TONE2           IR_6
#define COMMAND_TONE2           IR_7
#define COMMAND_TONE2           IR_8
#define COMMAND_TONE2           IR_9
#endif

/*
 * THIRD:
 * Main mapping of commands to C functions
 */

// Strings of commands for Serial output
static const char LEDon[] PROGMEM ="LED on";
static const char LEDoff[] PROGMEM ="LED off";

static const char blink20times[] PROGMEM ="blink 20 times";
static const char blinkStart[] PROGMEM ="blink start";

static const char increaseBlink[] PROGMEM ="increase blink frequency";
static const char decreaseBlink[] PROGMEM ="decrease blink frequency";

static const char tone2200[] PROGMEM ="tone 2200";
static const char tone1800[] PROGMEM ="tone 1800";
static const char printMenu[] PROGMEM ="printMenu";

static const char reset[] PROGMEM ="reset";
static const char stop[] PROGMEM ="stop";

/*
 * Main mapping array of commands to C functions and command strings
 * The macro COMMAND_STRING() removes the strings from memory, if USE_DISPATCHER_COMMAND_STRINGS is not enabled
 */
const struct IRToCommandMappingStruct IRMapping[] = { /**/
{ COMMAND_BLINK, IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP, &doLedBlink20times, COMMAND_STRING(blink20times) }, /**/
{ COMMAND_STOP, IR_COMMAND_FLAG_BLOCKING, &doStop, COMMAND_STRING(stop) }, /* */

/*
 * Short commands that can always be executed, but must be able to terminate other blocking commands (only doLedBlink20times() in this example)
 */
{ COMMAND_START, IR_COMMAND_FLAG_BLOCKING, &doLedBlinkStart, COMMAND_STRING(blinkStart) }, /**/
{ COMMAND_ON, IR_COMMAND_FLAG_BLOCKING, &doLedOn, COMMAND_STRING(LEDon) }, /**/
{ COMMAND_OFF, IR_COMMAND_FLAG_BLOCKING, &doLedOff, COMMAND_STRING(LEDoff) }, /**/

/*
 * Short commands that can always be executed
 */
{ COMMAND_TONE1, IR_COMMAND_FLAG_NON_BLOCKING, &doTone1800, COMMAND_STRING(tone1800) }, /* Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled */
{ COMMAND_TONE3, IR_COMMAND_FLAG_NON_BLOCKING, &doPrintMenu, COMMAND_STRING(printMenu) }, /**/
{ COMMAND_RESET, IR_COMMAND_FLAG_NON_BLOCKING, &doResetBlinkFrequency, COMMAND_STRING(reset) },

/*
 * Repeatable short commands
 */
{ COMMAND_TONE2, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doTone2200, COMMAND_STRING(tone2200) }, /* Lasts 50 ms and allows receiving of repeats */
{ COMMAND_INCREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doIncreaseBlinkFrequency, COMMAND_STRING(increaseBlink) }, /**/
{ COMMAND_DECREASE_BLINK, IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING, &doDecreaseBlinkFrequency, COMMAND_STRING(decreaseBlink) } };

#endif // _IR_COMMAND_MAPPING_H


================================================
FILE: examples/IRDispatcherDemo/IRDispatcherDemo.ino
================================================
/*
 *  IRDispatcherDemo.cpp
 *
 *  Example how to use IRCommandDispatcher to receive IR commands and map them to different actions / functions by means of a mapping array.
 *
 *  Copyright (C) 2020-2026  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

#include <Arduino.h>

/*
 * Choose the library to be used for IR receiving
 */
//#define USE_TINY_IR_RECEIVER // Recommended and default, but only for NEC protocol!!! If disabled and IRMP_INPUT_PIN is defined, the IRMP library is used for decoding
//#define USE_IRREMOTE_LIBRARY // The IRremote library is used for decoding
//#define USE_IRMP_LIBRARY     // The IRMP library is used for decoding
//#define DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT // Enables mapping and dispatching of IR commands consisting of more than 8 bits. Saves up to 160 bytes program memory and 5 bytes RAM + 1 byte RAM per mapping entry.
#define NO_LED_FEEDBACK_CODE   // We use LED_BUILTIN for command feedback and therefore cannot use is as IR receiving feedback
#define INFO // To see some informative output of the IRCommandDispatcher library
//#define DEBUG // To see some additional debug output of the IRCommandDispatcher library

#include "PinDefinitionsAndMore.h" // Define macros for input and output pin etc.

#if defined(INFO) || defined(DEBUG)
#define USE_DISPATCHER_COMMAND_STRINGS // Enables the printing of command strings. Requires additional 2 bytes RAM for each command mapping. Requires program memory for strings, but saves snprintf() code (1.5k) if INFO or DEBUG is activated, which has no effect if snprintf() is also used in other parts of your program / libraries.
#endif
#if defined(TONE_PIN)
#define DISPATCHER_BUZZER_FEEDBACK_PIN  TONE_PIN // The pin to be used for the optional 50 ms buzzer feedback before executing a command. Only available for TinyIR.
#endif

#if defined(USE_IRMP_LIBRARY)
//Enable protocols for IRMP
#define IRMP_SUPPORT_NEC_PROTOCOL         1 // this enables only one protocol
//#define IRMP_SUPPORT_KASEIKYO_PROTOCOL    1
//#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT  // Enable interrupt functionality (not for all protocols) - requires around 376 additional bytes of program memory
#endif // defined(USE_IRMP_LIBRARY)

bool doBlink = false;
uint16_t sBlinkDelay = 200;

/*
 * The functions which are called by the IR commands.
 * They must be declared before including DemoIRCommandMapping.h, where the mapping to IR keys is defined.
 */
void doPrintMenu();
void doLedOn();
void doLedOff();
void doIncreaseBlinkFrequency();
void doDecreaseBlinkFrequency();
void doStop();
void doResetBlinkFrequency();
void doLedBlinkStart();
void doLedBlink20times();
void doTone1800();
void doTone2200();

/*
 * Set definitions and include IRCommandDispatcher library after the declaration of all commands required for mapping
 */
#include "DemoIRCommandMapping.h" // must be included before IRCommandDispatcher.hpp to define IRMapping array, IR_ADDRESS etc.
#include "IRCommandDispatcher.hpp" // This can optionally set USE_TINY_IR_RECEIVER

void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration);

void setup()
{
    pinMode(LED_BUILTIN, OUTPUT);
    Serial.begin(115200);

#if defined(__AVR_ATmega32U4__) || defined(SERIAL_PORT_USBVIRTUAL) || defined(SERIAL_USB) /*stm32duino*/|| defined(USBCON) /*STM32_stm32*/ \
    || defined(SERIALUSB_PID)  || defined(ARDUINO_ARCH_RP2040) || defined(ARDUINO_attiny3217)
    delay(4000); // To be able to connect Serial monitor after reset or power up and before first print out. Do not wait for an attached Serial Monitor!
#endif
#if defined(ESP8266)
    Serial.println(); // to separate it from the internal boot output
#endif

    // Just to know which program is running on my Arduino
#if defined(USE_TINY_IR_RECEIVER)
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing TinyIRReceiver library version " VERSION_TINYIR));
#elif defined(USE_IRREMOTE_LIBRARY)
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRremote library version " VERSION_IRREMOTE));
#elif defined(USE_IRMP_LIBRARY)
    Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing IRMP library version " VERSION_IRMP));
#endif

#if !defined(ESP8266) && !defined(NRF5) && defined(TONE_PIN)
    // play feedback tone before IRDispatcher.init(), because it kills the IR timer settings, which are made by init()
    tone(TONE_PIN, 1000, 50);
    delay(50);
#endif

    IRDispatcher.init(); // This calls the init function of the chosen library
    IRDispatcher.printIRInfo(&Serial);

    doPrintMenu();
#if defined(DEBUG) && defined(SP)
    Serial.print(F("SP=0x"));
    Serial.println(SP, HEX);
#endif
}

void loop()
{

    IRDispatcher.checkAndRunSuspendedBlockingCommands();

    if (doBlink)
    {
        digitalWrite(LED_BUILTIN, HIGH);
        DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
        digitalWrite(LED_BUILTIN, LOW);
        DELAY_AND_RETURN_IF_STOP(sBlinkDelay);
    }

    if (millis() - IRDispatcher.IRReceivedData.MillisOfLastCode > 120000)
    {
        // Short beep as remainder, if we did not receive any command in the last 2 minutes
        IRDispatcher.IRReceivedData.MillisOfLastCode = millis();
        doTone1800();
#if defined(INFO)
        Serial.println(F("2 minutes timeout"));
#endif
    }

//    delay(10);
}

/*
 * Menu for simple China Keyes or Keyes clone IR controls with number pad and direction control pad
 */
void doPrintMenu()
{
    Serial.println();
    Serial.println(F("Press 1 for tone 1800 Hz"));
    Serial.println(F("Press 2 for tone 2200 Hz"));
    Serial.println(F("Press 3 for this Menu"));
    Serial.println(F("Press 0 for LED blink 20 times"));
    Serial.println(F("Press UP for LED on"));
    Serial.println(F("Press DOWN for LED off"));
    Serial.println(F("Press OK for LED blink start"));
    Serial.println(F("Press RIGHT for LED increase blink frequency"));
    Serial.println(F("Press LEFT for LED decrease blink frequency"));
    Serial.println(F("Press STAR for reset blink frequency"));
    Serial.println(F("Press HASH for stop"));
    Serial.println();
}
/*
 * Here the actions that are matched to IR keys
 */
void doLedOn()
{
    digitalWrite(LED_BUILTIN, HIGH);
    doBlink = false;
}
void doLedOff()
{
    digitalWrite(LED_BUILTIN, LOW);
    doBlink = false;
}
void doIncreaseBlinkFrequency()
{
    doBlink = true;
    if (sBlinkDelay > 5)
    {
        sBlinkDelay -= sBlinkDelay / 4;
    }
}
void doDecreaseBlinkFrequency()
{
    doBlink = true;
    sBlinkDelay += sBlinkDelay / 4;
}
void doStop()
{
    doBlink = false;
    digitalWrite(LED_BUILTIN, LOW);
}
void doResetBlinkFrequency()
{
    sBlinkDelay = 200;
    digitalWrite(LED_BUILTIN, LOW);
}
void doLedBlinkStart()
{
    doBlink = true;
}
/*
 * This is a blocking function which checks for stop
 */
void doLedBlink20times()
{
    for (int i = 0; i < 20; ++i)
    {
        digitalWrite(LED_BUILTIN, HIGH);
        DELAY_AND_RETURN_IF_STOP(200);
        digitalWrite(LED_BUILTIN, LOW);
        DELAY_AND_RETURN_IF_STOP(200);
    }
}

/*
 * Lasts 200 ms and blocks receiving of repeats. tone() requires interrupts enabled
 */
void doTone1800()
{
#if defined(TONE_PIN)
    IRremoteTone(TONE_PIN, 1800, 200);
#endif
}

/*
 * Lasts 50 ms and allows receiving of repeats
 */
void doTone2200()
{
#if defined(TONE_PIN)
    IRremoteTone(TONE_PIN, 2200, 50);
#endif
}

/*
 * Convenience IR library wrapper function for Arduino tone()
 * It currently disables the receiving of repeats
 * It is not part of the library because it statically allocates the tone interrupt vector 7.
 */
void IRremoteTone(uint8_t aTonePin, unsigned int aFrequency, unsigned long aDuration)
{
    // IRMP_ENABLE_PIN_CHANGE_INTERRUPT currently disables the receiving of repeats
#if defined(ESP8266) || defined(NRF5) || defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) // tone on esp8266 works only once, then it disables IrReceiver.restartTimer() / timerConfigForReceive().
    (void)  aTonePin;
    (void)  aFrequency;
    (void)  aDuration;
    return;
#else
    /*
     * Stop receiver, generate a single beep and start receiver again
     */
#  if defined(ESP32) || defined(USE_TINY_IR_RECEIVER )// ESP32 uses another timer for tone(), maybe other platforms (not tested yet) too.
    tone(aTonePin, aFrequency, aDuration);
#  else
#    if defined(USE_IRREMOTE_LIBRARY)
    IrReceiver.stopTimer(); // Stop timer consistently before calling tone() or other functions using the timer resource.
#    else
    storeIRTimer();
#    endif
    tone(aTonePin, aFrequency, 0);
    if (aDuration == 0)
    {
        aDuration = 100;
    }
    delay(aDuration);
    noTone(aTonePin);
#    if defined(USE_IRREMOTE_LIBRARY)
    IrReceiver.restartTimer(); // Restart IR timer after timer resource is no longer blocked.
#    else
    restoreIRTimer();
#    endif
#  endif
#endif
}


================================================
FILE: examples/IRDispatcherDemo/PinDefinitionsAndMore.h
================================================
/*
 *  PinDefinitionsAndMore.h
 *
 *  Contains pin definitions for IRMP examples for various platforms
 *  as well as definitions for feedback LED and tone() and includes
 *
 *  Copyright (C) 2020-2021  Armin Joachimsmeyer
 *  armin.joachimsmeyer@gmail.com
 *
 *  This file is part of IRMP https://github.com/IRMP-org/IRMP.
 *
 *  IRMP is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 *  See the GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
 *
 */

/*
 * Pin mapping table for different platforms
 *
 * Platform     IR input    IR output   Tone      Core/Pin schema
 * --------------------------------------------------------------
 * DEFAULT/AVR  2           3           4
 * ATtinyX5     0|PB0       4|PB4       3|PB3
 * ATtiny167    3|PA3       2|PA2       7|PA7     ATTinyCore
 * ATtiny167    9|PA3       8|PA2       5|PA7     Digispark pro
 * ATtiny3216  14|PA1      15|PA2      16|PA3     MegaTinyCore
 * SAMD21       3           4           5
 * ESP8266     14|D5       12|D6        %
 * ESP32       15           4           %
 * ESP32-C3     6           7          10
 * BluePill   PA6         PA7         PA3
 * APOLLO3     11          12           5
 * RP2040       3|GPIO15    4|GPIO16    5|GPIO17
 */
//#define IRMP_MEASURE_TIMING // For debugging purposes.
//
#if defined(ESP8266)
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board is active LOW
#define IRMP_INPUT_PIN      14 // D5
#define IRSND_OUTPUT_PIN    12 // D6 - D4/2 is internal LED
#define IR_TIMING_TEST_PIN  13 // D7

#define tone(...) void()      // tone() inhibits receive timer
#define noTone(a) void()
#define TONE_PIN            42 // Dummy for examples using it

#elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV)
#define NO_LED_FEEDBACK_CODE   // The  WS2812 on pin 8 of AI-C3 board crashes if used as receive feedback LED, other I/O pins are working...
#define IRMP_INPUT_PIN       6
#define IRSND_OUTPUT_PIN     7
#define TONE_PIN            10

#elif defined(ESP32)
#define IRMP_INPUT_PIN      15  // D15
#define IRSND_OUTPUT_PIN     4  // D4
#include <Arduino.h>
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
// tone() is included in ESP32 core since 2.0.2
#  if !defined(ESP_ARDUINO_VERSION)
#define ESP_ARDUINO_VERSION 0x010101 // Version 1.1.1
#  endif
#  if !defined(ESP_ARDUINO_VERSION_VAL)
#define ESP_ARDUINO_VERSION_VAL(major, minor, patch) ((major << 16) | (minor << 8) | (patch))
#  endif
#if ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_LEDC_CHANNEL        1  // Using channel 1 makes tone() independent of receiving timer -> No need to stop receiving timer.
void tone(uint8_t aPinNumber, unsigned int aFrequency){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
}
void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDuration){
    ledcAttachPin(aPinNumber, TONE_LEDC_CHANNEL);
    ledcWriteTone(TONE_LEDC_CHANNEL, aFrequency);
    delay(aDuration);
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
void noTone(uint8_t aPinNumber){
    ledcWriteTone(TONE_LEDC_CHANNEL, 0);
}
#endif // ESP_ARDUINO_VERSION  <= ESP_ARDUINO_VERSION_VAL(2, 0, 2)
#define TONE_PIN                27  // D27 25 & 26 are DAC0 and 1

#elif defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)
// BluePill in 2 flavors
// Timer 3 of IRMP blocks PA6, PA7, PB0, PB1 for use by Servo or tone()
#define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on the BluePill is active LOW
#define IRMP_INPUT_PIN          PA6
#define IRSND_OUTPUT_PIN        PA7
#define TONE_PIN                PA3
#define IR_TIMING_TEST_PIN      PA5

#elif  defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
#define IRMP_INPUT_PIN   0
#define IRSND_OUTPUT_PIN 4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board.
#define TONE_PIN         3
//#define IR_TIMING_TEST_PIN 3

#elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut"
// For ATtiny167 Pins PB6 and PA3 are usable as interrupt source.
#  if defined(ARDUINO_AVR_DIGISPARKPRO)
#define IRMP_INPUT_PIN   9 // PA3 - on Digispark board labeled as pin 9
//#define IRMP_INPUT_PIN  14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards
#define IRSND_OUTPUT_PIN 8 // PA2 - on Digispark board labeled as pin 8
#define TONE_PIN         5 // PA7
#define IR_TIMING_TEST_PIN 10 // PA4

#  else
#define IRMP_INPUT_
Download .txt
gitextract_kbf87dk0/

├── .github/
│   ├── issue_template.md
│   └── workflows/
│       ├── LibraryBuild.yml
│       └── PlatformIoPublish.yml
├── LICENSE.txt
├── README.md
├── examples/
│   ├── AllProtocols/
│   │   ├── ADCUtils.h
│   │   ├── ADCUtils.hpp
│   │   ├── AllProtocols.ino
│   │   ├── LiquidCrystal_I2C.h
│   │   ├── LiquidCrystal_I2C.hpp
│   │   └── PinDefinitionsAndMore.h
│   ├── Callback/
│   │   ├── Callback.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── IRDispatcherDemo/
│   │   ├── DemoIRCommandMapping.h
│   │   ├── IRDispatcherDemo.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── Interrupt/
│   │   ├── Interrupt.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── OneProtocol/
│   │   ├── OneProtocol.ino
│   │   └── PinDefinitionsAndMore.h
│   ├── RFProtocols/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── RFProtocols.ino
│   ├── ReceiveAndSend/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── ReceiveAndSend.ino
│   ├── ReceiveAndSendDynamicPins/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── ReceiveAndSendDynamicPins.ino
│   ├── ReceiverTimingAnalysis/
│   │   └── ReceiverTimingAnalysis.ino
│   ├── SendAllProtocols/
│   │   ├── PinDefinitionsAndMore.h
│   │   ├── SendAllProtocols.ino
│   │   └── SendAllProtocols.log
│   ├── SimpleReceiver/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── SimpleReceiver.ino
│   ├── SimpleSender/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── SimpleSender.ino
│   ├── TinyReceiver/
│   │   ├── PinDefinitionsAndMore.h
│   │   └── TinyReceiver.ino
│   └── TinySender/
│       ├── PinDefinitionsAndMore.h
│       └── TinySender.ino
├── extras/
│   ├── IRMP_UNO.fzz
│   └── IRMP_UNO_LCD.fzz
├── keywords.txt
├── library.json
├── library.properties
└── src/
    ├── IRCommandDispatcher.h
    ├── IRCommandDispatcher.hpp
    ├── IRFeedbackLED.h
    ├── IRFeedbackLED.hpp
    ├── IRTimer.h
    ├── IRTimer.hpp
    ├── LocalDebugLevelEnd.h
    ├── LocalDebugLevelStart.h
    ├── LongUnion.h
    ├── TinyIR.h
    ├── TinyIRReceiver.hpp
    ├── TinyIRSender.hpp
    ├── digitalWriteFast.h
    ├── irmp.h
    ├── irmp.hpp
    ├── irmpArduinoExt.h
    ├── irmpArduinoExt.hpp
    ├── irmpPinChangeInterrupt.hpp
    ├── irmpSelectAllProtocols.h
    ├── irmpSelectAllRFProtocols.h
    ├── irmpSelectMain15Protocols.h
    ├── irmpVersion.h
    ├── irmpconfig.h
    ├── irmpprotocols.h
    ├── irmpprotocols.hpp
    ├── irmpsystem.h
    ├── irsnd.h
    ├── irsnd.hpp
    ├── irsndArduinoExt.h
    ├── irsndArduinoExt.hpp
    ├── irsndSelectAllProtocols.h
    ├── irsndSelectMain15Protocols.h
    └── irsndconfig.h
Download .txt
SYMBOL INDEX (185 symbols across 30 files)

FILE: examples/AllProtocols/ADCUtils.hpp
  function readADCChannel (line 91) | uint16_t readADCChannel() {
  function readADCChannel (line 111) | uint16_t readADCChannel(uint8_t aADCChannelNumber) {
  function readADCChannelWithReference (line 131) | uint16_t readADCChannelWithReference(uint8_t aADCChannelNumber, uint8_t ...
  function readADCChannelWithReferenceUsingInternalReference (line 148) | uint16_t readADCChannelWithReferenceUsingInternalReference(uint8_t aADCC...
  function waitAndReadADCChannelWithReference (line 168) | uint16_t waitAndReadADCChannelWithReference(uint8_t aADCChannelNumber, u...
  function waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference (line 177) | uint16_t waitAndReadADCChannelWithReferenceAndRestoreADMUXAndReference(u...
  function setADCChannelAndReferenceForNextConversion (line 187) | void setADCChannelAndReferenceForNextConversion(uint8_t aADCChannelNumbe...
  function setADCChannelForNextConversionAndWaitUsingInternalReference (line 194) | void setADCChannelForNextConversionAndWaitUsingInternalReference(uint8_t...
  function setADCChannelForNextConversionAndWaitUsingDefaultReference (line 199) | void setADCChannelForNextConversionAndWaitUsingDefaultReference(uint8_t ...
  function readADCChannelWithOversample (line 251) | uint16_t readADCChannelWithOversample(uint8_t aADCChannelNumber, uint8_t...
  function readADCChannelWithReferenceOversample (line 258) | uint16_t readADCChannelWithReferenceOversample(uint8_t aADCChannelNumber...
  function readADCChannelWithReferenceOversampleFast (line 287) | uint16_t readADCChannelWithReferenceOversampleFast(uint8_t aADCChannelNu...
  function readADCChannelMultiSamplesWithReference (line 317) | uint16_t readADCChannelMultiSamplesWithReference(uint8_t aADCChannelNumb...
  function readADCChannelMultiSamplesWithReferenceAndPrescaler (line 348) | uint32_t readADCChannelMultiSamplesWithReferenceAndPrescaler(uint8_t aAD...
  function readADCChannelMultiSamples (line 378) | uint32_t readADCChannelMultiSamples(uint8_t aPrescale, uint16_t aNumberO...
  function readADCChannelWithReferenceMax (line 404) | uint16_t readADCChannelWithReferenceMax(uint8_t aADCChannelNumber, uint8...
  function readADCChannelWithReferenceMaxMicros (line 435) | uint16_t readADCChannelWithReferenceMaxMicros(uint8_t aADCChannelNumber,...
  function readUntil4ConsecutiveValuesAreEqual (line 444) | uint16_t readUntil4ConsecutiveValuesAreEqual(uint8_t aADCChannelNumber, ...
  function getVCCVoltageSimple (line 531) | float getVCCVoltageSimple(void) {
  function getVCCVoltageMillivoltSimple (line 542) | uint16_t getVCCVoltageMillivoltSimple(void) {
  function getVCCVoltageReadingFor1_1VoltReference (line 552) | uint16_t getVCCVoltageReadingFor1_1VoltReference(void) {
  function getVCCVoltage (line 563) | float getVCCVoltage(void) {
  function getVCCVoltageMillivolt (line 576) | uint16_t getVCCVoltageMillivolt(void) {
  function printVCCVoltageMillivolt (line 587) | uint16_t printVCCVoltageMillivolt(Print *aSerial) {
  function readAndPrintVCCVoltageMillivolt (line 595) | void readAndPrintVCCVoltageMillivolt(Print *aSerial) {
  function readVCCVoltageSimple (line 606) | void readVCCVoltageSimple(void) {
  function readVCCVoltageMillivoltSimple (line 617) | void readVCCVoltageMillivoltSimple(void) {
  function readVCCVoltage (line 626) | void readVCCVoltage(void) {
  function readVCCVoltageMillivolt (line 636) | void readVCCVoltageMillivolt(void) {
  function getVoltageMillivolt (line 648) | uint16_t getVoltageMillivolt(uint16_t aVCCVoltageMillivolt, uint8_t aADC...
  function getVoltageMillivolt (line 657) | uint16_t getVoltageMillivolt(uint8_t aADCChannelForVoltageMeasurement) {
  function getVoltageMillivoltWith_1_1VoltReference (line 662) | uint16_t getVoltageMillivoltWith_1_1VoltReference(uint8_t aADCChannelFor...
  function isVCCUSBPowered (line 672) | bool isVCCUSBPowered() {
  function isVCCUSBPowered (line 681) | bool isVCCUSBPowered(Print *aSerial) {
  function isVCCUndervoltageMultipleTimes (line 701) | bool isVCCUndervoltageMultipleTimes() {
  function isVCCUndervoltage (line 757) | bool isVCCUndervoltage() {
  function isVCCEmergencyUndervoltage (line 765) | bool isVCCEmergencyUndervoltage() {
  function resetCounterForVCCUndervoltageMultipleTimes (line 770) | void resetCounterForVCCUndervoltageMultipleTimes() {
  function isVCCOvervoltage (line 784) | bool isVCCOvervoltage() {
  function isVCCOvervoltageSimple (line 788) | bool isVCCOvervoltageSimple() {
  function isVCCTooHighSimple (line 794) | bool isVCCTooHighSimple() {
  function getCPUTemperatureSimple (line 814) | float getCPUTemperatureSimple(void) {
  function getTemperature (line 841) | float getTemperature(void) {
  function getCPUTemperature (line 844) | float getCPUTemperature(void) {
  function getVCCVoltageMillivoltSimple (line 862) | uint16_t getVCCVoltageMillivoltSimple(void){
  function readADCChannelWithReferenceOversample (line 866) | uint16_t readADCChannelWithReferenceOversample(uint8_t aChannelNumber __...
  function getCPUTemperature (line 870) | float getCPUTemperature() {
  function getVCCVoltage (line 873) | float getVCCVoltage() {

FILE: examples/AllProtocols/LiquidCrystal_I2C.h
  function class (line 57) | class LiquidCrystal_I2C : public Print {

FILE: examples/AllProtocols/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/Callback/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/IRDispatcherDemo/DemoIRCommandMapping.h
  type IRToCommandMappingStruct (line 177) | struct IRToCommandMappingStruct

FILE: examples/IRDispatcherDemo/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/Interrupt/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/OneProtocol/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/RFProtocols/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/ReceiveAndSend/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/ReceiveAndSendDynamicPins/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/SendAllProtocols/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/SimpleReceiver/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/SimpleSender/PinDefinitionsAndMore.h
  function tone (line 77) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 81) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 87) | void noTone(uint8_t aPinNumber){

FILE: examples/TinyReceiver/PinDefinitionsAndMore.h
  function tone (line 219) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 223) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 229) | void noTone(uint8_t aPinNumber){

FILE: examples/TinySender/PinDefinitionsAndMore.h
  function tone (line 219) | void tone(uint8_t aPinNumber, unsigned int aFrequency){
  function tone (line 223) | void tone(uint8_t aPinNumber, unsigned int aFrequency, unsigned long aDu...
  function noTone (line 229) | void noTone(uint8_t aPinNumber){

FILE: src/IRCommandDispatcher.h
  type uint_fast16_t (line 69) | typedef uint_fast16_t IRCommandType;
  type uint_fast8_t (line 71) | typedef uint_fast8_t IRCommandType;
  type IRToCommandMappingStruct (line 76) | struct IRToCommandMappingStruct {
  type IRDataForCommandDispatcherStruct (line 85) | struct IRDataForCommandDispatcherStruct {
  function class (line 93) | class IRCommandDispatcher {

FILE: src/IRCommandDispatcher.hpp
  function handleReceivedTinyIRData (line 89) | void handleReceivedTinyIRData() {
  function ReceiveCompleteCallbackHandler (line 155) | void ReceiveCompleteCallbackHandler() {
  function handleReceivedIRData (line 229) | void handleReceivedIRData()
  type IRToCommandMappingStruct (line 309) | struct IRToCommandMappingStruct
  type IRToCommandMappingStruct (line 498) | struct IRToCommandMappingStruct

FILE: src/IRFeedbackLED.hpp
  function irmp_irsnd_LEDFeedback (line 24) | void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed)
  function irmp_irsnd_LEDFeedback (line 45) | void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed)
  function irmp_irsnd_SetFeedbackLED (line 98) | void irmp_irsnd_SetFeedbackLED(bool aSwitchLedOn)

FILE: src/IRTimer.hpp
  function initIRTimerForSend (line 106) | void initIRTimerForSend(void)
  function storeIRTimer (line 387) | void storeIRTimer(void) {
  function restoreIRTimer (line 504) | void restoreIRTimer(void) {
  function disableIRTimerInterrupt (line 632) | void disableIRTimerInterrupt(void) {
  function enableIRTimerInterrupt (line 718) | void enableIRTimerInterrupt(void) {
  function IRTimerInterruptHandlerHelper (line 879) | bool IRTimerInterruptHandlerHelper(repeating_timer_t*) { // we are calle...

FILE: src/TinyIR.h
  type TinyIRReceiverStruct (line 203) | struct TinyIRReceiverStruct {
  type TinyIRReceiverCallbackDataStruct (line 235) | struct TinyIRReceiverCallbackDataStruct {

FILE: src/TinyIRReceiver.hpp
  function isTinyIRReceiverIdle (line 427) | bool isTinyIRReceiverIdle() {
  function isTinyReceiverIdle (line 430) | bool isTinyReceiverIdle() {
  function TinyIRReceiverDecode (line 437) | bool TinyIRReceiverDecode() {
  function TinyReceiverDecode (line 444) | bool TinyReceiverDecode() {
  function isIRReceiverAttachedForTinyIRReceiver (line 452) | bool isIRReceiverAttachedForTinyIRReceiver() {
  function isIRReceiverAttachedForTinyReceiver (line 458) | bool isIRReceiverAttachedForTinyReceiver() {
  function initPCIInterruptForTinyIRReceiver (line 466) | bool initPCIInterruptForTinyIRReceiver() {
  function initPCIInterruptForTinyReceiver (line 477) | bool initPCIInterruptForTinyReceiver() {
  function printTinyIRReceiverResultMinimal (line 481) | void printTinyIRReceiverResultMinimal(Print *aSerial) {
  function printTinyReceiverResultMinimal (line 501) | void printTinyReceiverResultMinimal(Print *aSerial) {
  function enablePCIInterruptForTinyIRReceiver (line 584) | bool enablePCIInterruptForTinyIRReceiver() {
  function enablePCIInterruptForTinyReceiver (line 654) | bool enablePCIInterruptForTinyReceiver() {
  function disablePCIInterruptForTinyIRReceiver (line 658) | void disablePCIInterruptForTinyIRReceiver() {
  function disablePCIInterruptForTinyReceiver (line 699) | void disablePCIInterruptForTinyReceiver() {
  function dummyFunctionToAvoidCompilerErrors (line 725) | void dummyFunctionToAvoidCompilerErrors()

FILE: src/TinyIRSender.hpp
  function sendMark (line 71) | void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) {
  function sendONKYO (line 113) | void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, u...
  function sendNECMinimal (line 181) | void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aComma...
  function sendNEC (line 184) | void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uin...
  function sendExtendedNEC (line 267) | void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aComm...
  function sendFast8BitAndParity (line 337) | void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast...
  function sendFAST (line 344) | void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberO...

FILE: src/irmp.hpp
  function irmp_register_complete_callback_function (line 710) | void irmp_register_complete_callback_function(void (*aCompleteCallbackFu...
  function irmp_uart_init (line 806) | void
  function irmp_uart_putc (line 963) | void
  function irmp_log (line 1031) | static void
  function irmp_init (line 2377) | void
  function uint_fast8_t (line 2492) | uint_fast8_t
  function irmp_set_callback_ptr (line 2819) | void
  function irmp_store_bit (line 2874) | static void
  function irmp_store_bit2 (line 3122) | static void
  function print_spectrum (line 5605) | void
  function uint_fast8_t (line 5720) | static uint_fast8_t
  function next_tick (line 5829) | static void
  function main (line 5938) | int

FILE: src/irmpArduinoExt.hpp
  function irmp_init (line 32) | void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin,...
  function irmp_init (line 63) | void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin)
  function irmp_init (line 75) | void irmp_init(uint_fast8_t aIrmpInputPin)
  function irmp_init (line 90) | void irmp_init(void)
  function irmp_DoLEDFeedback (line 115) | void irmp_DoLEDFeedback(bool aSwitchLedOff)
  function irmp_IsBusy (line 131) | bool irmp_IsBusy()
  function irmp_print_active_protocols (line 528) | void irmp_print_active_protocols(Print *aSerial)
  function irmp_print_protocol_name (line 558) | void irmp_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber)
  function irmp_result_print (line 585) | void irmp_result_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr)
  function irmp_result_print (line 610) | void irmp_result_print(IRMP_DATA *aIRMPDataPtr)

FILE: src/irmpPinChangeInterrupt.hpp
  function irmp_PCI_ISR (line 49) | void irmp_PCI_ISR(void)
  function enablePCIInterrupt (line 167) | void enablePCIInterrupt() {
  function disablePCIInterrupt (line 249) | void disablePCIInterrupt() {
  function irmp_debug_print (line 347) | void irmp_debug_print(const char *aMessage, bool aDoShortOutput)

FILE: src/irmpprotocols.h
  type PAUSE_LEN (line 171) | typedef uint16_t    PAUSE_LEN;
  type PAUSE_LEN (line 175) | typedef uint16_t    PAUSE_LEN;
  type PAUSE_LEN (line 177) | typedef uint8_t     PAUSE_LEN;

FILE: src/irmpsystem.h
  type uint_fast8_t (line 220) | typedef unsigned char                   uint_fast8_t;
  type uint_fast16_t (line 221) | typedef unsigned short                  uint_fast16_t;
  type IRMP_DATA (line 252) | typedef struct IRMP_PACKED_STRUCT IRMP_DATA

FILE: src/irsnd.hpp
  function irsnd_on (line 595) | static void
  function irsnd_off (line 683) | static void
  function irsnd_set_freq (line 774) | static void
  function irsnd_init (line 957) | void
  function irsnd_set_callback_ptr (line 1157) | void
  function irsnd_is_busy (line 1169) | uint8_t
  function bitsrevervse (line 1176) | static uint16_t bitsrevervse(uint16_t x, uint8_t len)
  function irsnd_send_data (line 1207) | uint8_t
  function irsnd_stop (line 1912) | void irsnd_stop(void)
  function irsnd_ISR (line 1926) | uint8_t
  function main (line 3429) | int

FILE: src/irsndArduinoExt.hpp
  function irsnd_init (line 38) | void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedP...
  function irsnd_init (line 65) | void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin)
  function irsnd_init (line 77) | void irsnd_init(uint_fast8_t aIrsndOutputPin)
  function irsnd_init (line 95) | void irsnd_init(void)
  function irsnd_set_freq (line 105) | static void irsnd_set_freq(IRSND_FREQ_TYPE freq __attribute__((unused)))
  function irsnd_on (line 116) | void irsnd_on(void)
  function irsnd_off (line 145) | void irsnd_off(void)
  function irsnd_print_protocol_name (line 537) | void irsnd_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber)
  function irsnd_data_print (line 555) | void irsnd_data_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr)
Condensed preview — 76 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,449K chars).
[
  {
    "path": ".github/issue_template.md",
    "chars": 2891,
    "preview": "---\nname: 🐛 Bug Report\nabout: Only if something isn't working as expected 🤔, otherwise please open a discussion.\nassigne"
  },
  {
    "path": ".github/workflows/LibraryBuild.yml",
    "chars": 10081,
    "preview": "# LibraryBuild.yml\n# Github workflow script to test compile all examples of an Arduino library repository.\n#\n# Copyright"
  },
  {
    "path": ".github/workflows/PlatformIoPublish.yml",
    "chars": 1187,
    "preview": "# PlatformIoPublish.yml\n# Github workflow script to publish a release to PlatformIo.\n#\n# Copyright (C) 2021-2023  Armin "
  },
  {
    "path": "LICENSE.txt",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 31310,
    "preview": "<div align = center>\n\n# [IRMP](https://github.com/IRMP-org/IRMP) - Infrared Multi Protocol Decoder + Encoder\nA library e"
  },
  {
    "path": "examples/AllProtocols/ADCUtils.h",
    "chars": 11277,
    "preview": "/*\n * ADCUtils.h\n *\n *  Copyright (C) 2016-2022  Armin Joachimsmeyer\n *  Email: armin.joachimsmeyer@gmail.com\n *\n *  Thi"
  },
  {
    "path": "examples/AllProtocols/ADCUtils.hpp",
    "chars": 34155,
    "preview": "/*\n * ADCUtils.hpp\n *\n * ADC utility functions. Conversion time is defined as 0.104 milliseconds for 16 MHz Arduinos in "
  },
  {
    "path": "examples/AllProtocols/AllProtocols.ino",
    "chars": 10820,
    "preview": "/*\n *  AllProtocols.cpp\n *\n *  Accepts 40 protocols concurrently\n *  If you specify F_INTERRUPTS to 20000 at line 86 (de"
  },
  {
    "path": "examples/AllProtocols/LiquidCrystal_I2C.h",
    "chars": 3474,
    "preview": "//YWROBOT\n#ifndef LiquidCrystal_I2C_h\n#define LiquidCrystal_I2C_h\n\n#include <inttypes.h>\n#include \"Print.h\"\n#if !defined"
  },
  {
    "path": "examples/AllProtocols/LiquidCrystal_I2C.hpp",
    "chars": 10727,
    "preview": "// LiquidCrystal_I2C.hpp\n// Based on the work by DFRobot\n/*\n * Extensions made by AJ 2023\n * Removed Arduino 0.x support"
  },
  {
    "path": "examples/AllProtocols/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/Callback/Callback.ino",
    "chars": 5978,
    "preview": "/*\n *  Callback.cpp\n *\n *  Uses a callback function which is called every time a complete IR command was received.\n *  T"
  },
  {
    "path": "examples/Callback/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/IRDispatcherDemo/DemoIRCommandMapping.h",
    "chars": 6817,
    "preview": "/*\n * DemoIRCommandMapping.h\n *\n * Contains IR remote button codes, strings, and the mapping of codes to functions to ca"
  },
  {
    "path": "examples/IRDispatcherDemo/IRDispatcherDemo.ino",
    "chars": 9639,
    "preview": "/*\n *  IRDispatcherDemo.cpp\n *\n *  Example how to use IRCommandDispatcher to receive IR commands and map them to differe"
  },
  {
    "path": "examples/IRDispatcherDemo/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/Interrupt/Interrupt.ino",
    "chars": 6130,
    "preview": "/*\n *  Interrupt.cpp\n *\n *  Receives IR protocol data by using pin change interrupts and no polling by timer.\n *  !!! Th"
  },
  {
    "path": "examples/Interrupt/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/OneProtocol/OneProtocol.ino",
    "chars": 5277,
    "preview": "/*\n *  OneProtocol.cpp\n *\n *  Receives IR protocol data. Only one protocol is activated.\n *\n *  Copyright (C) 2019-2020 "
  },
  {
    "path": "examples/OneProtocol/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/RFProtocols/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/RFProtocols/RFProtocols.ino",
    "chars": 2734,
    "preview": "/*\n *  RFProtocols.cpp\n *\n *  Receives 2 RF protocol (433 MHz) data.\n *\n *  Copyright (C) 2019-2020  Armin Joachimsmeyer"
  },
  {
    "path": "examples/ReceiveAndSend/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/ReceiveAndSend/ReceiveAndSend.ino",
    "chars": 8822,
    "preview": "/*\n *  ReceiveAndSend.cpp\n *\n *  Serves as a IR remote macro expander\n *  Receives Samsung32 protocol and on receiving a"
  },
  {
    "path": "examples/ReceiveAndSendDynamicPins/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/ReceiveAndSendDynamicPins/ReceiveAndSendDynamicPins.ino",
    "chars": 9558,
    "preview": "/*\n *  ReceiveAndSendDynamicPins.cpp\n *\n *  Example how to use pins specified at runtime.\n *\n *  Serves as a IR remote m"
  },
  {
    "path": "examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino",
    "chars": 8687,
    "preview": "/*\n *  ReceiverTimingAnalysis.cpp\n *\n *  This program enables the pin change interrupt at pin 3 and waits for NEC (or ot"
  },
  {
    "path": "examples/SendAllProtocols/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/SendAllProtocols/SendAllProtocols.ino",
    "chars": 3881,
    "preview": "/*\n *  SendAllProtocols.cpp\n *\n *  Sends 39 protocols for testing purposes\n *\n *  To disable one of them or to enable ot"
  },
  {
    "path": "examples/SendAllProtocols/SendAllProtocols.log",
    "chars": 2028,
    "preview": "START ../src/SendAllProtocols.cpp from Mar 17 2026\nUsing library version 3.7.0\nSend sample frequency=19000 Hz\nSend IR si"
  },
  {
    "path": "examples/SimpleReceiver/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/SimpleReceiver/SimpleReceiver.ino",
    "chars": 5126,
    "preview": "/*\n *  SimpleReceiver.cpp\n *\n *  Receives IR protocol data of 15 main protocols.\n *\n *  ********************************"
  },
  {
    "path": "examples/SimpleSender/PinDefinitionsAndMore.h",
    "chars": 9499,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRMP examples for various platforms\n *  as well as de"
  },
  {
    "path": "examples/SimpleSender/SimpleSender.ino",
    "chars": 4715,
    "preview": "/*\n *  SimpleSender.cpp\n *\n *  Sends NEC or Samsung protocol frames.\n *  Is able to send IR protocol data of 15 main pro"
  },
  {
    "path": "examples/TinyReceiver/PinDefinitionsAndMore.h",
    "chars": 16945,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRremote examples for various platforms\n *  as well a"
  },
  {
    "path": "examples/TinyReceiver/TinyReceiver.ino",
    "chars": 7313,
    "preview": "/*\n *  TinyReceiver.cpp\n *\n *  Small memory footprint and no timer usage!\n *\n *  Receives IR protocol data of NEC protoc"
  },
  {
    "path": "examples/TinySender/PinDefinitionsAndMore.h",
    "chars": 16945,
    "preview": "/*\n *  PinDefinitionsAndMore.h\n *\n *  Contains pin definitions for IRremote examples for various platforms\n *  as well a"
  },
  {
    "path": "examples/TinySender/TinySender.ino",
    "chars": 5814,
    "preview": "/*\n * TinySender.cpp\n *\n *  Example for sending using TinyIR. By default sends simultaneously using all supported protoc"
  },
  {
    "path": "keywords.txt",
    "chars": 1254,
    "preview": "#######################################\n# Syntax Coloring Map For IRMP\n#######################################\n\n########"
  },
  {
    "path": "library.json",
    "chars": 789,
    "preview": "{\n  \"name\": \"IRMP\",\n  \"version\": \"3.7.0\",\n  \"keywords\": \"infrared, ir, remote\",\n  \"description\": \"Receive and Send infra"
  },
  {
    "path": "library.properties",
    "chars": 559,
    "preview": "name=IRMP\nversion=3.7.0\nauthor=Frank Meyer, Armin Joachimsmeyer\nmaintainer=Armin Joachimsmeyer <armin.arduino@gmail.com>"
  },
  {
    "path": "src/IRCommandDispatcher.h",
    "chars": 6361,
    "preview": "/*\n * IRCommandDispatcher.h\n *\n * Library to process IR commands by calling functions specified in a mapping array.\n *\n "
  },
  {
    "path": "src/IRCommandDispatcher.hpp",
    "chars": 21006,
    "preview": "/*\n * IRCommandDispatcher.hpp\n *\n * Library to process IR commands by calling functions specified in a mapping array.\n *"
  },
  {
    "path": "src/IRFeedbackLED.h",
    "chars": 2172,
    "preview": "/*\n * IRFeedbackLED.h\n *\n *  Copyright (C) 2020-2021  Armin Joachimsmeyer\n *  armin.joachimsmeyer@gmail.com\n *\n *  This "
  },
  {
    "path": "src/IRFeedbackLED.hpp",
    "chars": 4109,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/IRTimer.h",
    "chars": 1604,
    "preview": "/*\n * IRTimer.h\n *\n *  Copyright (C) 2020  Armin Joachimsmeyer\n *  armin.joachimsmeyer@gmail.com\n *\n *  This file is par"
  },
  {
    "path": "src/IRTimer.hpp",
    "chars": 41789,
    "preview": "/*\n * IRTimer.hpp\n *\n *  Copyright (C) 2020  Armin Joachimsmeyer\n *  armin.joachimsmeyer@gmail.com\n *\n *  This file is p"
  },
  {
    "path": "src/LocalDebugLevelEnd.h",
    "chars": 1330,
    "preview": "/*\n * LocalDebugLevelEnd.h\n * Undefine local macros at the end of an included (.hpp) file\n *\n *  Copyright (C) 2024  Arm"
  },
  {
    "path": "src/LocalDebugLevelStart.h",
    "chars": 4112,
    "preview": "/*\n * LocalDebugLevelStart.h\n * Include to propagate global debug levels to file local ones and to define appropriate pr"
  },
  {
    "path": "src/LongUnion.h",
    "chars": 4031,
    "preview": "/*\n * LongUnion.h\n *\n *  Copyright (C) 2020-2022  Armin Joachimsmeyer\n *  Email: armin.joachimsmeyer@gmail.com\n *\n *  Th"
  },
  {
    "path": "src/TinyIR.h",
    "chars": 13028,
    "preview": "/*\n *  TinyIR.h\n *\n *\n *  Copyright (C) 2021-2025  Armin Joachimsmeyer\n *  armin.joachimsmeyer@gmail.com\n *\n *  This fil"
  },
  {
    "path": "src/TinyIRReceiver.hpp",
    "chars": 31534,
    "preview": "/*\n *  TinyIRReceiver.hpp\n *\n *  Receives IR data of NEC protocol using pin change interrupts.\n *  NEC is the protocol o"
  },
  {
    "path": "src/TinyIRSender.hpp",
    "chars": 16501,
    "preview": "/*\n *  TinyIRSender.hpp\n *\n *  Sends IR protocol data of NEC and FAST protocol using bit banging.\n *  NEC is the protoco"
  },
  {
    "path": "src/digitalWriteFast.h",
    "chars": 21110,
    "preview": "/*\n * digitalWriteFast.h\n *\n * Optimized digital functions for AVR microcontrollers\n * by Watterott electronic (www.watt"
  },
  {
    "path": "src/irmp.h",
    "chars": 15379,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmp.hpp",
    "chars": 398454,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpArduinoExt.h",
    "chars": 6650,
    "preview": "/*\n * irmpArduinoExt.h  Arduino extensions to the original irmp.h\n *\n *  Copyright (C) 2020  Armin Joachimsmeyer\n *  arm"
  },
  {
    "path": "src/irmpArduinoExt.hpp",
    "chars": 16947,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpPinChangeInterrupt.hpp",
    "chars": 14357,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpSelectAllProtocols.h",
    "chars": 9718,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpSelectAllRFProtocols.h",
    "chars": 2154,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpSelectMain15Protocols.h",
    "chars": 3593,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpVersion.h",
    "chars": 686,
    "preview": "/*\n * irmpVersion.h\n *\n * Is used for IRMP and IRSND, and therefore a separate file\n *\n *  Created on: 28.05.2020\n *    "
  },
  {
    "path": "src/irmpconfig.h",
    "chars": 25722,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpprotocols.h",
    "chars": 104193,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irmpprotocols.hpp",
    "chars": 5969,
    "preview": "/*\n * irmpprotocols.hpp - irmp protocols\n *\n *  Copyright (C) 2020-2021  Armin Joachimsmeyer\n *  armin.joachimsmeyer@gma"
  },
  {
    "path": "src/irmpsystem.h",
    "chars": 9589,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irsnd.h",
    "chars": 9049,
    "preview": " /*---------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irsnd.hpp",
    "chars": 192844,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irsndArduinoExt.h",
    "chars": 3265,
    "preview": "/*\n * irsndArduinoExt.h  Arduino extensions to the original irsnd.h\n *\n *  Copyright (C) 2020  Armin Joachimsmeyer\n *  a"
  },
  {
    "path": "src/irsndArduinoExt.hpp",
    "chars": 14994,
    "preview": "/*\n * irsndArduinoExt.hpp - Arduino extensions to the original irsnd.c\n *\n *  Copyright (C) 2020  Armin Joachimsmeyer\n *"
  },
  {
    "path": "src/irsndSelectAllProtocols.h",
    "chars": 7727,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irsndSelectMain15Protocols.h",
    "chars": 3195,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  },
  {
    "path": "src/irsndconfig.h",
    "chars": 15820,
    "preview": "/*----------------------------------------------------------------------------------------------------------------------"
  }
]

// ... and 2 more files (download for full content)

About this extraction

This page contains the full source code of the ukw100/IRMP GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 76 files (1.3 MB), approximately 347.8k tokens, and a symbol index with 185 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!