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 ### 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 ### Expected behavior ### Additional context **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. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . ================================================ FILE: README.md ================================================
# [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.
Supports 50 different protocols. [![Badge License: GPLv3](https://img.shields.io/badge/License-GPLv3-brightgreen.svg)](https://www.gnu.org/licenses/gpl-3.0)     [![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)     [![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)     [![Badge Build Status](https://github.com/IRMP-org/IRMP/workflows/LibraryBuild/badge.svg)](https://github.com/IRMP-org/IRMP/actions)     ![Badge Hit Counter](https://visitor-badge.laobi.icu/badge?page_id=IRMP-org_IRMP)

[![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)     [![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)
#### If you find this library useful, please give it a star. 🌎 [Google Translate](https://translate.google.com/translate?sl=en&u=https://github.com/IRMP-org/IRMP)
# 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.
| 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) |
# List of protocols ` Sony SIRCS `     ` NEC + APPLE + ONKYO `     ` Samsung + Samsg32 `     ` Kaseikyo ` ` JVC `     ` NEC16 + NEC42 `     ` Matsushita `     ` DENON `     ` Sharp `     ` RC5 `     ` RC6 & RC6A `     ` IR60 (SDA2008) Grundig `     ` Siemens Gigaset `     ` Nokia ` ` BOSE `     ` Kathrein `     ` NUBERT `     ` FAN (ventilator) `     ` SPEAKER (~NUBERT) `     ` Bang & Olufsen `     ` RECS80 (SAA3004) `
    ` RECS80EXT (SAA3008) `     ` Thomson `     ` NIKON camera `     ` Netbox keyboard `     ` ORTEK (Hama) `     ` Telefunken 1560 `
    ` FDC3402 keyboard `     ` RC Car `     ` iRobot Roomba `     ` RUWIDO `     ` T-Home `     ` A1 TV BOX `    ` LEGO Power RC `
    ` RCMM 12,24, or 32 `     ` LG Air Condition `     ` Samsung48 `     ` Merlin `     ` Pentax `     ` S100 `     ` ACP24 `     ` TECHNICS `
    ` PANASONIC Beamer `     ` Mitsubishi Aircond `     ` VINCENT `     ` SAMSUNG AH `     ` GREE CLIMATE `     ` RCII T+A `
    ` RADIO e.g. TEVION `     ` METZ ` ` NEC `     ` Kaseiko `     ` Denon `     ` RC6 `     ` Samsung + Samsg32 `   were successfully tested in **interrupt mode**, but there are many protocols which **in principle cannot be decoded** in this mode.
# 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.
# 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).
# Schematic for Arduino Uno The VS1838B is used as receiver for all examples and tests. This module has a 120 µs on/low and a 100 µs off/high delay between received signal and output. So it shortens the mark and extends the space by 20 µ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)
# 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)

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 |
# 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.
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)
**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
Microseconds() | blocking wait with delay
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
(4300 for 15 main / 8000 for all 40 protocols)
(+200 for callback)
(+80 for interrupt at pin 2+3)| 1270
(1400 for pin 2+3) | 4830 | 1770 | **900** | ?1100? | | RAM usage | 52
(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
(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
Interrupt()** | **All platforms with attach
Interrupt()** | | Last library update | 5/2023 | 4/2018 | 11/2022 | 9/2023 | 5/2023 | 2/2022 | | Remarks | Decodes 40 protocols concurrently.
39 Protocols to send.
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.
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
# 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).
The `irmp_init` and `irsnd_init` function then allows up to 3 parameters `uint_fast8_t aIrmpInputPin/aIrsndOutputPin, uint_fast8_t aIrmpFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow`.
Be aware, only one pin and enable flag for receive and send feedback LED is supported.
# 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.
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.
# 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); ```
# 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).
### SimpleReceiver + SimpleSender This examples are a good starting point.
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.
The **MinimalReceiver** example uses the **TinyReceiver** library which can **only receive NEC and FAST codes, but does not require any timer**.
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.
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.
It also computes the MARK_EXCESS_MICROS value, which is the extension of the mark (pulse) duration introduced by the IR receiver module.
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.
# 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 Ω to 100 Ω 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 Ω to 60 Ω. - 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);`
# 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 `.
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).
| 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 ` 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)*.
If you have not yet saved the example as your own sketch, then you are instantly in the right library folder.
Otherwise you have to navigate to the parallel `libraries` folder and select the library you want to access.
In both cases the library source and include files are located in the libraries `src` directory.
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*.
![Sloeber settings](https://github.com/ArminJo/ServoEasing/blob/master/pictures/SloeberDefineSymbols.png)
# [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.
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).
**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.
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.
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).
- 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.

# [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) |
# Documentation at mikrocontroller.net ### English http://www.mikrocontroller.net/articles/IRMP_-_english
http://www.mikrocontroller.net/articles/IRSND_-_english ### German http://www.mikrocontroller.net/articles/IRMP
http://www.mikrocontroller.net/articles/IRSND ### German Forum https://www.mikrocontroller.net/topic/irmp-infrared-multi-protocol-decoder?goto=6996113#6996137
# 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 to: #include !** - 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 . * */ #ifndef _ADC_UTILS_H #define _ADC_UTILS_H #include #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 . */ #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 . * */ #include #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 // 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_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 #include "Print.h" #if !defined(USE_SOFT_I2C_MASTER) && !defined(USE_SOFT_WIRE) #include #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 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 . * */ /* * 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 #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 . * */ #include /* * 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 #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_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 . * */ /* * 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 #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 . * */ #ifndef _IR_COMMAND_MAPPING_H #define _IR_COMMAND_MAPPING_H #include #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 . * */ #include /* * 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 . * */ /* * 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 #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/Interrupt/Interrupt.ino ================================================ /* * Interrupt.cpp * * Receives IR protocol data by using pin change interrupts and no polling by timer. * !!! This WILL NOT work for all protocols.!!! * Tested for NEC, Kaseiko, Denon, RC6, Samsung + Samsg32. * * To disable one of them or to enable other protocols, specify this before the "#include " line. * If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example). * The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example). * * 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 . * */ #include /* * 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 #define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality #define IRMP_ENABLE_PIN_CHANGE_INTERRUPT // Enable interrupt functionality #define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes #define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes #define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes #define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes /* * After setting the definitions we can include the code and compile it. */ #include 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() { 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)); 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) void IRAM_ATTR handleReceivedIRData() #else void handleReceivedIRData() #endif { irmp_get_data(&irmp_data); #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/Interrupt/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 . * */ /* * 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 #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/OneProtocol/OneProtocol.ino ================================================ /* * OneProtocol.cpp * * Receives IR protocol data. Only one protocol is activated. * * Copyright (C) 2019-2020 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 . * */ #include /* * Set input pin and output pin definitions etc. */ #include "PinDefinitionsAndMore.h" // Sets input pin to 3 //#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. #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. //#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 #define IRMP_SUPPORT_NEC_PROTOCOL 1 // includes APPLE and ONKYO protocols //#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 // use F_INTERRUPTS=20000 for Support of LEGO and RCMM //#define F_INTERRUPTS 20000 // interrupts per second, 50us, min: 10000, max: 20000, typ: 15000 //#define IRMP_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes //#define IRMP_SUPPORT_RCMM_PROTOCOL 1 // RCMM 12,24, or 32 >= 20000 ~150 bytes /* * Protocols which are not enabled in the irmpSelectAllProtocols.h for the AllProtocol example */ //#define IRMP_SUPPORT_FAN_PROTOCOL 1 // FAN (ventilator) >= 10000 ~50 bytes conflicts with NUBERT //#define IRMP_SUPPORT_ORTEK_PROTOCOL 1 // ORTEK (Hama) >= 10000 ~150 bytes conflicts with FDC and NETBOX //#define IRMP_SUPPORT_ROOMBA_PROTOCOL 1 // iRobot Roomba >= 10000 ~150 bytes conflicts with RC6 //#define IRMP_SUPPORT_RUWIDO_PROTOCOL 1 // RUWIDO, T-Home >= 15000 ~550 bytes conflicts with DENON //#define IRMP_SUPPORT_S100_PROTOCOL 1 // S100 >= 10000 ~250 bytes conflicts with RC5 //#define IRMP_SUPPORT_ACP24_PROTOCOL 1 // ACP24 >= 10000 ~250 bytes conflicts with DENON //#define IRMP_SUPPORT_PANASONIC_PROTOCOL 1 // PANASONIC Beamer >= 10000 ~250 bytes conflicts with KASEIKYO //#define IRMP_SUPPORT_RCII_PROTOCOL 1 // RCII T+A >= 15000 ~250 bytes conflicts with GRUNDIG and NOKIA /* * More protocol definitions can be found in irmpSelectAllProtocols.h */ /* * After setting the definitions we can include the code and compile it. */ #include IRMP_DATA irmp_data; 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) // Wait until Serial Monitor is attached. // Required for boards using USB code for Serial like Leonardo. // Is void for USB Serial implementations using external chips e.g. a CH340. while (!Serial) ; // !!! Program will not proceed if no Serial Monitor is attached !!! #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(); Serial.print(F("Ready to receive IR signals of protocols: ")); irmp_print_active_protocols(&Serial); Serial.println(F("at pin " STR(IRMP_INPUT_PIN))); irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN } void loop() { /* * Check if new data available and get them */ if (irmp_get_data(&irmp_data)) { /* * Here data is available -> evaluate IR command */ switch (irmp_data.command) { case 0x48: case 0x40: Serial.println(F("Received right code and do something")); digitalWrite(LED_BUILTIN, HIGH); break; default: break; } irmp_result_print(&irmp_data); } } ================================================ FILE: examples/OneProtocol/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 . * */ /* * 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 #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/RFProtocols/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 . * */ /* * 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 #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/RFProtocols/RFProtocols.ino ================================================ /* * RFProtocols.cpp * * Receives 2 RF protocol (433 MHz) data. * * Copyright (C) 2019-2020 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 . * */ #include /* * Set input pin and output pin definitions etc. */ #include "PinDefinitionsAndMore.h" // Sets input pin to 3 #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #include // This enables all possible RF protocols - currently 2 protocols /* * After setting the definitions we can include the code and compile it. */ #include IRMP_DATA irmp_data; void setup() { // initialize the digital pin as an output. 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) // Wait until Serial Monitor is attached. // Required for boards using USB code for Serial like Leonardo. // Is void for USB Serial implementations using external chips e.g. a CH340. while (!Serial) ; // !!! Program will not proceed if no Serial Monitor is attached !!! #endif // Just to know which program is running on my Arduino #if defined(ESP8266) Serial.println(); #endif 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 - commented out, since we use built in LED in loop below Serial.print(F("Ready to receive RF (433 MHz) signals of protocols: ")); irmp_print_active_protocols(&Serial); Serial.println(F("at pin " STR(IRMP_INPUT_PIN))); } void loop() { /* * Check if new data available and get them */ if (irmp_get_data(&irmp_data)) { irmp_result_print(&irmp_data); } } ================================================ FILE: examples/ReceiveAndSend/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 . * */ /* * 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 #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/ReceiveAndSend/ReceiveAndSend.ino ================================================ /* * ReceiveAndSend.cpp * * Serves as a IR remote macro expander * Receives Samsung32 protocol and on receiving a specified input frame, * it sends multiple Samsung32 frames with appropriate delays in between. * This serves as a Netflix-key emulation for my old Samsung H5273 TV. * * Copyright (C) 2019-2020 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 . * */ // ATMEL ATTINY85 // Piezo speaker must have a 270 ohm resistor in series for USB programming and running at the Samsung TV. // IR LED has a 270 ohm resistor in series. // +-\/-+ // !RESET (5) PB5 1| |8 Vcc // USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output // USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED // GND 4| |5 PB0 (0) IR Input // +----+ /* * Pin mapping table for different platforms * * Platform IR input IR output Tone * ----------------------------------------- * DEFAULT/AVR 2 3 4 * ATtinyX5 0 4 3 * ATtin167 9 8 5 // Digispark pro number schema * ATtin167 3 2 7 * SAMD21 3 4 5 * ESP8266 14 // D5 12 // D6 % * ESP32 15 4 % * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 */ #include /* * First define macros for input and output pin etc. */ #include "PinDefinitionsAndMore.h" //#define IR_OUTPUT_IS_ACTIVE_LOW #define IRSND_IR_FREQUENCY 38000 #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 /* * After setting the definitions we can include the code and compile it. */ #define USE_ONE_TIMER_FOR_IRMP_AND_IRSND // otherwise we get an error on AVR platform: redefinition of 'void __vector_8() #include #include IRMP_DATA irmp_data; IRMP_DATA irsnd_data; void sendSamsungSmartHubMacro(bool aDoSelect); void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis); 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 Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP)); // tone before IR setup, since it kills the IR timer settings tone(TONE_PIN, 2200); digitalWrite(LED_BUILTIN, HIGH); delay(400); digitalWrite(LED_BUILTIN, LOW); noTone(TONE_PIN); irmp_init(); irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at LED_BUILTIN for receive and send irsnd_init(); Serial.print(F("Ready to receive IR signals of protocols: ")); irmp_print_active_protocols(&Serial); Serial.println(F("at pin " STR(IRMP_INPUT_PIN))); Serial.println(F("Ready to send IR signals at pin " STR(IRSND_OUTPUT_PIN))); irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL; irsnd_data.address = 0x0707; irsnd_data.flags = 1; // repeat frame 1 time } void loop() { /* * Check if new data available and get them */ if (irmp_get_data(&irmp_data)) { irmp_result_print(&irmp_data); /* * Here data is available -> evaluate IR command */ switch (irmp_data.command) { case 0xB847: // The play key on the bottom of my Samsung remote Serial.println(F("Play key detected, open Netflix")); sendSamsungSmartHubMacro(true); break; case 0xB54A: // The pause key on the bottom of my Samsung remote Serial.println(F("Pause key detected, open SmartHub")); sendSamsungSmartHubMacro(false); break; default: break; } // Flush repeats received irmp_get_data(&irmp_data); } } void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis) { irsnd_data.command = aCommand; // For my Samsung, the high byte is the inverse of the low byte, this is not checked here. // true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending. if (!irsnd_send_data(&irsnd_data, true)) { Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print() } irsnd_data_print(&Serial,&irsnd_data); delay(aDelayMillis); } bool sMacroWasCalledBefore = false; #define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error #define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed /* * This macro calls the last SmartHub application you selected manually * * @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu * */ void sendSamsungSmartHubMacro(bool aDoSelect) { uint32_t tWaitTimeAfterBoot; if (aDoSelect) { tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS; } else { tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS; } if (millis() < tWaitTimeAfterBoot) { // division by 1000 and printing requires much (8%) program memory Serial.print(F("It is ")); Serial.print(millis() / 1000); Serial.print(F(" seconds after boot, Samsung H5273 TV requires ")); Serial.print(tWaitTimeAfterBoot / 1000); Serial.println(F(" seconds after boot to be ready for the command")); tone(TONE_PIN, 2200); delay(100); noTone(TONE_PIN); delay(100); tone(TONE_PIN, 2200); delay(100); noTone(TONE_PIN); while (millis() < tWaitTimeAfterBoot) { delay(10); // blocking wait } } // Do beep feedback for special key to be received tone(TONE_PIN, 2200); delay(200); noTone(TONE_PIN); irmp_init(); // restore timer for IR receive after using of tone Serial.println(F("Wait for \"not supported\" to disappear")); delay(2000); Serial.println(F("Start sending of Samsung IR macro")); IRSendWithDelay(0xE51A, 2000); // Menu and wait for the Menu to pop up Serial.println(F("Wait for the menu to pop up")); if (!sMacroWasCalledBefore) { delay(2000); // wait additional time for the Menu load } for (uint_fast8_t i = 0; i < 4; ++i) { IRSendWithDelay(0x9E61, 250); // Down arrow. For my Samsung, the high byte of the command is the inverse of the low byte } IRSendWithDelay(0x9D62, 400); // Right arrow for (uint_fast8_t i = 0; i < 2; ++i) { IRSendWithDelay(0x9E61, 250); // Down arrow } delay(250); IRSendWithDelay(0x9768, 1); // Enter for SmartHub if (aDoSelect) { Serial.println(F("Wait for SmartHub to show up, before entering current application")); delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears IRSendWithDelay(0x9768, 1); // Enter for last application (e.g. Netflix or Amazon) } sMacroWasCalledBefore = true; Serial.println(F("Done")); } ================================================ FILE: examples/ReceiveAndSendDynamicPins/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 . * */ /* * 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 #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/ReceiveAndSendDynamicPins/ReceiveAndSendDynamicPins.ino ================================================ /* * ReceiveAndSendDynamicPins.cpp * * Example how to use pins specified at runtime. * * Serves as a IR remote macro expander * Receives Samsung32 protocol and on receiving a specified input frame, it sends multiple Samsung32 frames. * This serves as a Netflix-key emulation for my old Samsung H5273 TV. * * Copyright (C) 2019-2020 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 . * */ // ATMEL ATTINY85 // Piezo speaker must have a 270 ohm resistor in series for USB programming and running at the Samsung TV. // IR LED has a 270 ohm resistor in series. // +-\/-+ // !RESET (5) PB5 1| |8 Vcc // USB+ 3.6V Z-Diode, 1.5kOhm to VCC Piezo (3) PB3 2| |7 PB2 (2) TX Debug output // USB- 3.6V Z-Diode IR Output (4) PB4 3| |6 PB1 (1) Feedback LED // GND 4| |5 PB0 (0) IR Input // +----+ /* * Pin mapping table for different platforms * * Platform IR input IR output Tone * ----------------------------------------- * DEFAULT/AVR 2 3 4 * ATtinyX5 0 4 3 * ATtin167 9 8 5 // Digispark pro number schema * ATtin167 3 2 7 * SAMD21 3 4 5 * ESP8266 14 // D5 12 // D6 % * ESP32 15 4 % * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 */ /* * Allow dynamic specification of input and output pins. * Requires additional 200 bytes program memory. * This must be first, it is used in PinDefinitionsAndMore.h */ #define IRMP_IRSND_ALLOW_DYNAMIC_PINS #include /* * Set library modifiers first to set input and output pin etc. */ #include "PinDefinitionsAndMore.h" //#define IR_OUTPUT_IS_ACTIVE_LOW #define IRSND_IR_FREQUENCY 38000 #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 /* * After setting the definitions we can include the code and compile it. */ #define USE_ONE_TIMER_FOR_IRMP_AND_IRSND // otherwise we get an error on AVR platform: redefinition of 'void __vector_8() #include #include IRMP_DATA irmp_data; uint8_t sIRMPInputPin; IRMP_DATA irsnd_data; void sendSamsungSmartHubMacro(bool aDoSelect); void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis); 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 Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP)); tone(TONE_PIN, 2200); digitalWrite(LED_BUILTIN, HIGH); delay(400); digitalWrite(LED_BUILTIN, LOW); noTone(TONE_PIN); /* * Request pin number from user by serial monitor */ Serial.println(F("Please enter pin number to use for receiving IR signals.")); while (Serial.available() == 0) { ; // Wait for user response } sIRMPInputPin = Serial.parseInt(); while (Serial.available()) { Serial.read(); // read rest of line and CR/LF from buffer to enable for next input } Serial.print(F("Ready to receive IR signals of protocols: ")); irmp_print_active_protocols(&Serial); Serial.println(F("at pin ")); Serial.println(sIRMPInputPin); irmp_init(sIRMPInputPin, LED_BUILTIN); // Enable receive signal feedback at LED_BUILTIN for receive (and send) Serial.println(F("Please enter pin number to use for sending IR signals.")); while (Serial.available() == 0) { ; // Wait for user response } uint8_t tIRSNDOutputPin = Serial.parseInt(); Serial.print(F("Ready to send IR signals at pin ")); Serial.println(tIRSNDOutputPin); irsnd_init(tIRSNDOutputPin); // feedback LED is specified at irmp_init() irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL; irsnd_data.address = 0x0707; irsnd_data.flags = 1; // repeat frame 1 time } void loop() { /* * Check if new data available and get them */ if (irmp_get_data(&irmp_data)) { irmp_result_print(&irmp_data); /* * Here data is available -> evaluate IR command */ switch (irmp_data.command) { case 0xB847: // The play key on the bottom of my Samsung remote Serial.println(F("Play key detected, open Netflix")); sendSamsungSmartHubMacro(true); break; case 0xB54A: // The pause key on the bottom of my Samsung remote Serial.println(F("Pause key detected, open SmartHub")); sendSamsungSmartHubMacro(false); break; default: break; } // Flush repeats received irmp_get_data(&irmp_data); } } void IRSendWithDelay(uint16_t aCommand, uint16_t aDelayMillis) { irsnd_data.command = aCommand; // true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending. if (!irsnd_send_data(&irsnd_data, true)) { Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print() } irsnd_data_print(&Serial,&irsnd_data); delay(aDelayMillis); } bool sMacroWasCalledBefore = false; #define INITIAL_WAIT_TIME_APPS_READY_MILLIS 70000 // Time to let the TV load all software before Netflix can be started without an error #define INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS 20000 // Time to let the TV load all software before SmartHub manu can be displayed /* * This macro calls the last SmartHub application you selected manually * * @param aDoSelect - if true select the current app (needs longer initial wait time) else show smarthub menu * */ void sendSamsungSmartHubMacro(bool aDoSelect) { uint32_t tWaitTimeAfterBoot; if (aDoSelect) { tWaitTimeAfterBoot = INITIAL_WAIT_TIME_APPS_READY_MILLIS; } else { tWaitTimeAfterBoot = INITIAL_WAIT_TIME_SMARTHUB_READY_MILLIS; } if (millis() < tWaitTimeAfterBoot) { // division by 1000 and printing requires much (8%) program memory Serial.print(F("It is ")); Serial.print(millis() / 1000); Serial.print(F(" seconds after boot, Samsung H5273 TV requires ")); Serial.print(tWaitTimeAfterBoot / 1000); Serial.println(F(" seconds after boot to be ready for the command")); tone(TONE_PIN, 2200); delay(100); noTone(TONE_PIN); delay(100); tone(TONE_PIN, 2200); delay(100); noTone(TONE_PIN); while (millis() < tWaitTimeAfterBoot) { delay(10); // blocking wait } } // Do beep feedback for special key to be received tone(TONE_PIN, 2200); delay(200); noTone(TONE_PIN); irmp_init(sIRMPInputPin); // restore timer for IR receive after using of tone Serial.println(F("Wait for \"not supported\" to disappear")); delay(2000); Serial.println(F("Start sending of Samsung IR macro")); IRSendWithDelay(0xE51A, 2000); // Menu and wait for the Menu to pop up Serial.println(F("Wait for the menu to pop up")); if (!sMacroWasCalledBefore) { delay(2000); // wait additional time for the Menu load } for (uint_fast8_t i = 0; i < 4; ++i) { IRSendWithDelay(0x9E61, 250); // Down arrow } IRSendWithDelay(0x9D62, 400); // Right arrow for (uint_fast8_t i = 0; i < 2; ++i) { IRSendWithDelay(0x9E61, 250); // Down arrow } delay(250); IRSendWithDelay(0x9768, 1); // Enter for SmartHub if (aDoSelect) { Serial.println(F("Wait for SmartHub to show up, before entering current application")); delay(10000); // Wait not longer than 12 seconds, because smarthub menu then disappears IRSendWithDelay(0x9768, 1); // Enter for last application (e.g. Netflix or Amazon) } sMacroWasCalledBefore = true; Serial.println(F("Done")); } ================================================ FILE: examples/ReceiverTimingAnalysis/ReceiverTimingAnalysis.ino ================================================ /* * ReceiverTimingAnalysis.cpp * * This program enables the pin change interrupt at pin 3 and waits for NEC (or other Pulse-Distance-Coding) IR Signal. * It measures the pulse and pause times of the incoming signal and computes some statistics for it. * * Observed values: * Delta of each signal type is around 50 up to 100 and at low signals up to 200. TSOP is better, especially at low IR signal level. * VS1838 Mark Excess -50 to +50 us * TSOP31238 Mark Excess 0 to +50 * * * Copyright (C) 2019-2020 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 . * */ #include #define IR_RECEIVE_PIN 2 //#define IR_RECEIVE_PIN 3 // 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(EICRA) && defined(EIFR) && defined(EIMSK)) void measureTimingISR(void); #endif 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) // Wait until Serial Monitor is attached. // Required for boards using USB code for Serial like Leonardo. // Is void for USB Serial implementations using external chips e.g. a CH340. while (!Serial) ; // !!! Program will not proceed if no Serial Monitor is attached !!! #endif // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ " from " __DATE__)); #if defined(EICRA) && defined(EIFR) && defined(EIMSK) # if (IR_RECEIVE_PIN == 2) EICRA |= _BV(ISC00); // interrupt on any logical change EIFR |= _BV(INTF0); // clear interrupt bit EIMSK |= _BV(INT0); // enable interrupt on next change # elif (IR_RECEIVE_PIN == 3) EICRA |= _BV(ISC10); // enable interrupt on pin3 on both edges for ATmega328 EIFR |= _BV(INTF1); // clear interrupt bit EIMSK |= _BV(INT1); // enable interrupt on next change # endif #else # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax attachInterrupt(IR_RECEIVE_PIN, measureTimingISR, CHANGE); # else attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), measureTimingISR, CHANGE); // CHANGE can also be an enum :-( # endif #endif Serial.println(F("Ready to analyze NEC IR signal at pin " STR(IR_RECEIVE_PIN))); Serial.println(); } uint8_t ISREdgeCounter = 0; volatile uint32_t LastMicros; struct timingStruct { uint16_t minimum; uint8_t indexOfMinimum; uint16_t maximum; uint8_t indexOfMaximum; uint16_t average; uint16_t SumForAverage; uint8_t SampleCount; // uint8_t LastPrintedCount; }; struct timingStruct Mark; struct timingStruct ShortSpace; struct timingStruct LongSpace; /* * Compute minimum, maximum and average */ void processTmingValue(struct timingStruct *aTimingStruct, uint16_t aValue) { if (aTimingStruct->SampleCount == 0) { // initialize values aTimingStruct->minimum = UINT16_MAX; aTimingStruct->maximum = 0; aTimingStruct->SumForAverage = 0; } if (aTimingStruct->minimum > aValue) { aTimingStruct->minimum = aValue; aTimingStruct->indexOfMinimum = aTimingStruct->SampleCount; } if (aTimingStruct->maximum < aValue) { aTimingStruct->maximum = aValue; aTimingStruct->indexOfMaximum = aTimingStruct->SampleCount; } aTimingStruct->SampleCount++; aTimingStruct->SumForAverage += aValue; aTimingStruct->average = (aTimingStruct->SumForAverage + (aTimingStruct->SampleCount / 2)) / aTimingStruct->SampleCount; } void printTimingValues(struct timingStruct *aTimingStruct, const char *aCaption) { // if (aTimingStruct->LastPrintedCount != aTimingStruct->SampleCount) // { // aTimingStruct->LastPrintedCount = aTimingStruct->SampleCount; Serial.print(aCaption); Serial.print(F(": SampleCount=")); Serial.print(aTimingStruct->SampleCount); Serial.print(F(" Minimum=")); Serial.print(aTimingStruct->minimum); Serial.print(F(" @")); Serial.print(aTimingStruct->indexOfMinimum); Serial.print(F(" Maximum=")); Serial.print(aTimingStruct->maximum); Serial.print(F(" @")); Serial.print(aTimingStruct->indexOfMaximum); Serial.print(F(" Delta=")); Serial.print(aTimingStruct->maximum - aTimingStruct->minimum); Serial.print(F(" Average=")); Serial.print(aTimingStruct->average); Serial.println(); // } } void loop() { if (Mark.SampleCount >= 32) { /* * This check enables statistics for longer protocols like Kaseikyo/Panasonics */ #if !defined(ARDUINO_ARCH_MBED) noInterrupts(); #endif uint32_t tLastMicros = LastMicros; #if !defined(ARDUINO_ARCH_MBED) interrupts(); #endif uint32_t tMicrosDelta = micros() - tLastMicros; if (tMicrosDelta > 10000) { // NEC signal ended just now Serial.println(); printTimingValues(&Mark, "Mark "); printTimingValues(&ShortSpace, "ShortSpace"); printTimingValues(&LongSpace, "LongSpace "); /* * Print analysis of mark and short spaces */ Serial.println(F("Analysis :")); Serial.print(F(" (Average of mark + short space)/2 = ")); int16_t MarkAndShortSpaceAverage = (Mark.average + ShortSpace.average) / 2; Serial.print(MarkAndShortSpaceAverage); Serial.print(F(" us\r\n Delta (to NEC standard 560) = ")); Serial.print(MarkAndShortSpaceAverage - 560); Serial.print(F("us\r\n MARK_EXCESS_MICROS = (Average of mark - Average of mark and short space) = ")); Serial.print((int16_t) Mark.average - MarkAndShortSpaceAverage); Serial.print(F("us")); Serial.println(); Serial.println(); Mark.SampleCount = 0; // used as flag for not printing the results more than once } } } /* * The interrupt handler. * Just add to the appropriate timing structure. */ #if defined(ESP8266) || defined(ESP32) void IRAM_ATTR measureTimingISR() #else # if defined(EICRA) && defined(EIFR) && defined(EIMSK) # if (IR_RECEIVE_PIN == 2) ISR(INT0_vect) # elif (IR_RECEIVE_PIN == 3) ISR(INT1_vect) # endif # else void measureTimingISR() # endif #endif { uint32_t tMicros = micros(); uint32_t tMicrosDelta = tMicros - LastMicros; LastMicros = tMicros; /* * read level and give feedback */ uint8_t tInputLevel = digitalRead(IR_RECEIVE_PIN); digitalWrite(LED_BUILTIN, !tInputLevel); if (tMicrosDelta > 10000) { // gap > 10 ms detected, reset counter to first detected edge and initialize timing structures ISREdgeCounter = 1; LongSpace.SampleCount = 0; ShortSpace.SampleCount = 0; Mark.SampleCount = 0; } else { ISREdgeCounter++; } /* * Skip header mark and space and first bit mark and space */ if (ISREdgeCounter > 4) { if (tInputLevel != LOW) { // Mark ended processTmingValue(&Mark, tMicrosDelta); // Serial.print('M'); } else { // Space ended if (tMicrosDelta > 1000) { // long space - logical 1 processTmingValue(&LongSpace, tMicrosDelta); Serial.print('1'); } else { // short space - logical 0 processTmingValue(&ShortSpace, tMicrosDelta); Serial.print('0'); } } } } ================================================ FILE: examples/SendAllProtocols/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 . * */ /* * 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 #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/SendAllProtocols/SendAllProtocols.ino ================================================ /* * SendAllProtocols.cpp * * Sends 39 protocols for testing purposes * * To disable one of them or to enable other protocols, specify this before the "#include " line. * If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example). * The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example). * * Copyright (C) 2019-2020 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 . * */ #include /* * Set library modifiers first to set output pin etc. */ #include "PinDefinitionsAndMore.h" #define IRSND_IR_FREQUENCY 38000 #if ! (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) #define IRSND_PROTOCOL_NAMES 1 #endif //#define IRSND_GENERATE_NO_SEND_RF // for back to back tests #include /* * After setting the definitions we can include the code and compile it. */ #include IRMP_DATA irsnd_data; 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) 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 Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_IRMP)); Serial.print(F("Send sample frequency=")); Serial.print(F_INTERRUPTS); Serial.println(F(" Hz")); irsnd_init(); irmp_irsnd_LEDFeedback(true); // Enable send signal feedback at LED_BUILTIN Serial.println(F("Send IR signals at pin " STR(IRSND_OUTPUT_PIN))); delay(1000); } void loop() { static uint16_t sAddress = 0x201; static uint16_t sCommand = 0x201; static uint8_t sRepeats = 0; Serial.print(F("Now sending all with ")); Serial.print(sRepeats); Serial.println(F(" repeats")); for (uint_fast8_t i = 0; i < sizeof(irsnd_used_protocol_index); ++i) { irsnd_data.protocol = pgm_read_byte(&irsnd_used_protocol_index[i]); irsnd_data.address = sAddress; irsnd_data.command = sCommand; irsnd_data.flags = sRepeats; // true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending. if (!irsnd_send_data(&irsnd_data, true)) { Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print() } irsnd_data_print(&Serial, &irsnd_data); sAddress += 0x101; sCommand += 0x101; delay(1000); } Serial.println(); Serial.println(); sRepeats++; // we have 0x27 protocols now start with next number range sAddress = (sAddress & 0xC0) + 0x40; sCommand = sAddress; delay(2000); } ================================================ FILE: examples/SendAllProtocols/SendAllProtocols.log ================================================ START ../src/SendAllProtocols.cpp from Mar 17 2026 Using library version 3.7.0 Send sample frequency=19000 Hz Send IR signals at pin 3 Protocol=SIRCS Address=0x1 Command=0x1 Protocol=NEC Address=0x2 Command=0x2 Protocol=SAMSUNG Address=0x3 Command=0x3 Protocol=MATSUSH Address=0x4 Command=0x4 Protocol=KASEIKYO Address=0x5 Command=0x5 Protocol=RECS80 Address=0x6 Command=0x6 Protocol=RC5 Address=0x7 Command=0x7 Protocol=DENON Address=0x8 Command=0x8 Protocol=RC6 Address=0x9 Command=0x9 Protocol=SAMSG32 Address=0xA Command=0xA Protocol=APPLE Address=0xB Command=0xB Protocol=RECS80EX Address=0xC Command=0xC Protocol=NUBERT Address=0xD Command=0xD Protocol=GRUNDIG Address=0xE Command=0xE Protocol=NOKIA Address=0xF Command=0xF Protocol=SIEMENS Address=0x10 Command=0x10 Protocol=FDC Address=0x11 Command=0x11 Protocol=RCCAR Address=0x12 Command=0x12 Protocol=JVC Address=0x13 Command=0x13 Protocol=RC6A Address=0x14 Command=0x14 Protocol=NIKON Address=0x15 Command=0x15 Protocol=RUWIDO Address=0x16 Command=0x16 Protocol=NEC16 Address=0x17 Command=0x17 Protocol=NEC42 Address=0x18 Command=0x18 Protocol=LEGO Address=0x19 Command=0x19 Protocol=THOMSON Address=0x1A Command=0x1A Protocol=BOSE Address=0x1B Command=0x1B Protocol=A1TVBOX Address=0x1C Command=0x1C Protocol=TELEFUNKEN Address=0x1D Command=0x1D Protocol=ROOMBA Address=0x1E Command=0x1E Protocol=SPEAKER Address=0x1F Command=0x1F Protocol=LGAIR Address=0x20 Command=0x20 Protocol=SAMSG48 Address=0x21 Command=0x21 Protocol=PENTAX Address=0x22 Command=0x22 Protocol=FAN Address=0x23 Command=0x23 Protocol=ACP24 Address=0x24 Command=0x24 Protocol=TECHNICS Address=0x25 Command=0x25 Protocol=PANASONIC Address=0x26 Command=0x26 Protocol=MITSU_HEAVY Address=0x27 Command=0x27 Now sending all with number of repeats=1 Protocol=SIRCS Address=0x40 Command=0x40 Repeats=1 Protocol=NEC Address=0x41 Command=0x41 Repeats=1 Protocol=SAMSUNG Address=0x42 Command=0x42 Repeats=1 Protocol=MATSUSH Address=0x43 Command=0x43 Repeats=1 ================================================ FILE: examples/SimpleReceiver/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 . * */ /* * 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 #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/SimpleReceiver/SimpleReceiver.ino ================================================ /* * SimpleReceiver.cpp * * Receives IR protocol data of 15 main protocols. * * ***************************************************************************************************************************** * To access the library files from your sketch, you have to first use `Sketch > Show Sketch Folder (Ctrl+K)` in the Arduino IDE. * Then navigate to the parallel `libraries` folder and select the library you want to access. * The library files itself are located in the `src` sub-directory. * If you did not yet store the example as your own sketch, then with Ctrl+K you are instantly in the right library folder. * ***************************************************************************************************************************** * * * The following IR protocols are enabled by default: * Sony SIRCS * NEC + APPLE * Samsung + Samsg32 * Kaseikyo * * Plus 11 other main protocols by including irmpMain15.h instead of irmp.h * JVC, NEC16, NEC42, Matsushita, DENON, Sharp, RC5, RC6 & RC6A, IR60 (SDA2008) Grundig, Siemens Gigaset, Nokia * * To disable one of them or to enable other protocols, specify this before the "#include " line. * If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example). * The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example). * * Copyright (C) 2019 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 . * */ #include /* * Set input pin and output pin definitions etc. */ #include "PinDefinitionsAndMore.h" #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. Must before #include //#include // This enables 15 main protocols #define IRMP_SUPPORT_NEC_PROTOCOL 1 // this enables only one protocol //#define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // this enables only one protocol /* * We use LED_BUILTIN as feedback for commands 0x40 and 0x48 and cannot use it as feedback LED for receiving */ #if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) #define IRMP_FEEDBACK_LED_PIN ALTERNATIVE_IR_FEEDBACK_LED_PIN #endif /* * After setting the definitions we can include the code and compile it. */ #include IRMP_DATA irmp_data; 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) // Wait until Serial Monitor is attached. // Required for boards using USB code for Serial like Leonardo. // Is void for USB Serial implementations using external chips e.g. a CH340. while (!Serial) ; // !!! Program will not proceed if no Serial Monitor is attached !!! #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(); Serial.print(F("Ready to receive IR signals of protocols: ")); irmp_print_active_protocols(&Serial); Serial.println(F("at pin " STR(IRMP_INPUT_PIN))); /* * We use LED_BUILTIN as feedback for commands 0x40 and 0x48 and cannot use it as feedback LED for receiving */ #if defined(ALTERNATIVE_IR_FEEDBACK_LED_PIN) irmp_irsnd_LEDFeedback(true); // Enable receive signal feedback at ALTERNATIVE_IR_FEEDBACK_LED_PIN Serial.println(F("IR feedback pin is " STR(ALTERNATIVE_IR_FEEDBACK_LED_PIN))); #endif } void loop() { /* * Check if new data available and get them */ if (irmp_get_data(&irmp_data)) { /* * Skip repetitions of command */ if (!(irmp_data.flags & IRMP_FLAG_REPETITION)) { /* * Here data is available and is no repetition -> evaluate IR command */ switch (irmp_data.command) { case 0x48: // 72 case 0x40: // 64 digitalWrite(LED_BUILTIN, LOW); delay(4000); break; default: digitalWrite(LED_BUILTIN, HIGH); break; } } irmp_result_print(&irmp_data); } } ================================================ FILE: examples/SimpleSender/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 . * */ /* * 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 #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/SimpleSender/SimpleSender.ino ================================================ /* * SimpleSender.cpp * * Sends NEC or Samsung protocol frames. * Is able to send IR protocol data of 15 main protocols. * * Sony SIRCS * NEC + APPLE * Samsung + Samsg32 * Kaseikyo * * Plus 11 other main protocols * JVC, NEC16, NEC42, Matsushita, DENON, Sharp, RC5, RC6 & RC6A, IR60 (SDA2008) Grundig, Siemens Gigaset, Nokia * * To disable one of them or to enable other protocols, specify this before the "#include " line. * If you get warnings of redefining symbols, just ignore them or undefine them first (see Interrupt example). * The exact names can be found in the library file irmpSelectAllProtocols.h (see Callback example). * * Copyright (C) 2019-2020 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 . * */ #include //#define SEND_SAMSUNG // else send NEC /* * Set library modifiers first to set output pin etc. */ #include "PinDefinitionsAndMore.h" //#define IR_OUTPUT_IS_ACTIVE_LOW #define IRSND_IR_FREQUENCY 38000 #define IRSND_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings - requires some FLASH. #include // or disable #include and use only one protocol to save programming space //#define IRSND_SUPPORT_NEC_PROTOCOL 1 //#define IRSND_SUPPORT_NEC_PROTOCOL 1 /* * After setting the definitions we can include the code and compile it. */ #include IRMP_DATA irsnd_data; #if defined(SEND_SAMSUNG) union WordUnion { struct { uint8_t LowByte; uint8_t HighByte; } UByte; struct { int8_t LowByte; int8_t HighByte; } Byte; uint8_t UBytes[2]; int8_t Bytes[2]; uint16_t UWord; int16_t Word; uint8_t *BytePointer; }; #endif 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) 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)); irsnd_init(); irmp_irsnd_LEDFeedback(true); // Enable send signal feedback at LED_BUILTIN Serial.println(F("Send IR signals at pin " STR(IRSND_OUTPUT_PIN))); #if defined(SEND_SAMSUNG) /* * Send Samsung32 */ irsnd_data.protocol = IRMP_SAMSUNG32_PROTOCOL; irsnd_data.address = 0x0707; irsnd_data.command = 0xFB04; // For my Samsung, the high byte is the inverse of the low byte irsnd_data.flags = 0; // repeat frame 0 time #else /* * Send NEC */ irsnd_data.protocol = IRMP_NEC_PROTOCOL; irsnd_data.address = 0x0707; irsnd_data.command = 0xFB; // The required inverse of the 8 bit command is added by the send routine. irsnd_data.flags = 2; // repeat frame 2 times #endif // true = wait for frame and trailing space/gap to end. This stores timer state and restores it after sending. if (!irsnd_send_data(&irsnd_data, true)) { Serial.println(F("Protocol not found")); // name of protocol is printed by irsnd_data_print() } irsnd_data_print(&Serial, &irsnd_data); } void loop() { delay(5000); irsnd_data.command++; #if defined(SEND_SAMSUNG) // For my Samsung remote, the high byte is the inverse of the low byte WordUnion tNextCommand; // using WordUnion saves 14 bytes program memory for the next 3 lines tNextCommand.UWord = irsnd_data.command; tNextCommand.UByte.HighByte = ~tNextCommand.UByte.LowByte; irsnd_data.command = tNextCommand.UWord; #endif irsnd_send_data(&irsnd_data, true); irsnd_data_print(&Serial, &irsnd_data); } ================================================ FILE: examples/TinyReceiver/PinDefinitionsAndMore.h ================================================ /* * PinDefinitionsAndMore.h * * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * * Arduino-IRremote 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 . * */ /* * Pin mapping table for different platforms * * Platform IR input IR output Tone Core/Pin schema * -------------------------------------------------------------- * DEFAULT/AVR 2 3 4 Arduino * ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore * ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore * ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core * ATtiny84 |PB2 |PA4 |PA3 ATTinyCore * ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * MKR* 1 3 4 * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ //#define _IR_MEASURE_TIMING // For debugging purposes. #if defined(__AVR__) #if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore. #include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. #define IR_RECEIVE_PIN PIN_PB0 #define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. #define TONE_PIN PIN_PB3 #define _IR_TIMING_TEST_PIN PIN_PB3 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" // For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. # if defined(ARDUINO_AVR_DIGISPARKPRO) // For use with Digispark original core #define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 //#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards #define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 #define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 #define _IR_TIMING_TEST_PIN 10 // PA4 # elif !defined(PIN_PA3) #error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h. # else // For use with ATTinyCore #define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards #define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 #define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 # endif # elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. #define IR_RECEIVE_PIN PIN_PB2 // INT0 #define IR_SEND_PIN PIN_PA4 #define TONE_PIN PIN_PA3 #define _IR_TIMING_TEST_PIN PIN_PA5 # elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore. #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. // Pin 6 is TX, pin 7 is RX #define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 #define IR_SEND_PIN PIN_PD4 // 4 #define TONE_PIN PIN_PB1 // 9 #define _IR_TIMING_TEST_PIN PIN_PB0 // 8 # elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore // Tiny Core Dev board // https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock // https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock #define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32 #define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32 #define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output #define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 #define IR_SEND_PIN PIN_PA3 // 16 #define TONE_PIN PIN_PA5 // 1 #define APPLICATION_PIN PIN_PA4 // 0 #undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output #define LED_BUILTIN PIN_PB5 // 4 # elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA7 // 3 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 # elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PA4 // 0 # elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 13 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 # else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. #define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit // We have no built in LED at pin 13 -> reuse RX LED #undef LED_BUILTIN #define LED_BUILTIN LED_BUILTIN_RX # endif # endif // defined(__AVR_ATtiny25__)... #elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 // To be compatible with Uno R3. #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 #define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED #define _IR_TIMING_TEST_PIN 2 // D4 #define APPLICATION_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(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) // ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) // ESP32 - C3 other #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 IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) // ESP32 - S3 - !!! NOT tested !!! #define IR_RECEIVE_PIN 15 // alternatively 13 #define IR_SEND_PIN 16 // alternatively 14 #define TONE_PIN 17 #define APPLICATION_PIN 18 #elif defined(ESP32) #include // 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 IR_RECEIVE_PIN 15 // D15 #define IR_SEND_PIN 4 // D4 #define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 #define APPLICATION_PIN 16 // RX2 pin #elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill // Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() #define IR_RECEIVE_PIN PA6 #define IR_RECEIVE_PIN_STRING "PA6" #define IR_SEND_PIN PA7 #define IR_SEND_PIN_STRING "PA7" #define TONE_PIN PA3 #define _IR_TIMING_TEST_PIN PA5 #define APPLICATION_PIN PA2 #define APPLICATION_PIN_STRING "PA2" # if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) // BluePill LED is active low #define FEEDBACK_LED_IS_ACTIVE_LOW # endif #elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards #define IR_RECEIVE_PIN 11 #define IR_SEND_PIN 12 #define TONE_PIN 5 #elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED // Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 #define APPLICATION_PIN 6 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 8 #elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico #define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3) #define IR_SEND_PIN 16 // GPIO16 #define TONE_PIN 17 #define APPLICATION_PIN 18 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 20 // 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(PARTICLE) && defined(A4) // !!!UNTESTED!!! #define IR_RECEIVE_PIN A4 #define IR_SEND_PIN A5 // Particle supports multiple pins #define LED_BUILTIN D7 /* * 4 times the same (default) layout for easy adaption in the future */ #elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) # if defined(USE_ARDUINO_MKR_PIN_LAYOUT) #define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ # else #define IR_RECEIVE_PIN 2 # endif #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) // On the Zero and others we switch explicitly to SerialUSB #define Serial SerialUSB #endif // 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 #elif defined (NRF51) // BBC micro:bit #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define APPLICATION_PIN 1 #define _IR_TIMING_TEST_PIN 4 #define tone(...) void() // no tone() available #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it #else #warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) #if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif ================================================ FILE: examples/TinyReceiver/TinyReceiver.ino ================================================ /* * TinyReceiver.cpp * * Small memory footprint and no timer usage! * * Receives IR protocol data of NEC protocol using pin change interrupts. * For each complete IR frame/command received, the decoded data is copied to the TinyIRReceiverData structure * and the handleReceivedTinyIRData() function is called in an interrupt context. * However, interrupts are explicitly enabled here to allow the use of delay() and millis() etc. * !!!!!!!!!!!!!!!!!!!!!! * Functions called in interrupt context should be running as short as possible, * !!!!!!!!!!!!!!!!!!!!! * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command. * This results in a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License * * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************************ */ #include #include "PinDefinitionsAndMore.h" // Set IR_RECEIVE_PIN for different CPU's //#define DEBUG // to see if attachInterrupt is used //#define TRACE // to see the state of the ISR state machine /* * Protocol selection */ //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. /* * Set compile options to modify the generated code. */ //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define USE_CALLBACK_FOR_TINY_RECEIVER // Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received. #include "TinyIRReceiver.hpp" // include the code 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) // Wait until Serial Monitor is attached. // Required for boards using USB code for Serial like Leonardo. // Is void for USB Serial implementations using external chips e.g. a CH340. while (!Serial) ; // !!! Program will not proceed if no Serial Monitor is attached !!! #endif // Just to know which program is running on my Arduino #if defined(ESP8266) || defined(ESP32) Serial.println(); #endif Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR)); // Enables the interrupt generation on change of IR input signal if (!initPCIInterruptForTinyReceiver()) { Serial.println(F("No interrupt available for pin " STR(IR_RECEIVE_PIN))); // optimized out by the compiler, if not required :-) } #if defined(USE_FAST_PROTOCOL) Serial.println(F("Ready to receive Fast IR signals at pin " STR(IR_RECEIVE_PIN))); #else Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN))); #endif } void loop() { if (TinyReceiverDecode()) { /* * The library has already copied the data used for this output, * so there is no need to do this in the callback function. */ #if !defined(USE_FAST_PROTOCOL) // We have no address at FAST protocol Serial.print(F("Address=0x")); Serial.print(TinyIRReceiverData.Address, HEX); Serial.print(' '); #endif Serial.print(F("Command=0x")); Serial.print(TinyIRReceiverData.Command, HEX); if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) { Serial.print(F(" Repeat")); } if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) { Serial.print(F(" Parity failed")); #if !defined(USE_EXTENDED_NEC_PROTOCOL) && !defined(USE_ONKYO_PROTOCOL) Serial.print(F(", try USE_EXTENDED_NEC_PROTOCOL or USE_ONKYO_PROTOCOL")); #endif } Serial.println(); } /* * Put your code here */ /* * No resume() required :-) */ } /* * Optional code, if you require a callback */ #if defined(USE_CALLBACK_FOR_TINY_RECEIVER) /* * This is the function, which is called if a complete frame was received * This function is executed in an ISR (Interrupt Service Routine) context but with interrupts enabled! * However, it is always best to keep this callback function short and fast! */ # if defined(ESP8266) || defined(ESP32) IRAM_ATTR # endif void handleReceivedTinyIRData() { # if defined(ARDUINO_ARCH_MBED) || defined(ESP32) /* * Printing is not allowed in ISR context for RTOS based cores like ESP, even when interrupts are enabled. * For Mbed we get a kernel panic and "Error Message: Semaphore: 0x0, Not allowed in ISR context" for Serial.print() * for ESP32 we get a "Guru Meditation Error: Core 1 panic'ed" (we also have an RTOS running!) */ # else // As an example, print very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon printTinyReceiverResultMinimal(&Serial); # endif if (TinyIRReceiverData.Command == 0x10) { // do something SHORT here } else if (TinyIRReceiverData.Command == 0x11) { // do something SHORT here too } } #endif ================================================ FILE: examples/TinySender/PinDefinitionsAndMore.h ================================================ /* * PinDefinitionsAndMore.h * * Contains pin definitions for IRremote examples for various platforms * as well as definitions for feedback LED and tone() and includes * * Copyright (C) 2021-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * * Arduino-IRremote 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 . * */ /* * Pin mapping table for different platforms * * Platform IR input IR output Tone Core/Pin schema * -------------------------------------------------------------- * DEFAULT/AVR 2 3 4 Arduino * ATtinyX5 0|PB0 4|PB4 3|PB3 ATTinyCore * ATtiny167 3|PA3 2|PA2 7|PA7 ATTinyCore * ATtiny167 9|PA3 8|PA2 5|PA7 Digispark original core * ATtiny84 |PB2 |PA4 |PA3 ATTinyCore * ATtiny88 3|PD3 4|PD4 9|PB1 ATTinyCore * ATtiny3216 14|PA1 15|PA2 16|PA3 MegaTinyCore * ATtiny1604 2 3|PA5 % * ATtiny816 14|PA1 16|PA3 1|PA5 MegaTinyCore * ATtiny1614 8|PA1 10|PA3 1|PA5 MegaTinyCore * MKR* 1 3 4 * SAMD 2 3 4 * ESP8266 14|D5 12|D6 % * ESP32 15 4 27 * ESP32-C3 2 3 4 * ESP32-S3 2 3 4 * BluePill PA6 PA7 PA3 * APOLLO3 11 12 5 * RP2040 3|GPIO15 4|GPIO16 5|GPIO17 */ //#define _IR_MEASURE_TIMING // For debugging purposes. #if defined(__AVR__) #if (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) && defined(PIN_PB0) // Digispark board. For use with ATTinyCore. #include "ATtinySerialOut.hpp" // TX is at pin 2 - Available as Arduino library "ATtinySerialOut". Saves 700 bytes program memory and 70 bytes RAM for ATtinyCore. #define IR_RECEIVE_PIN PIN_PB0 #define IR_SEND_PIN PIN_PB4 // Pin 2 is serial output with ATtinySerialOut. Pin 1 is internal LED and Pin3 is USB+ with pullup on Digispark board. #define TONE_PIN PIN_PB3 #define _IR_TIMING_TEST_PIN PIN_PB3 # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Digispark pro board #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut" // For ATtiny167 Pins PB6 and PA3 are usable as interrupt source. # if defined(ARDUINO_AVR_DIGISPARKPRO) // For use with Digispark original core #define IR_RECEIVE_PIN 9 // PA3 - on Digispark board labeled as pin 9 //#define IR_RECEIVE_PIN 14 // PB6 / INT0 is connected to USB+ on DigisparkPro boards #define IR_SEND_PIN 8 // PA2 - on Digispark board labeled as pin 8 #define TONE_PIN 5 // PA7 - on Digispark board labeled as pin 5 #define _IR_TIMING_TEST_PIN 10 // PA4 # elif !defined(PIN_PA3) #error ATtiny87 or ATtiny167 is not supported for the selected core. Please extend PinDefinitionsAndMore.h. # else // For use with ATTinyCore #define IR_RECEIVE_PIN PIN_PA3 // On Digispark board labeled as pin 9 - INT0 is connected to USB+ on DigisparkPro boards #define IR_SEND_PIN PIN_PA2 // On Digispark board labeled as pin 8 #define TONE_PIN PIN_PA7 // On Digispark board labeled as pin 5 # endif # elif defined(__AVR_ATtiny84__) && defined(PIN_PB2) // For use with ATTinyCore #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. #define IR_RECEIVE_PIN PIN_PB2 // INT0 #define IR_SEND_PIN PIN_PA4 #define TONE_PIN PIN_PA3 #define _IR_TIMING_TEST_PIN PIN_PA5 # elif defined(__AVR_ATtiny88__) && defined(PIN_PD3) // MH-ET Tiny88 board. For use with ATTinyCore. #include "ATtinySerialOut.hpp" // Available as Arduino library "ATtinySerialOut". Saves 128 bytes program memory. // Pin 6 is TX, pin 7 is RX #define IR_RECEIVE_PIN PIN_PD3 // 3 - INT1 #define IR_SEND_PIN PIN_PD4 // 4 #define TONE_PIN PIN_PB1 // 9 #define _IR_TIMING_TEST_PIN PIN_PB0 // 8 # elif (defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__)) && defined(PIN_PA1) // For use with megaTinyCore // Tiny Core Dev board // https://www.tindie.com/products/xkimi/tiny-core-16-dev-board-attiny1616/ - Out of Stock // https://www.tindie.com/products/xkimi/tiny-core-32-dev-board-attiny3217/ - Out of Stock #define IR_RECEIVE_PIN PIN_PA1 // 14 use 18 instead of PIN_PA1 for TinyCore32 #define IR_SEND_PIN PIN_PA2 // 15, 19 for TinyCore32 #define TONE_PIN PIN_PA3 // 16, 20 for TinyCore32 #define APPLICATION_PIN PIN_PC3 // 13, PIN_PA0 is RESET #undef LED_BUILTIN // No LED available on the TinyCore 32 board, take the one on the programming board which is connected to the DAC output #define LED_BUILTIN PIN_PA6 // use 2 instead of PIN_PA6 for TinyCore32 # elif defined(__AVR_ATtiny816__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 14 #define IR_SEND_PIN PIN_PA3 // 16 #define TONE_PIN PIN_PA5 // 1 #define APPLICATION_PIN PIN_PA4 // 0 #undef LED_BUILTIN // No LED available, take the one which is connected to the DAC output #define LED_BUILTIN PIN_PB5 // 4 # elif defined(__AVR_ATtiny1604__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA7 // 3 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB2 // 5 # elif defined(__AVR_ATtiny1614__) && defined(PIN_PA1) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA5 // 10 TCA0-WO5 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PA4 // 0 # elif defined(__AVR_ATtiny1624__) && defined(PIN_PA6) // For use with megaTinyCore #define IR_RECEIVE_PIN PIN_PA1 // 8 #define IR_SEND_PIN PIN_PA5 // 3 TCA0-WO5 #define TONE_PIN PIN_PA3 // 1 TCA0-WO3 #define APPLICATION_PIN PIN_PB1 // 6 # elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \ || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \ || defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \ || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \ || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \ || defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \ || defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \ || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \ || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__) #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 13 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 # else // Default as for ATmega328 like on Uno, Nano, Leonardo, Teensy 2.0 etc. #define IR_RECEIVE_PIN 2 // To be compatible with interrupt example, pin 2 is chosen here. #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 # if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro is __AVR_ATmega32U4__ but has different external circuit // We have no built in LED at pin 13 -> reuse RX LED #undef LED_BUILTIN #define LED_BUILTIN LED_BUILTIN_RX # endif # endif // defined(__AVR_ATtiny25__)... #elif defined(ARDUINO_ARCH_RENESAS_UNO) // Uno R4 // To be compatible with Uno R3. #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ESP8266) #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D4) is active LOW #define IR_RECEIVE_PIN 14 // D5 #define IR_SEND_PIN 12 // D6 - D4/pin 2 is internal LED #define _IR_TIMING_TEST_PIN 2 // D4 #define APPLICATION_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(ARDUINO_NOLOGO_ESP32C3_SUPER_MINI) // ESP32 - C3 super mini #define FEEDBACK_LED_IS_ACTIVE_LOW // The LED on my board (D8) is active LOW #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32C3) || defined(ARDUINO_ESP32C3_DEV) // ESP32 - C3 other #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 IR_RECEIVE_PIN 6 #define IR_SEND_PIN 7 #define TONE_PIN 9 #define APPLICATION_PIN 10 #elif defined(CONFIG_IDF_TARGET_ESP32S3) || defined(ARDUINO_ESP32S3_DEV) // ESP32 - S3 - !!! NOT tested !!! #define IR_RECEIVE_PIN 15 // alternatively 13 #define IR_SEND_PIN 16 // alternatively 14 #define TONE_PIN 17 #define APPLICATION_PIN 18 #elif defined(ESP32) #include // 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 IR_RECEIVE_PIN 15 // D15 #define IR_SEND_PIN 4 // D4 #define TONE_PIN 27 // D27 25 & 26 are DAC0 and 1 #define APPLICATION_PIN 16 // RX2 pin #elif (defined(ARDUINO_ARCH_STM32) || defined(ARDUINO_ARCH_STM32F1)) && defined(PA6) // BluePill // Timer 3 blocks PA6, PA7, PB0, PB1 for use by Servo or tone() #define IR_RECEIVE_PIN PA6 #define IR_RECEIVE_PIN_STRING "PA6" #define IR_SEND_PIN PA7 #define IR_SEND_PIN_STRING "PA7" #define TONE_PIN PA3 #define _IR_TIMING_TEST_PIN PA5 #define APPLICATION_PIN PA2 #define APPLICATION_PIN_STRING "PA2" # if defined(ARDUINO_GENERIC_STM32F103C) || defined(ARDUINO_BLUEPILL_F103C8) // BluePill LED is active low #define FEEDBACK_LED_IS_ACTIVE_LOW # endif #elif defined(ARDUINO_ARCH_APOLLO3) // Sparkfun Apollo boards #define IR_RECEIVE_PIN 11 #define IR_SEND_PIN 12 #define TONE_PIN 5 #elif defined(ARDUINO_ARCH_MBED) && defined(ARDUINO_ARCH_MBED_NANO) // Arduino Nano 33 BLE and Arduino Nano Connect layout for MBED // Must be before ARDUINO_ARCH_RP2040, since it is the layout for the MBED core of Arduino Nano Connect #define IR_RECEIVE_PIN 3 // GPIO15 Start with pin 3 since pin 2|GPIO25 is connected to LED on Pi pico #define IR_SEND_PIN 4 // GPIO16 #define TONE_PIN 5 #define APPLICATION_PIN 6 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 7 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 8 #elif defined(ARDUINO_ARCH_RP2040) // Arduino Nano Connect, Pi Pico with arduino-pico core https://github.com/earlephilhower/arduino-pico #define IR_RECEIVE_PIN 15 // GPIO15 to be compatible with the Arduino Nano RP2040 Connect (pin3) #define IR_SEND_PIN 16 // GPIO16 #define TONE_PIN 17 #define APPLICATION_PIN 18 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 19 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 20 // 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(PARTICLE) && defined(A4) // !!!UNTESTED!!! #define IR_RECEIVE_PIN A4 #define IR_SEND_PIN A5 // Particle supports multiple pins #define LED_BUILTIN D7 /* * 4 times the same (default) layout for easy adaption in the future */ #elif defined(TEENSYDUINO) // Teensy 2.0 is handled at default for ATmega328 like on Uno, Nano, Leonardo etc. #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_SAM) # if defined(USE_ARDUINO_MKR_PIN_LAYOUT) #define IR_RECEIVE_PIN 1 // Pin 2 on MKR is not interrupt capable, see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ # else #define IR_RECEIVE_PIN 2 # endif #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #if !defined(ARDUINO_SAMD_ADAFRUIT) && !defined(ARDUINO_SEEED_XIAO_M0) // On the Zero and others we switch explicitly to SerialUSB #define Serial SerialUSB #endif // 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 #elif defined (NRF51) // BBC micro:bit #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define APPLICATION_PIN 1 #define _IR_TIMING_TEST_PIN 4 #define tone(...) void() // no tone() available #define noTone(a) void() #define TONE_PIN 42 // Dummy for examples using it #else #warning Board and Core / CPU is not detected using pre-processor symbols -> using default values for IR_RECEIVE_PIN etc., which may not fit. Please extend PinDefinitionsAndMore.h. // Default valued for unidentified boards #define IR_RECEIVE_PIN 2 #define IR_SEND_PIN 3 #define TONE_PIN 4 #define APPLICATION_PIN 5 #define ALTERNATIVE_IR_FEEDBACK_LED_PIN 6 // E.g. used for examples which use LED_BUILDIN for example output. #define _IR_TIMING_TEST_PIN 7 #endif // defined(ESP8266) #if defined(ESP32) || defined(ARDUINO_ARCH_RP2040) || defined(PARTICLE) || defined(ARDUINO_ARCH_MBED) #define SEND_PWM_BY_TIMER // We do not have pin restrictions for this CPU's, so lets use the hardware PWM for send carrier signal generation #else # if defined(SEND_PWM_BY_TIMER) #undef IR_SEND_PIN // SendPin is determined by timer! This avoids warnings in IRremote.hpp and IRTimer.hpp # endif #endif #if !defined (FLASHEND) #define FLASHEND 0xFFFF // Dummy value for platforms where FLASHEND is not defined #endif #if !defined (RAMEND) #define RAMEND 0x0FFF // Dummy value for platforms where RAMEND is not defined #endif ================================================ FILE: examples/TinySender/TinySender.ino ================================================ /* * TinySender.cpp * * Example for sending using TinyIR. By default sends simultaneously using all supported protocols * To use a single protocol, simply delete or comment out all unneeded protocols in the main loop * Program size is significantly reduced when using a single protocol * For example, sending only 8 bit address and command NEC codes saves 780 bytes program memory and 26 bytes RAM compared to SimpleSender, * which does the same, but uses the IRRemote library (and is therefore much more flexible). * * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, * leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License * * Copyright (c) 2022-2024 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************************ */ #include #include "PinDefinitionsAndMore.h" // Set IR_SEND_PIN for different CPU's #include "TinyIRSender.hpp" void setup() { pinMode(LED_BUILTIN, OUTPUT); Serial.begin(115200); // Just to know which program is running on my Arduino Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR)); Serial.print(F("Send IR signals at pin ")); Serial.println(IR_SEND_PIN); } /* * Set up the data to be sent. * The compiler is intelligent and removes the code for 16 bit address handling if we call it with an uint8_t address :-). * Using an uint16_t address or data requires additional 28 bytes program memory for NEC and 56 bytes program memory for FAST. */ uint8_t sAddress = 0x02; //uint16_t sAddress = 0x02; uint8_t sCommand = 0x34; //uint16_t sCommand = 0x34; uint8_t sRepeats = 0; void loop() { /* * Print current send values */ Serial.println(); Serial.print(F("Send now:")); Serial.print(F(" address=0x")); Serial.print(sAddress, HEX); Serial.print(F(" command=0x")); Serial.print(sCommand, HEX); Serial.print(F(" repeats=")); Serial.print(sRepeats); Serial.println(); // Send with FAST // No address and only 16 bits of data, interpreted as 8 bit command and 8 bit inverted command for parity checking Serial.println(F("Send FAST with 8 bit command")); Serial.flush(); sendFAST(IR_SEND_PIN, sCommand, sRepeats); // Send with NEC // NEC uses 8 bit address and 8 bit command each with 8 bit inverted parity checks // However, sendNEC will accept 16 bit address and commands too (but remove the parity checks) Serial.println(F("Send NEC with 8 bit address and command")); Serial.flush(); sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); // Send with Extended NEC // Like NEC, but the address is forced 16 bits with no parity check Serial.println(F("Send ExtendedNEC with 16 bit address and 8 bit command")); Serial.flush(); sendExtendedNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats); // Send with ONKYO // Like NEC, but both the address and command are forced 16 bits with no parity check Serial.println(F("Send ONKYO with 16 bit address and command")); Serial.flush(); sendONKYO(IR_SEND_PIN, sAddress, sCommand, sRepeats); // Send with NEC2 // Instead of sending the NEC special repeat code, sends the full original frame for repeats // Sending NEC2 is done by setting the optional bool NEC2Repeats argument to true (defaults to false) // sendExtendedNEC and sendONKYO also support the NEC2Repeats argument for full frame repeats (not demonstrated here) Serial.println(F("Send NEC2 with 8 bit address and command and original frame repeats")); Serial.flush(); sendNEC(IR_SEND_PIN, sAddress, sCommand, sRepeats, true); /* * Increment send values * Also increment address just for demonstration, which normally makes no sense */ sAddress += 0x0101; sCommand += 0x11; sRepeats++; // clip repeats at 4 if (sRepeats > 4) { sRepeats = 4; } delay(1000); // delay must be greater than 5 ms (RECORD_GAP_MICROS), otherwise the receiver sees it as one long signal } ================================================ FILE: keywords.txt ================================================ ####################################### # Syntax Coloring Map For IRMP ####################################### ####################################### # Datatypes (KEYWORD1) ####################################### irmp_protocol_names KEYWORD1 IRMP_DATA KEYWORD1 ####################################### # Methods and Functions (KEYWORD2) ####################################### irmp_init KEYWORD2 irmp_register_complete_callback_function KEYWORD2 irmp_IsBusy KEYWORD2 irmp_print_active_protocols KEYWORD2 irmp_get_data KEYWORD2 irmp_result_print KEYWORD2 irsnd_init KEYWORD2 irsnd_send_data KEYWORD2 irsnd_data_print KEYWORD2 irsnd_is_busy KEYWORD2 irmp_irsnd_LEDFeedback KEYWORD2 disableIRTimerInterrupt KEYWORD2 enableIRTimerInterrupt KEYWORD2 storeIRTimer KEYWORD2 restoreIRTimer KEYWORD2 ####################################### # Constants (LITERAL1) ####################################### IRMP_FLAG_REPETITION LITERAL1 IRMP_FLAG_RELEASE LITERAL1 IRMP_PROTOCOL_NAMES LITERAL1 IRMP_USE_COMPLETE_CALLBACK LITERAL1 F_INTERRUPTS LITERAL1 IRSND_IR_FREQUENCY LITERAL1 IR_OUTPUT_IS_ACTIVE_LOW LITERAL1 IRMP_ENABLE_PIN_CHANGE_INTERRUPT LITERAL1 USE_ONE_TIMER_FOR_IRMP_AND_IRSND LITERAL1 IRMP_ENABLE_RELEASE_DETECTION LITERAL1 IRMP_HIGH_ACTIVE LITERAL1 ================================================ FILE: library.json ================================================ { "name": "IRMP", "version": "3.7.0", "keywords": "infrared, ir, remote", "description": "Receive and Send infrared signals from your remote.", "homepage": "https://github.com/IRMP-org/IRMP", "repository": { "type": "git", "url": "https://github.com/IRMP-org/IRMP.git" }, "authors": [ { "name": "Armin Joachimsmeyer", "email": "armin.arduino@gmail.com", "maintainer": true }, { "name": "Frank Meyer", "email": "frank@fli4l.de" } ], "license": "GPL-3.0-or-later", "frameworks": "arduino", "platforms": ["atmelavr", "atmelmegaavr", "atmelsam", "espressif8266", "espressif32", "ststm32"], "headers": ["irmp.hpp", "irsnd.hpp"], "examples": "examples/*/*.ino", "export": {"exclude": [".github", "pictures"]} } ================================================ FILE: library.properties ================================================ name=IRMP version=3.7.0 author=Frank Meyer, Armin Joachimsmeyer maintainer=Armin Joachimsmeyer , frank@fli4l.de sentence=Receive and send infrared signals.
paragraph=Supports 50 different IR and 3 RF protocols. Can receive 40 protocols concurrently. Supports ATtiny, AVR and MegaAVR boards as well as ESP8266, ESP32, STM32, SAMD, RP2040 and Apollo boards. category=Signal Input/Output url=https://github.com/IRMP-org/IRMP architectures=avr,megaavr,samd,esp8266,esp32,stm32,STM32F1,apollo3,mbed,mbed_nano,rp2040 includes=irmp.hpp ================================================ FILE: src/IRCommandDispatcher.h ================================================ /* * IRCommandDispatcher.h * * Library to process IR commands by calling functions specified in a mapping array. * * To run this example you need to install the "IRremote" or "IRMP" library under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" * * Copyright (C) 2019-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * 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. * * IRCommandDispatcher 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 . */ #ifndef _IR_COMMAND_DISPATCHER_H #define _IR_COMMAND_DISPATCHER_H #include //#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 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. #if defined(USE_DISPATCHER_COMMAND_STRINGS) #define COMMAND_STRING(anyString) anyString #else #define COMMAND_STRING(anyString) #endif /* * For command mapping file */ #define IR_COMMAND_FLAG_BLOCKING 0x00 // default - blocking command, repeat not accepted, only one command at a time. Stops an already running command. #define IR_COMMAND_FLAG_REPEATABLE 0x01 // repeat accepted #define IR_COMMAND_FLAG_NON_BLOCKING 0x02 // Non blocking (short) command that can be processed any time and may interrupt other IR commands - used for stop, set direction etc. #define IR_COMMAND_FLAG_REPEATABLE_NON_BLOCKING (IR_COMMAND_FLAG_REPEATABLE | IR_COMMAND_FLAG_NON_BLOCKING) #define IR_COMMAND_FLAG_BEEP 0x04 // Do a single short beep before executing command. May not be useful for short or repeating commands. #define IR_COMMAND_FLAG_BLOCKING_BEEP (IR_COMMAND_FLAG_BLOCKING | IR_COMMAND_FLAG_BEEP) #if !defined(IS_STOP_REQUESTED) #define IS_STOP_REQUESTED IRDispatcher.requestToStopReceived #endif #if !defined(RETURN_IF_STOP) #define RETURN_IF_STOP if (IRDispatcher.requestToStopReceived) return #endif #if !defined(BREAK_IF_STOP) #define BREAK_IF_STOP if (IRDispatcher.requestToStopReceived) break #endif #if !defined(DELAY_AND_RETURN_IF_STOP) #define DELAY_AND_RETURN_IF_STOP(aDurationMillis) if (IRDispatcher.delayAndCheckForStop(aDurationMillis)) return #endif /* * Define as COMMAND_EMPTY a code which is not sent by the remote - otherwise please redefine it here */ #if defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT) #define COMMAND_EMPTY __UINT_FAST16_MAX__ // 0xFFFF code no command typedef uint_fast16_t IRCommandType; #else typedef uint_fast8_t IRCommandType; #define COMMAND_EMPTY __UINT_FAST8_MAX__ // 0xFF code no command #endif // Basic mapping structure struct IRToCommandMappingStruct { IRCommandType IRCode; uint8_t Flags; void (*CommandToCall)(); #if defined(USE_DISPATCHER_COMMAND_STRINGS) const char *CommandString; #endif }; struct IRDataForCommandDispatcherStruct { uint16_t address; // to distinguish between multiple senders IRCommandType command; bool isRepeat; volatile uint32_t MillisOfLastCode; // millis() of last IR command -including repeats!- received - for timeouts etc. volatile bool isAvailable; // flag for a polling interpreting function, that a new command has arrived. Is set true by library and set false by main loop. }; class IRCommandDispatcher { public: void init(); void printIRInfo(Print *aSerial); bool checkAndRunNonBlockingCommands(); bool checkAndRunSuspendedBlockingCommands(); void setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext); bool delayAndCheckForStop(uint16_t aDelayMillis); // The main dispatcher function void checkAndCallCommand(bool aCallBlockingCommandImmediately); void printIRCommandString(Print *aSerial, IRCommandType aCommand); void printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex); void setRequestToStopReceived(bool aRequestToStopReceived = true); IRCommandType currentBlockingCommandCalled = COMMAND_EMPTY; // The code for the current called command IRCommandType lastBlockingCommandCalled = COMMAND_EMPTY; // The code for the last called command. Can be evaluated by main loop IRCommandType BlockingCommandToRunNext = COMMAND_EMPTY; // Storage for command currently suspended to allow the current command to end, before it is called by main loop bool justCalledBlockingCommand = false; // Flag that a blocking command was received and called - is set before call of command /* * Flag for running blocking commands to terminate. To check, you can use "if (IRDispatcher.requestToStopReceived) return;" (available as macro RETURN_IF_STOP). * It is set if a blocking IR command received, which cannot be executed directly. Can be reset by main loop, if command has stopped. * It is reset before executing a blocking command. */ volatile bool requestToStopReceived; /* * This flag must be true, if we have a function, which want to interpret the IR codes by itself e.g. the calibrate function of QuadrupedControl */ bool doNotUseDispatcher = false; struct IRDataForCommandDispatcherStruct IRReceivedData; }; extern IRCommandDispatcher IRDispatcher; #endif // _IR_COMMAND_DISPATCHER_H ================================================ FILE: src/IRCommandDispatcher.hpp ================================================ /* * IRCommandDispatcher.hpp * * Library to process IR commands by calling functions specified in a mapping array. * Commands can be tagged as blocking or non blocking. * * To run this example you need to install the "IRremote" or "IRMP" library. * Install it under "Tools -> Manage Libraries..." or "Ctrl+Shift+I" * * The IR library calls a callback function, which executes a non blocking command directly in ISR (Interrupt Service Routine) context! * A blocking command is stored and sets a stop flag for an already running blocking function to terminate. * The blocking command can in turn be executed by main loop by calling IRDispatcher.checkAndRunSuspendedBlockingCommands(). * * Copyright (C) 2019-2026 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of ServoEasing https://github.com/ArminJo/ServoEasing. * 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. * * IRCommandDispatcher 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 . */ /* * Program behavior is modified by the following macros * USE_TINY_IR_RECEIVER * USE_IRMP_LIBRARY * DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT */ #ifndef _IR_COMMAND_DISPATCHER_HPP #define _IR_COMMAND_DISPATCHER_HPP #include #include "IRCommandDispatcher.h" //#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. //#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 #if !defined(USE_TINY_IR_RECEIVER) && !defined(USE_IRREMOTE_LIBRARY) && !defined(USE_IRMP_LIBRARY) #define USE_TINY_IR_RECEIVER // Set TiniIR as default library #endif IRCommandDispatcher IRDispatcher; #if defined(USE_TINY_IR_RECEIVER) /****************************** * Code for the TinyIR library ******************************/ #if defined(USE_ONKYO_PROTOCOL) && ! defined(DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT) #warning ONKYO protocol has 16 bit commands so activating of DISPATCHER_IR_COMMAND_HAS_MORE_THAN_8_BIT is recommended #endif #define USE_CALLBACK_FOR_TINY_RECEIVER // Call the function "handleReceivedTinyIRData()" below each time a frame or repeat is received. #include "TinyIRReceiver.hpp" // included in "IRremote" and "IRMP" library // This block must be located after the includes of other *.hpp files //#define LOCAL_INFO // This enables info output only for this file //#define LOCAL_DEBUG // This enables debug output only for this file - only for development //#define LOCAL_TRACE // This enables trace output only for this file - only for development #include "LocalDebugLevelStart.h" void IRCommandDispatcher::init() { initPCIInterruptForTinyIRReceiver(); } /* * This is the TinyIRReceiver callback function, which is called if a complete command was received. * Interrupts are enabled here to allow e.g. delay() in commands. * Copy the (volatile) IR data in order not to be overwritten on receiving of next frame. * Next, check for right address if IR_ADDRESS is defined. * At last call the dispatcher. */ # if defined(ESP8266) || defined(ESP32) IRAM_ATTR # endif void handleReceivedTinyIRData() { IRDispatcher.IRReceivedData.address = TinyIRReceiverData.Address; IRDispatcher.IRReceivedData.command = TinyIRReceiverData.Command; IRDispatcher.IRReceivedData.isRepeat = TinyIRReceiverData.Flags & IRDATA_FLAGS_IS_REPEAT; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); # if defined(LOCAL_INFO) printTinyIRReceiverResultMinimal(&Serial); # endif # if defined(IR_ADDRESS) // if available, compare address. TinyIRReceiverData.Address saves 6 bytes if (TinyIRReceiverData.Address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h INFO_PRINT(F("Wrong address. Expected 0x")); INFO_PRINTLN(IR_ADDRESS, HEX); } else # endif { IRDispatcher.IRReceivedData.isAvailable = true; // check if dispatcher enabled if (!IRDispatcher.doNotUseDispatcher) { /* * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() */ IRDispatcher.checkAndCallCommand(false); } } } #elif defined(USE_IRREMOTE_LIBRARY) /********************************* * Code for the IRremote library *********************************/ #define DECODE_NEC // Includes Apple and Onkyo #include "IRremote.hpp" // This block must be located after the includes of other *.hpp files //#define LOCAL_INFO // This enables info output only for this file //#define LOCAL_DEBUG // This enables debug output only for this file - only for development //#define LOCAL_TRACE // This enables trace output only for this file - only for development #include "LocalDebugLevelStart.h" void ReceiveCompleteCallbackHandler(); void IRCommandDispatcher::init() { // Start the receiver and if not 3. parameter specified, take LED_BUILTIN pin from the internal boards definition as default feedback LED IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK); /* * Tell the ISR to call this function, when a complete frame has been received */ IrReceiver.registerReceiveCompleteCallback(ReceiveCompleteCallbackHandler); } /* * Callback function * Here we know, that data is available. * This function is executed in an ISR (Interrupt Service Routine) context. * This means that interrupts are blocked here, so delay(), millis() and Serial prints of data longer than the print buffer size etc. will block forever. * This is because they require their internal interrupt routines to run in order to return. * Therefore it is best to make this callback function short and fast! * A dirty hack is to enable interrupts again by calling sei() (enable interrupt again), but you should know what you are doing, */ #if defined(ESP32) || defined(ESP8266) IRAM_ATTR # endif void ReceiveCompleteCallbackHandler() { /* * Fill IrReceiver.decodedIRData */ IrReceiver.decode(); IRDispatcher.IRReceivedData.address = IrReceiver.decodedIRData.address; IRDispatcher.IRReceivedData.command = IrReceiver.decodedIRData.command; IRDispatcher.IRReceivedData.isRepeat = IrReceiver.decodedIRData.flags & IRDATA_FLAGS_IS_REPEAT; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); // Interrupts are already enabled for SUPPORT_MULTIPLE_RECEIVER_INSTANCES #if !defined(SUPPORT_MULTIPLE_RECEIVER_INSTANCES) && !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. # endif # if defined(LOCAL_INFO) IrReceiver.printIRResultMinimal(&Serial); Serial.println(); # endif /* * Enable receiving of the next frame. */ IrReceiver.resume(); # if defined(IR_ADDRESS) // if available, compare address if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { // IR_ADDRESS is defined in *IRCommandMapping.h INFO_PRINT(F("Wrong address. Expected 0x")); INFO_PRINTLN(IR_ADDRESS, HEX); } else # endif { IRDispatcher.IRReceivedData.isAvailable = true; // check if dispatcher enabled if (!IRDispatcher.doNotUseDispatcher) { /* * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() */ IRDispatcher.checkAndCallCommand(false); } } } #elif defined(USE_IRMP_LIBRARY) /****************************** * Code for the IRMP library ******************************/ #define IRMP_USE_COMPLETE_CALLBACK 1 // Enable callback functionality. It is required if IRMP library is used. #define IRMP_PROTOCOL_NAMES 1 // Enable protocol number mapping to protocol strings for printIRInfo() #include "irmp.hpp" #include "LocalDebugLevelStart.h" IRMP_DATA irmp_data; void handleReceivedIRData(); void IRCommandDispatcher::init() { irmp_init(); irmp_register_complete_callback_function(&handleReceivedIRData); // fixed function in IRCommandDispatcher.hpp } /* * This is the callback function, which is called if a complete command was received. * Interrupts are NOT enabled here so we must do it manually to allow e.g. delay() in commands. * Copy the (volatile) IR data in order not to be overwritten on receiving of next frame. * Next, check for right address if IR_ADDRESS is defined. * At last call the dispatcher. */ #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif void handleReceivedIRData() { irmp_get_data(&irmp_data); IRDispatcher.IRReceivedData.address = irmp_data.address; IRDispatcher.IRReceivedData.command = irmp_data.command; IRDispatcher.IRReceivedData.isRepeat = irmp_data.flags & IRMP_FLAG_REPETITION; IRDispatcher.IRReceivedData.MillisOfLastCode = millis(); #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled interrupts(); // To enable tone(), delay() etc. for commands. Be careful with non-blocking and repeatable commands which lasts longer than the IR repeat duration. # endif # if defined(LOCAL_INFO) irmp_result_print(&Serial, &irmp_data); # endif # if defined(IR_ADDRESS) // if available, compare address if (IRDispatcher.IRReceivedData.address != IR_ADDRESS) { INFO_PRINT(F("Wrong address. Expected 0x")); INFO_PRINTLN(IR_ADDRESS, HEX); } else # endif { IRDispatcher.IRReceivedData.isAvailable = true; // check if dispatcher enabled if (!IRDispatcher.doNotUseDispatcher) { /* * Only short (non blocking) commands are executed directly in ISR (Interrupt Service Routine) context, * others are stored for main loop which calls checkAndRunSuspendedBlockingCommands() */ IRDispatcher.checkAndCallCommand(false); } } } #endif // elif defined(USE_IRMP_LIBRARY) /******************************************* * Start of the IR library independent code *******************************************/ void IRCommandDispatcher::printIRInfo(Print *aSerial) { aSerial->println(); // For available IR commands see IRCommandMapping.h https://github.com/ArminJo/PWMMotorControl/blob/master/examples/SmartCarFollower/IRCommandMapping.h #if defined(USE_IRMP_LIBRARY) # if defined(IR_REMOTE_NAME) aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IRMP_INPUT_PIN))); # else aSerial->println(F("Listening to IR remote at pin " STR(IRMP_INPUT_PIN))); # endif aSerial->print(F("Accepted protocols are: ")); irmp_print_active_protocols(&Serial); aSerial->println(); #else # if defined(IR_REMOTE_NAME) aSerial->println(F("Listening to IR remote of type " STR(IR_REMOTE_NAME) " at pin " STR(IR_RECEIVE_PIN))); # else aSerial->println(F("Listening to IR remote at pin " STR(IR_RECEIVE_PIN))); # endif #endif } /* * The main dispatcher function called by IR-ISR, main loop and checkAndRunSuspendedBlockingCommands() * Non blocking commands are executed immediately, blocking commands are executed if no other command is just running. * If another blocking command is currently running, the request to stop is set * and the command is stored for main loop to be later execute by checkAndRunSuspendedBlockingCommands(). * This function sets flags justCalledRegularIRCommand, executingBlockingCommand, requestToStopReceived * @param aCallBlockingCommandImmediately Run blocking command directly, if no other command is just running. * Should be false if called by ISR in order not to block ISR. Is true when called from checkAndRunSuspendedBlockingCommands(). */ void IRCommandDispatcher::checkAndCallCommand(bool aCallBlockingCommandImmediately) { if (IRReceivedData.command == COMMAND_EMPTY) { return; } /* * Search for command in Array of IRToCommandMappingStruct */ for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { if (IRReceivedData.command == IRMapping[i].IRCode) { /* * Command found */ #if defined(LOCAL_INFO) # if defined(__AVR__) # if defined(USE_DISPATCHER_COMMAND_STRINGS) const __FlashStringHelper *tCommandName = reinterpret_cast(IRMapping[i].CommandString); # else char tCommandName[7]; snprintf_P(tCommandName, sizeof(tCommandName), PSTR("0x%x"), IRMapping[i].IRCode); # endif # else # if defined(USE_DISPATCHER_COMMAND_STRINGS) const char *tCommandName = IRMapping[i].CommandString; # else char tCommandName[7]; snprintf(tCommandName, sizeof(tCommandName), "0x%x", IRMapping[i].IRCode); # endif # endif #endif /* * Check for repeat and if repeat is allowed for the current command */ if (IRReceivedData.isRepeat && !(IRMapping[i].Flags & IR_COMMAND_FLAG_REPEATABLE)) { DEBUG_PRINT(F("Repeats of command \"")); DEBUG_PRINT(tCommandName); DEBUG_PRINTLN("\" not accepted"); return; } /* * Do not accept recursive call of the same command */ if (currentBlockingCommandCalled == IRReceivedData.command) { DEBUG_PRINT(F("Recursive command \"")); DEBUG_PRINT(tCommandName); DEBUG_PRINTLN("\" not accepted"); return; } /* * Execute commands */ bool tIsNonBlockingCommand = (IRMapping[i].Flags & IR_COMMAND_FLAG_NON_BLOCKING); if (tIsNonBlockingCommand) { // short command here, just call INFO_PRINT(F("Run non blocking command: ")); INFO_PRINTLN(tCommandName); #if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* * Do (non blocking) buzzer feedback before command is executed */ if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50); } #endif IRMapping[i].CommandToCall(); } else { /* * Blocking command here */ if (aCallBlockingCommandImmediately && currentBlockingCommandCalled == COMMAND_EMPTY) { /* * Here no blocking command was running and we are called from main loop */ requestToStopReceived = false; // Do not stop the command executed now justCalledBlockingCommand = true; currentBlockingCommandCalled = IRReceivedData.command; // set lock for recursive calls lastBlockingCommandCalled = IRReceivedData.command; // set history, can be evaluated by main loop /* * This call is blocking!!! */ INFO_PRINT(F("Run blocking command: ")); INFO_PRINTLN(tCommandName); #if defined(DISPATCHER_BUZZER_FEEDBACK_PIN) && defined(USE_TINY_IR_RECEIVER) /* * Do (non blocking) buzzer feedback before command is executed */ if(IRMapping[i].Flags & IR_COMMAND_FLAG_BEEP) { tone(DISPATCHER_BUZZER_FEEDBACK_PIN, 2200, 50); } #endif IRMapping[i].CommandToCall(); TRACE_PRINTLN(F("End of blocking command")); currentBlockingCommandCalled = COMMAND_EMPTY; } else { /* * Called by ISR or another command still running. * Do not run command directly, but set request to stop to true and store command * for main loop to execute by checkAndRunSuspendedBlockingCommands() */ BlockingCommandToRunNext = IRReceivedData.command; requestToStopReceived = true; // to stop running command INFO_PRINT(F("Requested stop and stored blocking command ")); INFO_PRINT(tCommandName); INFO_PRINTLN(F(" as next command to run.")); } } break; // command found } // if (IRReceivedData.command == IRMapping[i].IRCode) } // for loop return; } /* * Intended to be called from main loop * @return true, if command was called */ bool IRCommandDispatcher::checkAndRunSuspendedBlockingCommands() { /* * Take last rejected command and call associated function */ if (BlockingCommandToRunNext != COMMAND_EMPTY) { INFO_PRINT(F("Run stored command=0x")); INFO_PRINTLN(BlockingCommandToRunNext, HEX); IRReceivedData.command = BlockingCommandToRunNext; BlockingCommandToRunNext = COMMAND_EMPTY; IRReceivedData.isRepeat = false; requestToStopReceived = false; // Signal to main loop to stop the command currently executed checkAndCallCommand(true); return true; } return false; } /* * Not used internally */ void IRCommandDispatcher::setNextBlockingCommand(IRCommandType aBlockingCommandToRunNext) { #if defined(LOCAL_INFO) Serial.print(F("Set next command to run to 0x")); Serial.print(aBlockingCommandToRunNext, HEX); # if defined(USE_DISPATCHER_COMMAND_STRINGS) Serial.print('|'); printIRCommandString(&Serial, aBlockingCommandToRunNext); # endif Serial.println(); #endif BlockingCommandToRunNext = aBlockingCommandToRunNext; requestToStopReceived = true; } /* * Special delay function for the IRCommandDispatcher. Returns prematurely if requestToStopReceived is set. * To be used in blocking functions as delay * @return true - as soon as stop received */ bool IRCommandDispatcher::delayAndCheckForStop(uint16_t aDelayMillis) { uint32_t tStartMillis = millis(); do { if (requestToStopReceived) { return true; } } while (millis() - tStartMillis < aDelayMillis); return false; } void IRCommandDispatcher::printIRCommandStringForArrayIndex(Print *aSerial, uint_fast8_t aMappingArrayIndex) { #if defined(__AVR__) # if defined(USE_DISPATCHER_COMMAND_STRINGS) aSerial->println(reinterpret_cast(IRMapping[aMappingArrayIndex].CommandString)); # else aSerial->print(F("0x")); aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX); # endif #else # if defined(USE_DISPATCHER_COMMAND_STRINGS) aSerial->println(IRMapping[aMappingArrayIndex].CommandString); # else aSerial->print("0x"); aSerial->println(IRMapping[aMappingArrayIndex].IRCode, HEX); # endif #endif } void IRCommandDispatcher::printIRCommandString(Print *aSerial, IRCommandType aCommand) { for (uint_fast8_t i = 0; i < sizeof(IRMapping) / sizeof(struct IRToCommandMappingStruct); ++i) { if (aCommand == IRMapping[i].IRCode) { printIRCommandStringForArrayIndex(aSerial, i); return; } } aSerial->println(F("unknown")); } void IRCommandDispatcher::setRequestToStopReceived(bool aRequestToStopReceived) { requestToStopReceived = aRequestToStopReceived; } #include "LocalDebugLevelEnd.h" #endif // _IR_COMMAND_DISPATCHER_HPP ================================================ FILE: src/IRFeedbackLED.h ================================================ /* * IRFeedbackLED.h * * 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 . * */ // NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_. #if defined(ARDUINO) #ifndef _IR_FEEDBACK_LED_H #define _IR_FEEDBACK_LED_H // define it for convenience reasons. It is an empty function, if NO_LED_FEEDBACK_CODE is enabled void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed); // set the mode #if !defined(NO_LED_FEEDBACK_CODE) /* * Set IRMP_FEEDBACK_LED_PIN to a reasonable value * defining it to 0 disables LED feedback function otherwise LED_BUILTIN (if available) is taken as feedback LED. */ #if !defined(IRMP_FEEDBACK_LED_PIN) # if defined(LED_BUILTIN) #define IRMP_FEEDBACK_LED_PIN LED_BUILTIN # else #warning IRMP_FEEDBACK_LED_PIN and LED_BUILTIN not defined. Pin 5 is used for feedback output if feedback is enabled. You can change this in IRFeedbackLED.h. #define IRMP_FEEDBACK_LED_PIN 5 // choose an arbitrary pin # endif #endif void irmp_irsnd_SetFeedbackLED(bool aSwitchLedOn); // set set pin constexpr auto irmp_blink13 = irmp_irsnd_LEDFeedback; // alias for irmp_blink13 constexpr auto irmp_LEDFeedback = irmp_irsnd_LEDFeedback; // alias for irmp_LEDFeedback constexpr auto irsnd_LEDFeedback = irmp_irsnd_LEDFeedback; // alias for irsnd_LEDFeedback #endif // !defined(NO_LED_FEEDBACK_CODE) #endif // _IR_FEEDBACK_LED_H #endif // defined(ARDUINO) ================================================ FILE: src/IRFeedbackLED.hpp ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IRFeedbackLED.hpp - Arduino extensions for IR feedback LED handling * * Copyright (c) 2020-2021 Armin Joachimsmeyer * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IR_FEEDBACK_LED_HPP #define _IR_FEEDBACK_LED_HPP #if defined(ARDUINO) #include "IRFeedbackLED.h" #if defined(NO_LED_FEEDBACK_CODE) // dummy void function in this case void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed) { (void)aEnableBlinkLed; } #else // defined(NO_LED_FEEDBACK_CODE) static bool irmp_irsnd_LedFeedbackEnabled; #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) // global variable to hold feedback led pin number. Set to 0 to not activating feedback LED by default. uint_fast8_t irmp_irsnd_LedFeedbackPin = 0; # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) bool irmp_irsnd_LedFeedbackPinIsActiveLow = true; // global variable to hold feedback led polarity. # else bool irmp_irsnd_LedFeedbackPinIsActiveLow = false; // global variable to hold feedback led polarity. # endif #endif /* * Enable/disable echoing the input signal to the built in (or specified) LED. */ void irmp_irsnd_LEDFeedback(bool aEnableBlinkLed) { #if defined(IRMP_FEEDBACK_LED_PIN) || defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) irmp_irsnd_LedFeedbackEnabled = aEnableBlinkLed; if (aEnableBlinkLed) { # if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) pinMode(irmp_irsnd_LedFeedbackPin, OUTPUT); if (irmp_irsnd_LedFeedbackPinIsActiveLow) { digitalWrite(irmp_irsnd_LedFeedbackPin, HIGH); } else { digitalWrite(irmp_irsnd_LedFeedbackPin, LOW); } # elif defined(IRMP_FEEDBACK_LED_PIN) pinModeFast(IRMP_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW); # endif # endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) } # if defined(ALLOW_DISABLE_FEEDBACK_LED_EXPLICIT) else { /* * Disable here * normally this code is never used, since disabling is done by setting irmp_led_feedback to false. */ # if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) if(irmp_irsnd_LedFeedbackPin != 0) { pinMode(irmp_irsnd_LedFeedbackPin, INPUT); digitalWrite(irmp_irsnd_LedFeedbackPin, LOW); // to disable internal pullup } # else pinModeFast(IRMP_FEEDBACK_LED_PIN, INPUT); digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW); // to disable internal pullup # endif } # endif #endif // defined(IRMP_FEEDBACK_LED_PIN) || defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) } /* * Internally used from IRMP_ISR() with -oS it is taken as inline function */ #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif void irmp_irsnd_SetFeedbackLED(bool aSwitchLedOn) { #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) if(irmp_irsnd_LedFeedbackPin != 0) { if (irmp_irsnd_LedFeedbackPinIsActiveLow) { digitalWrite(irmp_irsnd_LedFeedbackPin, !aSwitchLedOn); } else { digitalWrite(irmp_irsnd_LedFeedbackPin, aSwitchLedOn); } } #elif defined(IRMP_FEEDBACK_LED_PIN) # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) // If the built in LED on the board is active LOW digitalWriteFast(IRMP_FEEDBACK_LED_PIN, !aSwitchLedOn); # else digitalWriteFast(IRMP_FEEDBACK_LED_PIN, aSwitchLedOn); # endif #endif } #endif // !defined(NO_LED_FEEDBACK_CODE) #endif // defined(ARDUINO) #endif // _IR_FEEDBACK_LED_HPP ================================================ FILE: src/IRTimer.h ================================================ /* * IRTimer.h * * Copyright (C) 2020 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 . * */ // NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_. #if defined(ARDUINO) #if ! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) && defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H) #error You seem to use receive and send in one sketch but forget to define USE_ONE_TIMER_FOR_IRMP_AND_IRSND before the includes. Unfortunately this cannot be done automatically. #endif #if defined(_IRMP_H_) void initIRTimerForReceive(void); #endif #if defined(_IRSND_H_) extern void initIRTimerForSend(void); #endif // defined(_IRSND_H_) extern void irmp_timer_ISR(void); extern void disableIRTimerInterrupt(void); extern void enableIRTimerInterrupt(void); extern void storeIRTimer(void); extern void restoreIRTimer(void); #endif // defined(ARDUINO) ================================================ FILE: src/IRTimer.hpp ================================================ /* * IRTimer.hpp * * Copyright (C) 2020 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 . * */ /* * We use IR timer (timer 2 for AVR) for receive and send. Both functions can be used alternating but not at the same time. * For receive we initialize IR timer to generate interrupts at 10 to 20 kHz for calling irmp_ISR(). * For send we have 76 kHz to toggle output pin. The irsnd_ISR() call rate is 1/4 of IR signal toggle rate. * For send, initIRTimer() is called at each irsnd_send_data(). * The current state of IR timer is stored by initIRTimer() and restored after sending. * This enables us to set up IR timer for receiving and on calling irsnd_send_data() the IR timer is reconfigured for the duration of sending. * Therefore no (non interrupt) receiving is possible during sending of data. */ // NO GUARD here, we have the GUARD below with #ifdef _IRSND_H_ and #ifdef _IRMP_H_. #include "IRTimer.h" #if !defined(TIMER_DECLARED) #define TIMER_DECLARED # if defined(ESP32) static hw_timer_t *sReceiveAndSendInterruptTimer = nullptr; // BluePill in 2 flavors see https://samuelpinches.com.au/3d-printer/cutting-through-some-confusion-on-stm32-and-arduino/ # elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark. // STM32F1 architecture for "Generic STM32F103C series" from "STM32F1 Boards (Arduino_STM32)" of Arduino Board manager // http://dan.drown.org/stm32duino/package_STM32duino_index.json #include // 4 timers and 4. timer (4.channel) is used for tone() /* * Use timer 3 as IRMP timer. * Timer 3 blocks PA6, PA7, PB0, PB1, so if you require one of them as tone() or Servo output, you must choose another timer. */ HardwareTimer sReceiveAndSendInterruptTimer(3); # elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems. // stm32 architecture for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager // https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json #include /* * Use timer 4 as IRMP timer. * Timer 4 blocks PB6, PB7, PB8, PB9, so if you require one of them as tone() or Servo output, you must choose another timer. */ # if defined(TIM4) HardwareTimer sReceiveAndSendInterruptTimer(TIM4); # else HardwareTimer sReceiveAndSendInterruptTimer(TIM2); # endif #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 mbed::Ticker sReceiveAndSendInterruptTimer; /* * RP2040 based boards for pico core * https://github.com/earlephilhower/arduino-pico * https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json * Can use any pin for PWM, no timer restrictions */ #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc. #include "pico/time.h" repeating_timer_t sReceiveAndSendInterruptTimer; bool IRTimerInterruptHandlerHelper(repeating_timer_t*); #elif defined(TEENSYDUINO) // common for all Teensy IntervalTimer sReceiveAndSendInterruptTimer; # endif #endif // TIMER_DECLARED #if defined(_IRMP_H_) // we compile for irmp #undef IR_INTERRUPT_FREQUENCY #define IR_INTERRUPT_FREQUENCY F_INTERRUPTS // define frequency for receive #elif defined(_IRSND_H_) // we compile for irsnd #undef IR_INTERRUPT_FREQUENCY #define IR_INTERRUPT_FREQUENCY IRSND_INTERRUPT_FREQUENCY // define frequency for send #endif // defined(_IRMP_H_) // The eclipse formatter has problems with // comments in undefined code blocks // !!! Must be without trailing comment and closed by @formatter:on // @formatter:off #if defined(_IRMP_H_) void initIRTimerForReceive(void) #elif defined(_IRSND_H_) void initIRTimerForSend(void) #endif { #if defined(__AVR__) // Use Timer 2 # if defined(__AVR_ATmega16__) TCCR2 = _BV(WGM21) | _BV(CS21); // CTC mode, prescale by 8 OCR2 = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz TCNT2 = 0; TIMSK = _BV(OCIE2); // enable interrupt # elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // Since the ISR takes 5 to 22 microseconds for ATtiny@16MHz only 16 and 8 MHz makes sense # if defined(ARDUINO_AVR_DIGISPARK) // standard Digispark settings use timer 1 for millis() and micros() // Timer 0 has only 1 and 8 as useful prescaler TCCR0A = 0; // must be set to zero before configuration! # if (F_CPU / IR_INTERRUPT_FREQUENCY) > 256 // for 8 bit timer OCR0A = OCR0B = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz TCCR0B = _BV(CS01); // presc = 8 # else OCR0A = OCR0B = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz TCCR0B = _BV(CS00); // presc = 1 / no prescaling # endif TCCR0A = _BV(WGM01); // CTC with OCRA as top TCNT0 = 0; TIMSK |= _BV(OCIE0B); // enable compare match interrupt # else // Use timer 1 # if (F_CPU / IR_INTERRUPT_FREQUENCY) > 256 // for 8 bit timer OCR1B = OCR1C = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz TCCR1 = _BV(CTC1) | _BV(CS12); // switch CTC Mode on, set prescaler to 8 # else OCR1B = OCR1C = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz TCCR1 = _BV(CTC1) | _BV(CS10); // switch CTC Mode on, set prescaler to 1 / no prescaling # endif TCNT1 = 0; TIMSK |= _BV(OCIE1B); // enable compare match interrupt # endif # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) // Timer 1 is a 16 bit counter so we need no prescaler ICR1 = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1065 for 15 kHz @16 MHz. compare value: 1/15000 of CPU frequency TCCR1B = _BV(WGM12) | _BV(WGM13) | _BV(CS10); // switch CTC Mode on, set prescaler to 1 / no prescaling TCNT1 = 0; TIMSK1 = _BV(OCIE1B); // enable compare match B interrupt, compare match A is used by tone library # elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every // TCB1 is used by Tone() // TCB2 is used by Servo // TCB3 is used by millis() TCB0.CTRLB = TCB_CNTMODE_INT_gc; TCB0.CCMP = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // compare value: 209 for 76 kHz, 221 for 72kHz @16MHz TCB0.INTFLAGS = TCB_CAPT_bm; // reset interrupt flags TCB0.INTCTRL = TCB_CAPT_bm; // enable capture compare interrupt TCB0.CTRLA = TCB_CLKSEL_CLKDIV1_gc | TCB_ENABLE_bm; # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // TinyCore boards // use one ramp mode and overflow interrupt # if defined(MILLIS_USE_TIMERA0) TCD0.CTRLA = 0; // reset enable bit in order to unprotect the other bits TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc; // must be set since it is used by PWM // TCD0.CMPBSET = 80; TCD0.CMPBCLR = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1332 for 15 kHz, 262 for 76000 interrupts per second @ 20MHz // Generate 50% duty cycle signal for debugging etc. // TCD0.CMPASET = 0; // TCD0.CMPACLR = (F_CPU / (IR_INTERRUPT_FREQUENCY * 2)) - 1; // 50% duty cycle for WOA // TCD0.CTRLC = 0; // reset WOx outputs // _PROTECTED_WRITE(TCD0.FAULTCTRL,FUSE_CMPAEN_bm); // enable WOA signal // PORTA.DIRSET = PIN4_bm; // enable WOA output pin 13/PA4 // _PROTECTED_WRITE(TCD0.FAULTCTRL,FUSE_CMPAEN_bm | FUSE_CMPBEN_bm); // enable WOA + WOB signal signal // PORTA.DIRSET = PIN4_bm | PIN5_bm; // enable WOA + WOB output pins 13/PA4 + 14/PA5 TCD0.INTFLAGS = TCD_OVF_bm; // reset interrupt flags TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt // check enable ready // while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required // enable timer - this locks the other bits and static registers and activates values in double buffered registers TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc| TCD_CNTPRES_DIV1_gc; // System clock, no prescale, no synchronization prescaler # else TCA0.SINGLE.CTRLD = 0; // Single mode - required at least for MegaTinyCore TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc; // Normal mode, top = PER TCA0.SINGLE.PER = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1332 for 15 kHz, 262 for 76000 interrupts per second @ 20MHz TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; // reset interrupt flags TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; // overflow interrupt // check enable ready // while ((TCA0.SINGLE.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required // enable timer - this locks the other bits and static registers and activates values in double buffered registers TCA0.SINGLE.CTRLA = TCA_SINGLE_ENABLE_bm | TCA_SINGLE_CLKSEL_DIV1_gc; // System clock # endif # elif defined(__AVR_ATmega8__) # if (F_CPU / IR_INTERRUPT_FREQUENCY) <= 256 // for 8 bit timer TCCR2 = _BV(WGM21) | _BV(CS20); // CTC mode, no prescale OCR2 = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second # else TCCR2 = _BV(WGM21) | _BV(CS21); // CTC mode, prescale by 8 OCR2 = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz # endif TCNT2 = 0; TIFR = _BV(OCF2) | _BV(TOV2); // reset interrupt flags TIMSK = _BV(OCIE2); // enable TIMER2_COMP_vect interrupt to be compatible with tone() library # elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. TCCR3A = 0; TCCR3B = _BV(CS30) | _BV(WGM32); // no prescale, CTC mode Top OCR3A // Set OCR3B = OCR3A since we use TIMER3_COMPB_vect as interrupt, but run timer in CTC mode with OCR3A as TOP OCR3B = OCR3A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 1065 for 15 kHz, 209 for 76 kHz @ 16MHz TCNT3 = 0; TIMSK3 = _BV(OCIE3B); // enable TIMER3_COMPB_vect interrupt to be compatible with tone() library # elif defined(OCF2B) // __AVR_ATmega328__ here TCCR2A = _BV(WGM21); // CTC mode # if (F_CPU / IR_INTERRUPT_FREQUENCY) <= 256 // for 8 bit timer TCCR2B = _BV(CS20); // no prescale // Set OCR2B = OCR2A since we use TIMER2_COMPB_vect as interrupt, but run timer in CTC mode with OCR2A as TOP OCR2B = OCR2A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second @ 16MHz # else TCCR2B = _BV(CS21); // prescale by 8 OCR2B = OCR2A = (((F_CPU / 8) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY) - 1; // 132 for 15 kHz @16 MHz, 52 for 38 kHz @16 MHz # endif TCNT2 = 0; TIFR2 = _BV(OCF2B) | _BV(OCF2A) | _BV(TOV2); // reset interrupt flags TIMSK2 = _BV(OCIE2B); // enable TIMER2_COMPB_vect interrupt to be compatible with tone() library # elif defined(TCCR1B) // __AVR_ATtiny88__ here TCCR1A = 0; TCCR1B = _BV(WGM12) | _BV(CS10); // CTC mode, no prescaling OCR1A = (F_CPU / IR_INTERRUPT_FREQUENCY) - 1; // 209 for 76000 interrupts per second @ 16MHz TCNT1 = 0; # if defined(TIMSK1) TIMSK1 = _BV(OCIE1A); // Timer/Counter1, Output Compare A Match Interrupt Enable # else // ATmega128 ? TIMSK = _BV(OCIE1A); // Timer/Counter1, Output Compare A Match Interrupt Enable # endif # else // if defined(__AVR_ATmega16__) etc #error "This AVR CPU is not supported by IRMP" # endif // if defined(__AVR_ATmega16__) #elif defined(ESP8266) timer1_isr_init(); timer1_attachInterrupt(irmp_timer_ISR); /* * TIM_DIV1 = 0, //80MHz (80 ticks/us - 104857.588 us max) * TIM_DIV16 = 1, //5MHz (5 ticks/us - 1677721.4 us max) * TIM_DIV256 = 3 //312.5Khz (1 tick = 3.2us - 26843542.4 us max) */ timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP); // must be before timer1_write! timer1_write(((80000000 / 16) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY); // 80000000 holds for 80 and 160 MHz clock! #elif defined(ESP32) // Tasmota requires timer 3 (last of 4 timers) // Use timer with 1 microsecond resolution, main clock is 80MHZ if(sReceiveAndSendInterruptTimer == nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) sReceiveAndSendInterruptTimer = timerBegin(1000000); // Only 1 parameter is required. 1000000 corresponds to 1 MHz / 1 uSec. After successful setup the timer will automatically start. timerAttachInterrupt(sReceiveAndSendInterruptTimer, irmp_timer_ISR); timerAlarm(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true, 0); // 0 in the last parameter is repeat forever # else sReceiveAndSendInterruptTimer = timerBegin(3, 80, true); timerAttachInterrupt(sReceiveAndSendInterruptTimer, irmp_timer_ISR, false); // false -> level interrupt, true -> edge interrupt, but this is not supported :-( timerAlarmWrite(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true); #endif } enableIRTimerInterrupt(); # if defined(DEBUG) && defined(ESP32) Serial.print("CPU frequency="); Serial.print(getCpuFrequencyMhz()); Serial.println("MHz"); Serial.print("Timer clock frequency="); Serial.print(getApbFrequency()); Serial.println("Hz"); # endif // BluePill in 2 flavors #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark. // http://dan.drown.org/stm32duino/package_STM32duino_index.json sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); sReceiveAndSendInterruptTimer.setPrescaleFactor(1); sReceiveAndSendInterruptTimer.setOverflow(F_CPU / IR_INTERRUPT_FREQUENCY); //sReceiveAndSendInterruptTimer.setPeriod(1000000 / IR_INTERRUPT_FREQUENCY); sReceiveAndSendInterruptTimer.attachInterrupt(TIMER_CH1, irmp_timer_ISR); sReceiveAndSendInterruptTimer.refresh(); // Set the timer's count to 0 and update the prescaler and overflow values. #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems. // https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_OUTPUT_COMPARE, NC); // used for generating only interrupts, no pin specified sReceiveAndSendInterruptTimer.setPrescaleFactor(1); sReceiveAndSendInterruptTimer.setOverflow(F_CPU / IR_INTERRUPT_FREQUENCY, TICK_FORMAT); // clock cycles period //sReceiveAndSendInterruptTimer.setOverflow(1000000 / IR_INTERRUPT_FREQUENCY, MICROSEC_FORMAT); // microsecond period sReceiveAndSendInterruptTimer.attachInterrupt(irmp_timer_ISR); // this sets update interrupt enable sReceiveAndSendInterruptTimer.resume(); // Start or resume HardwareTimer: all channels are resumed, interrupts are enabled if necessary #elif defined(ARDUINO_ARCH_SAMD) REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC2_TC3); // GCLK1=32kHz, GCLK0=48MHz // while (GCLK->STATUS.bit.SYNCBUSY) // not required to wait // ; TcCount16* TC = (TcCount16*) TC3; TC->CTRLA.reg &= ~TC_CTRLA_ENABLE; // Enable write access to CTRLA register while (TC->STATUS.bit.SYNCBUSY == 1); // wait for sync // Set Timer counter Mode to 16 bits, use match mode so that the timer counter resets when the count matches the compare register TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ |TC_CTRLA_PRESCALER_DIV1; TC->CC[0].reg = (uint16_t) ((F_CPU / IR_INTERRUPT_FREQUENCY) - 1); // ((48MHz / sampleRate) - 1); // Enable the compare interrupt TC->INTENSET.reg = 0; TC->INTENSET.bit.MC0 = 1; NVIC_EnableIRQ (TC3_IRQn); TC->CTRLA.reg |= TC_CTRLA_ENABLE; // while (TC5->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY); // Not required to wait at end of function //#elif defined(ARDUINO_ARCH_APOLLO3) //// Use Timer 3 segment B // am_hal_ctimer_clear(3, AM_HAL_CTIMER_TIMERB); // reset timer //// only AM_HAL_CTIMER_FN_REPEAT resets counter after match (CTC mode) // am_hal_ctimer_config_single(3, AM_HAL_CTIMER_TIMERB, (AM_HAL_CTIMER_INT_ENABLE | AM_HAL_CTIMER_HFRC_12MHZ | AM_HAL_CTIMER_FN_REPEAT)); // am_hal_ctimer_compare_set(3, AM_HAL_CTIMER_TIMERB, 0, 12000000 / IR_INTERRUPT_FREQUENCY); // am_hal_ctimer_start(3, AM_HAL_CTIMER_TIMERB); // // am_hal_ctimer_int_register(AM_HAL_CTIMER_INT_TIMERB3, irmp_timer_ISR); // am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERB3); // NVIC_EnableIRQ(CTIMER_IRQn); #elif defined(ARDUINO_ARCH_MBED) sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY)); #elif defined(ARDUINO_ARCH_RP2040) // Raspberry Pi Pico, Adafruit Feather RP2040, etc. add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer); // 13.15 us #elif defined(TEENSYDUINO) sReceiveAndSendInterruptTimer.begin(irmp_timer_ISR, 1000000 / IR_INTERRUPT_FREQUENCY); #endif // defined(__AVR__) } // @formatter:on #if !defined(TIMER_FUNCTIONS_DEFINED) #define TIMER_FUNCTIONS_DEFINED /** Temporarily storage for timer register*/ #if defined(__AVR__) uint8_t sTimerTCCRA; uint8_t sTimerTCCRB; # if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) \ || defined(__AVR_ATtiny3217__) || defined(__AVR_ATmega4809__) uint16_t sTimerOCR; // we have a 12/16 bit timer # else uint8_t sTimerOCR; # endif uint8_t sTimerOCRB; uint8_t sTimerTIMSK; #elif defined(ESP8266) uint32_t sTimerLoadValue; #elif defined(ESP32) uint64_t sTimerAlarmValue; #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) || defined(__STM32F1__) uint32_t sTimerOverflowValue; #elif defined(ARDUINO_ARCH_SAMD) // || defined(ARDUINO_ARCH_APOLLO3) uint16_t sTimerCompareCapureValue; #endif // defined(__AVR__) /* * If we do not use receive, we have no timer defined at the first call of this function. * But for AVR saving the timer settings is possible anyway, since it only consists of saving registers. * This helps cooperation with other libraries using the same timer. */ void storeIRTimer(void) { #if defined(__AVR_ATmega16__) sTimerTCCRA = TCCR2; sTimerOCR = OCR2; sTimerTIMSK = TIMSK; #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) # if defined(ARDUINO_AVR_DIGISPARK) sTimerTCCRA = TCCR0A; sTimerTCCRB = TCCR0B; sTimerOCRB = OCR0B; sTimerOCR = OCR0A; sTimerTIMSK = TIMSK; # else sTimerTCCRA = TCCR1; sTimerOCRB = OCR1B; sTimerOCR = OCR1C; sTimerTIMSK = TIMSK; # endif #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) sTimerTCCRB = TCCR1B; sTimerOCR = ICR1; sTimerOCRB = OCR1B; sTimerTIMSK = TIMSK1; #elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every // store current timer state sTimerTCCRA = TCB0.CTRLA; sTimerTCCRB = TCB0.CTRLB; sTimerOCR = TCB0.CCMP; sTimerTIMSK = TCB0.INTCTRL; #elif defined(__AVR_ATmega8__) sTimerTCCRA = TCCR2; sTimerOCR = OCR2; sTimerTIMSK = TIMSK; #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. // store current timer state sTimerTCCRA = TCCR3A; sTimerTCCRB = TCCR3B; sTimerOCR = OCR3A; sTimerOCRB = OCR3B; sTimerTIMSK = TIMSK3; #elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // store settings used for PWM # if defined(MILLIS_USE_TIMERA0) sTimerTCCRA = TCD0.CTRLA; sTimerTCCRB = TCD0.CTRLB; sTimerOCR = TCD0.CMPBCLR; sTimerOCRB = TCD0.CTRLC; sTimerTIMSK = TCD0.INTCTRL; # else sTimerTCCRA = TCA0.SINGLE.CTRLA; sTimerTCCRB = TCA0.SINGLE.CTRLB; sTimerOCR = TCA0.SINGLE.PER; sTimerOCRB = TCA0.SINGLE.CTRLC; sTimerTIMSK = TCA0.SINGLE.INTCTRL; # endif #elif defined(OCF2B) // __AVR_ATmega328__ here // store current timer state sTimerTCCRA = TCCR2A; sTimerTCCRB = TCCR2B; sTimerOCR = OCR2A; sTimerOCRB = OCR2B; sTimerTIMSK = TIMSK2; #elif defined(TCCR1B) // __AVR_ATtiny88__ here // store current timer state sTimerTCCRA = TCCR1A; sTimerTCCRB = TCCR1B; sTimerOCR = OCR1A; sTimerOCRB = OCR1B; # if defined(TIMSK1) sTimerTIMSK = TIMSK1; # else sTimerTIMSK = TIMSK; # endif #elif defined(__AVR__) // #error "This AVR CPU is not supported by IRMP" #elif defined(ESP8266) sTimerLoadValue= T1L; #endif // defined(__AVR_ATmega16__) #if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) // If we do not use receive, we have no timer defined at the first call of this function # if defined(ESP32) # if ESP_ARDUINO_VERSION < ESP_ARDUINO_VERSION_VAL(3, 0, 0) sTimerAlarmValue = timerAlarmRead(sReceiveAndSendInterruptTimer); # endif # elif defined(STM32F1xx) sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow(TICK_FORMAT); # elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow(TICK_FORMAT); # elif defined(__STM32F1__) sTimerOverflowValue = sReceiveAndSendInterruptTimer.getOverflow(); # elif defined(ARDUINO_ARCH_SAMD) sTimerCompareCapureValue = TC3->COUNT16.CC[0].reg; //# elif defined(ARDUINO_ARCH_APOLLO3) // sTimerCompareCapureValue = *((uint32_t *)CTIMERADDRn(CTIMER, 3, CMPRB0)) & 0xFFFF; # endif #endif // defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) } /* * Restore settings of the timer e.g. for IRSND */ void restoreIRTimer(void) { #if defined(__AVR_ATmega16__) TCCR2 = sTimerTCCRA; OCR2 = sTimerOCR; TIMSK = sTimerTIMSK; #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) # if defined(ARDUINO_AVR_DIGISPARK) TCCR0A = sTimerTCCRA; TCCR0B = sTimerTCCRB; OCR0B = sTimerOCRB; OCR0A = sTimerOCR; TIMSK = sTimerTIMSK; # else TCCR1 = sTimerTCCRA; OCR1B = sTimerOCRB; OCR1C = sTimerOCR; TIMSK = sTimerTIMSK; # endif #elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) TCCR1B = sTimerTCCRB; ICR1 = sTimerOCR; OCR1B = sTimerOCRB; TIMSK1 = sTimerTIMSK; #elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every TCB0.CTRLA = sTimerTCCRA; TCB0.CTRLB = sTimerTCCRB; TCB0.CCMP = sTimerOCR; TCB0.INTCTRL = sTimerTIMSK; #elif defined(__AVR_ATmega8__) TCCR2 = sTimerTCCRA; OCR2 = sTimerOCR; TIMSK = sTimerTIMSK; #elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. // restore current timer state TCCR3A = sTimerTCCRA; TCCR3B = sTimerTCCRB; OCR3A = sTimerOCR; OCR3B = sTimerOCRB; TIMSK3 = sTimerTIMSK; #elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // restore settings used for PWM # if defined(MILLIS_USE_TIMERA0) TCD0.CTRLA = 0; // unlock timer TCD0.CTRLB = sTimerTCCRB; TCD0.CMPBCLR = sTimerOCR; TCD0.CTRLC = sTimerOCRB; TCD0.INTCTRL = sTimerTIMSK; TCD0.CTRLA = sTimerTCCRA; # else TCA0.SINGLE.CTRLA = 0; // unlock timer TCA0.SINGLE.CTRLB = sTimerTCCRB; TCA0.SINGLE.PER = sTimerOCR; TCA0.SINGLE.CTRLC = sTimerOCRB; TCA0.SINGLE.INTCTRL = sTimerTIMSK; TCA0.SINGLE.CTRLA = sTimerTCCRA; # endif #elif defined(OCF2B) // __AVR_ATmega328__ here TCCR2A = sTimerTCCRA; TCCR2B = sTimerTCCRB; OCR2A = sTimerOCR; OCR2B = sTimerOCRB; TIMSK2 = sTimerTIMSK; #elif defined(TCCR1B) // __AVR_ATtiny88__ here // store current timer state TCCR1A = sTimerTCCRA; TCCR1B = sTimerTCCRB; OCR1A = sTimerOCR; OCR1B = sTimerOCRB; # if defined(TIMSK1) TIMSK1 = sTimerTIMSK; # else TIMSK = sTimerTIMSK; # endif #elif defined(__AVR__) // #error "This AVR CPU is not supported by IRMP" #elif defined(ESP8266) timer1_write(sTimerLoadValue); #endif // defined(__AVR_ATmega16__) #if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) # if defined(ESP32) # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) // we have no timerAlarmRead, so we just initialize timer again. timerAlarm(sReceiveAndSendInterruptTimer, ((getApbFrequency() / 80) + (IR_INTERRUPT_FREQUENCY / 2)) / IR_INTERRUPT_FREQUENCY, true, 0); // 0 in the last parameter is repeat forever # else timerAlarmWrite(sReceiveAndSendInterruptTimer, sTimerAlarmValue, true); # endif # elif defined(STM32F1xx) sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue, TICK_FORMAT); # elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue, TICK_FORMAT); # elif defined(__STM32F1__) sReceiveAndSendInterruptTimer.setOverflow(sTimerOverflowValue); # elif defined(ARDUINO_ARCH_SAMD) TC3->COUNT16.CC[0].reg = sTimerCompareCapureValue; //# elif defined(ARDUINO_ARCH_APOLLO3) // am_hal_ctimer_compare_set(3, AM_HAL_CTIMER_TIMERB, 0, sTimerCompareCapureValue); # elif defined(ARDUINO_ARCH_MBED) sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY)); #elif defined(ARDUINO_ARCH_RP2040) add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer); # elif defined(TEENSYDUINO) sReceiveAndSendInterruptTimer.update(1000000 / IR_INTERRUPT_FREQUENCY); # endif #endif // defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) } /* * NOT used if IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined * Initialize timer to generate interrupts at a rate F_INTERRUPTS (15000) per second to poll the input pin. */ void disableIRTimerInterrupt(void) { #if defined(__AVR__) // Use Timer 2 # if defined(__AVR_ATmega16__) TIMSK = 0; // disable interrupt # elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) # if defined(ARDUINO_AVR_DIGISPARK) TIMSK &= ~_BV(OCIE0B); // disable interrupt # else TIMSK &= ~_BV(OCIE1B); // disable interrupt # endif # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) TIMSK1 &= ~_BV(OCIE1A); // disable interrupt #elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every TCB0.INTCTRL &= ~TCB_CAPT_bm; #elif defined(__AVR_ATmega8__) TIMSK &= ~_BV(OCIE2); // disable interrupt # elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. TIMSK3 = 0; // disable interrupt # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) # if defined(MILLIS_USE_TIMERA0) TCD0.INTCTRL = 0; // overflow interrupt # else TCA0.SINGLE.INTCTRL = 0; // overflow interrupt # endif # elif defined(OCF2B) // __AVR_ATmega328__ here TIMSK2 = 0; // disable interrupt # elif defined(TCCR1B) // __AVR_ATtiny88__ here # if defined(TIMSK1) TIMSK1 = 0; # else TIMSK = 0; # endif # else // #error "This AVR CPU is not supported by IRMP" # endif // defined(__AVR_ATmega16__) #elif defined(ESP8266) timer1_detachInterrupt(); // disables interrupt too #elif defined(ESP32) if (sReceiveAndSendInterruptTimer != nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) timerStop(sReceiveAndSendInterruptTimer); # else timerAlarmDisable(sReceiveAndSendInterruptTimer); # endif } #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems. sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_DISABLED); sReceiveAndSendInterruptTimer.detachInterrupt(); #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark. sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_DISABLED); sReceiveAndSendInterruptTimer.detachInterrupt(TIMER_CH1); #elif defined(ARDUINO_ARCH_SAMD) TC3->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE; // while (TC3->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY) ; // Not required to wait at end of function //#elif defined(ARDUINO_ARCH_APOLLO3) // am_hal_ctimer_int_disable(AM_HAL_CTIMER_INT_TIMERB3); #elif defined(ARDUINO_ARCH_MBED) sReceiveAndSendInterruptTimer.detach(); #elif defined(ARDUINO_ARCH_RP2040) cancel_repeating_timer(&sReceiveAndSendInterruptTimer); #elif defined(TEENSYDUINO) sReceiveAndSendInterruptTimer.end(); #endif // defined(__AVR__) } // used by AllProtocols example void enableIRTimerInterrupt(void) { #if defined(__AVR__) // Use Timer 2 # if defined(__AVR_ATmega16__) TIMSK = _BV(OCIE2); // enable interrupt # elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) # if defined(ARDUINO_AVR_DIGISPARK) TIMSK |= _BV(OCIE0B); // enable compare match interrupt # else TIMSK |= _BV(OCIE1B); // enable compare match interrupt # endif # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) TIMSK1 |= _BV(OCIE1A); // enable compare match interrupt #elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every TCB0.INTCTRL = TCB_CAPT_bm; #elif defined(__AVR_ATmega8__) TIMSK = _BV(OCIE2); // enable interrupt # elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. TIMSK3 = _BV(OCIE3B); // enable interrupt # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) # if defined(MILLIS_USE_TIMERA0) TCD0.INTCTRL = TCD_OVF_bm; // overflow interrupt # else TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; // overflow interrupt # endif # elif defined(OCF2B) // __AVR_ATmega328__ here TIMSK2 = _BV(OCIE2B); // enable interrupt # elif defined(TCCR1B) // __AVR_ATtiny88__ here # if defined(TIMSK1) TIMSK1 = _BV(OCIE1A); # else TIMSK = _BV(OCIE1A); # endif # else // #error "This AVR CPU is not supported by IRMP" # endif // defined(__AVR_ATmega16__) #elif defined(ESP8266) timer1_attachInterrupt(irmp_timer_ISR); // enables interrupt too #elif defined(ESP32) if (sReceiveAndSendInterruptTimer != nullptr) { # if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0) // timerAlarm() enables it automatically timerStart(sReceiveAndSendInterruptTimer); # else timerAlarmEnable(sReceiveAndSendInterruptTimer); # endif } #elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1) // Recommended original Arduino_STM32 by Roger Clark. // http://dan.drown.org/stm32duino/package_STM32duino_index.json sReceiveAndSendInterruptTimer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE); sReceiveAndSendInterruptTimer.attachInterrupt(TIMER_CH1, irmp_timer_ISR); sReceiveAndSendInterruptTimer.refresh(); // Set the timer's count to 0 and update the prescaler and overflow values. #elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32) // STM32duino by ST Microsystems. // https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json sReceiveAndSendInterruptTimer.setMode(LL_TIM_CHANNEL_CH1, TIMER_OUTPUT_COMPARE, NC); // used for generating only interrupts, no pin specified sReceiveAndSendInterruptTimer.attachInterrupt(irmp_timer_ISR); sReceiveAndSendInterruptTimer.refresh();// Set the timer's count to 0 and update the prescaler and overflow values. #elif defined(ARDUINO_ARCH_SAMD) TC3->COUNT16.CTRLA.reg |= TC_CTRLA_ENABLE; while (TC3->COUNT16.STATUS.reg & TC_STATUS_SYNCBUSY) ; //wait until TC5 is done syncing //#elif defined(ARDUINO_ARCH_APOLLO3) // am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERB3); #elif defined(ARDUINO_ARCH_MBED) sReceiveAndSendInterruptTimer.attach(irmp_timer_ISR, std::chrono::microseconds(1000000 / IR_INTERRUPT_FREQUENCY)); #elif defined(ARDUINO_ARCH_RP2040) add_repeating_timer_us(-1000000 / IR_INTERRUPT_FREQUENCY, IRTimerInterruptHandlerHelper, nullptr, &sReceiveAndSendInterruptTimer); #elif defined(TEENSYDUINO) sReceiveAndSendInterruptTimer.begin(irmp_timer_ISR, 1000000 / IR_INTERRUPT_FREQUENCY); #else #warning Board / CPU is not covered by definitions using pre-processor symbols -> no timer available. Please extend IRTimer.hpp. #endif // defined(__AVR__) } #endif // TIMER_FUNCTIONS_DEFINED /* * If both irmp and irsnd are used, compile it only once in the second step, when all variables are declared. */ #if (! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) || ( defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H) )) && ! defined(ISR_DEFINED) # if !defined(ISR_DEFINED) #define ISR_DEFINED # endif /* * ISR is active while signal is sent AND during the trailing pause of IR frame * Called every 13.5us * Bit bang requires 5.9 us. 5 us for 16 push and 16 pop etc. and 0.9 us for function body * Together with call of irsnd_ISR() 10.5 us (frame) or 9.4 (trailing pause) - measured by scope * We use TIMER2_COMPB_vect to be compatible with tone() library */ #if defined(__AVR__) # if F_CPU < 8000000L #error F_CPU must not be less than 8MHz for IRMP and IRSND # endif # if defined(__AVR_ATmega16__) ISR(TIMER2_COMP_vect) # elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(ARDUINO_AVR_DIGISPARK) ISR(TIMER0_COMPB_vect) # else ISR(TIMER1_COMPB_vect) # endif # elif defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every ISR(TCB0_INT_vect) # elif defined(__AVR_ATmega8__) ISR(TIMER2_COMP_vect) # elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) // Leonardo etc. ISR(TIMER3_COMPB_vect) # elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) # if defined(MILLIS_USE_TIMERA0) ISR(TCD0_OVF_vect) # else ISR(TCA0_OVF_vect) # endif # elif defined(OCF2B) // __AVR_ATmega328__ here ISR(TIMER2_COMPB_vect) # elif defined(TCCR1B) // __AVR_ATtiny88__ here ISR(TIMER1_COMPB_vect) # else // #error "This AVR CPU is not supported by IRMP" # endif // defined(__AVR_ATmega16__) #elif defined(ESP8266) || defined(ESP32) void IRAM_ATTR irmp_timer_ISR(void) #elif defined(ARDUINO_ARCH_SAMD) void TC3_Handler(void) #elif defined(STM32F1xx) && STM32_CORE_VERSION_MAJOR == 1 && STM32_CORE_VERSION_MINOR <= 8 // for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager void irmp_timer_ISR(HardwareTimer *aDummy __attribute__((unused))) // old 1.8 version - changed in stm32duino 1.9 - 5/2020 #elif defined(ARDUINO_ARCH_RP2040) void irmp_timer_ISR(void); bool IRTimerInterruptHandlerHelper(repeating_timer_t*) { // we are called with a different signature irmp_timer_ISR(); return true; } void irmp_timer_ISR(void) #else // STM32F1xx (v1.9), __STM32F1__, ARDUINO_ARCH_APOLLO3, MBED, TEENSYDUINO void irmp_timer_ISR(void) #endif // defined(__AVR__) // Start of ISR { #if defined(ARDUINO_ARCH_SAMD) TC3->COUNT16.INTFLAG.bit.MC0 = 1; // Clear interrupt #endif #if defined(__AVR_ATmega4809__) // Uno WiFi Rev 2, Nano Every // Not tested, but with the experience, I made with the ATtiny3217, I guess it is required TCB0.INTFLAGS = TCB_CAPT_bm; // reset interrupt flags #endif #if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // must reset interrupt flag here # if defined(MILLIS_USE_TIMERA0) TCD0.INTFLAGS = TCD_OVF_bm; # else TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; # endif #endif #if (defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND)) static uint8_t sDivider; // IR signal toggle rate is 2 (4) times IRSND call rate #endif #if defined(IRMP_MEASURE_TIMING) && defined(IR_TIMING_TEST_PIN) digitalWriteFast(IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles #endif #if defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) /* * Send part of ISR */ if(irsnd_busy) { if (irsnd_is_on) { # if defined(IRSND_GENERATE_NO_SEND_RF) // output is active low if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} # else if(sDivider & 0x01) // true / inactive if sDivider is 3 or 1, so we start with active and end with inactive { if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} } else { if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_ACTIVE_LEVEL);} } # endif // defined(IRSND_GENERATE_NO_SEND_RF) } else { // irsnd off here if (__builtin_constant_p(IRSND_OUTPUT_PIN) ) { digitalWriteFast(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} else { digitalWrite(IRSND_OUTPUT_PIN, IR_OUTPUT_INACTIVE_LEVEL);} } /* * Call irsnd_ISR() every second (fourth) call if current LED state is inactive */ if (--sDivider == 0) { // This in turn calls irsnd_on() or irsnd_off(). Empty call requires additional 0.7 us. if (!irsnd_ISR()) { // End of frame restoreIRTimer(); # if ! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) // only send mode required -> disable interrupt disableIRTimerInterrupt(); # endif sDivider = 1; // to call irsnd_ISR() directly at next interrupt } else { sDivider = 4; } } } // if(irsnd_busy) #endif // defined(_IRSND_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) #if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) else { // for receive and send in one ISR #endif #if defined(_IRMP_H_) || defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) /* * Receive part of ISR */ irmp_ISR(); #endif #if defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) } // for receive and send in one ISR #endif #if defined(IRMP_MEASURE_TIMING) && defined(IR_TIMING_TEST_PIN) digitalWriteFast(IR_TIMING_TEST_PIN, LOW); // 2 clock cycles #endif } #endif // (! defined(USE_ONE_TIMER_FOR_IRMP_AND_IRSND) || ( defined(_IRMP_ARDUINO_EXT_H) && defined(_IRSND_ARDUINO_EXT_H) )) && ! defined(ISR_DEFINED) ================================================ FILE: src/LocalDebugLevelEnd.h ================================================ /* * LocalDebugLevelEnd.h * Undefine local macros at the end of an included (.hpp) file * * Copyright (C) 2024 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * * Arduino-Utils 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 INFOse for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /* * Undefine local macros at the end of an included (.hpp) file */ #if defined(LOCAL_TRACE) #undef LOCAL_TRACE #endif #undef TRACE_PRINT #undef TRACE_PRINTLN #undef TRACE_FLUSH #if defined(LOCAL_DEBUG) #undef LOCAL_DEBUG #endif #undef DEBUG_PRINT #undef DEBUG_PRINTLN #undef DEBUG_FLUSH #if defined(LOCAL_INFO) #undef LOCAL_INFO #endif #undef INFO_PRINT #undef INFO_PRINTLN #undef INFO_FLUSH ================================================ FILE: src/LocalDebugLevelStart.h ================================================ /* * LocalDebugLevelStart.h * Include to propagate global debug levels to file local ones and to define appropriate print macros. * !!! If used in included (.hpp) files, #include "LocalDebugLevelEnd.h" must be used at end of file to undefine local macros. * If, for example, #define LOCAL_TRACE is placed before this include, it will not be propagated. This enables TRACE-level output to be selected only. * * LOCAL_TRACE // Information you need to understand details of a function or if you hunt a bug. * LOCAL_DEBUG // Information need to understand the operating of your program. E.g. function calls and values of control variables. * LOCAL_INFO // Information you want to see in regular operation to see what the program is doing. E.g. "Now playing Muppets melody". * LOCAL_WARN // Information that the program may encounter problems, like small Heap/Stack area. * LOCAL_ERROR // Informations to explain why the program will not run. E.g. not enough Ram for all created objects. * * Copyright (C) 2024-2026 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * * Arduino-Utils 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 INFOse for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ /////////////// put this before the include ///////////////////////// // This block must be located after the includes of other *.hpp files //#define LOCAL_INFO // This enables info output only for this file //#define LOCAL_DEBUG // This enables debug output only for this file - only for development //#define LOCAL_TRACE // This enables trace output only for this file - only for development /* * Propagate debug level to local ones but at first not to each other, i.e. enabling TRACE does not enable DEBUG and INFO */ #if defined(TRACE) // Information you need to understand details of a function or if you hunt a bug. #define LOCAL_TRACE # if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS) // Propagate levels by default i.e. enabling TRACE does enable DEBUG and INFO #define LOCAL_DEBUG #define LOCAL_INFO # endif #endif #if defined(DEBUG) // Information need to understand the operating of your program. E.g. function calls and values of control variables. #define LOCAL_DEBUG # if !defined(DO_NOT_PROPAGATE_DEBUG_LEVELS) #define LOCAL_INFO # endif #endif #if defined(INFO) // Information you want to see in regular operation to see what the program is doing. E.g. "START ../src/LightToTone.cpp Version 1.2 from Dec 31 2019" or "Now playing Muppets melody". #define LOCAL_INFO #endif /* * Define appropriate print macros */ #if defined(LOCAL_TRACE) #define TRACE_PRINT(...) Serial.print(__VA_ARGS__) #define TRACE_PRINTLN(...) Serial.println(__VA_ARGS__) #define TRACE_FLUSH() Serial.flush() #else #define TRACE_PRINT(...) void() #define TRACE_PRINTLN(...) void() #define TRACE_FLUSH() void() #endif #if defined(LOCAL_DEBUG) #define DEBUG_PRINT(...) Serial.print(__VA_ARGS__) #define DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__) #define DEBUG_FLUSH() Serial.flush() #else #define DEBUG_PRINT(...) void() #define DEBUG_PRINTLN(...) void() #define DEBUG_FLUSH() void() #endif #if defined(LOCAL_INFO) #define INFO_PRINT(...) Serial.print(__VA_ARGS__) #define INFO_PRINTLN(...) Serial.println(__VA_ARGS__) #define INFO_FLUSH() Serial.flush() #else #define INFO_PRINT(...) void() #define INFO_PRINTLN(...) void() #define INFO_FLUSH() void() #endif ================================================ FILE: src/LongUnion.h ================================================ /* * LongUnion.h * * Copyright (C) 2020-2022 Armin Joachimsmeyer * Email: armin.joachimsmeyer@gmail.com * * This file is part of Arduino-Utils https://github.com/ArminJo/Arduino-Utils. * * Arduino-Utils 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 . * */ #if !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H) #include #ifndef _WORD_UNION_H #define _WORD_UNION_H /** * Union to specify parts / manifestations of a 16 bit Word without casts and shifts. * It also supports the compiler generating small code. * Usage: WordUnion tWord; * tWord.UByte.HighByte = 0x12; */ union WordUnion { struct { uint8_t LowByte; uint8_t HighByte; } UByte; struct { int8_t LowByte; int8_t HighByte; } Byte; uint8_t UBytes[2]; // UBytes[0] is LowByte int8_t Bytes[2]; uint16_t UWord; int16_t Word; uint8_t *BytePointer; }; #endif // _WORD_UNION_H #ifndef _LONG_UNION_H #define _LONG_UNION_H /** * Union to specify parts / manifestations of a 32 bit Long without casts and shifts. * It also supports the compiler generating small code. */ union LongUnion { struct { uint8_t LowByte; uint8_t MidLowByte; uint8_t MidHighByte; uint8_t HighByte; } UByte; struct { int8_t LowByte; int8_t MidLowByte; int8_t MidHighByte; int8_t HighByte; } Byte; /* Does not work for STM32 struct { uint8_t LowByte; uint16_t MidWord; uint8_t HighByte; } UByteWord; */ struct { uint16_t LowWord; uint16_t HighWord; } UWord; struct { int16_t LowWord; int16_t HighWord; } Word; struct { WordUnion LowWord; WordUnion HighWord; } TwoWordUnions; uint8_t UBytes[4]; // seems to have the same code size as using struct UByte int8_t Bytes[4]; // Bytes[0] is LowByte uint16_t UWords[2]; int16_t Words[2]; uint32_t ULong; int32_t Long; float Float; }; #endif // _LONG_UNION_H #ifndef _LONG_LONG_UNION_H #define _LONG_LONG_UNION_H /** * Union to specify parts / manifestations of a 64 bit LongLong without casts and shifts. * It also supports the compiler generating small code. */ union LongLongUnion { struct { uint16_t LowWord; uint16_t MidLowWord; uint16_t MidHighWord; uint16_t HighWord; } UWord; struct { int16_t LowWord; int16_t MidLowWord; int16_t MidHighWord; int16_t HighWord; } Word; struct { WordUnion LowWord; WordUnion MidLowWord; WordUnion MidHighWord; WordUnion HighWord; } FourWordUnions; struct { uint32_t LowLong; uint32_t HighLong; } ULong; struct { int32_t LowLong; int32_t HighLong; } Long; struct { LongUnion LowLong; LongUnion HighLong; } TwoLongUnions; uint8_t UBytes[8]; // seems to have the same code size as using struct UByte int8_t Bytes[8]; uint16_t UWords[4]; int16_t Words[4]; uint64_t ULongLong; int64_t LongLong; #if __DBL_MANT_DIG__== 24 float Floats[2]; // 32 bit double, as for AVR #else // 64 bit double double Double; #endif }; #endif // _LONG_LONG_UNION_H #endif // !defined(_WORD_UNION_H) || !defined(_LONG_UNION_H) || !defined(_LONG_LONG_UNION_H) ================================================ FILE: src/TinyIR.h ================================================ /* * TinyIR.h * * * Copyright (C) 2021-2025 Armin Joachimsmeyer * armin.joachimsmeyer@gmail.com * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * * TinyIRReceiver 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 . * */ #ifndef _TINY_IR_H #define _TINY_IR_H #include #include "LongUnion.h" /** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol * @{ */ #define VERSION_TINYIR "2.3.0" #define VERSION_TINYIR_MAJOR 2 #define VERSION_TINYIR_MINOR 3 #define VERSION_TINYIR_PATCH 0 // The change log is at the bottom of the file /** * Timing for NEC protocol * * see: https://www.sbprojects.net/knowledge/ir/nec.php * LSB first, 1 start bit + 16 bit address + 8 bit data + 8 bit inverted data + 1 stop bit. */ #if !defined(NEC_ADDRESS_BITS) #define NEC_ADDRESS_BITS 16 // 16 bit address or 8 bit address and 8 bit inverted address #define NEC_COMMAND_BITS 16 // Command and inverted command #define NEC_BITS (NEC_ADDRESS_BITS + NEC_COMMAND_BITS) #define NEC_UNIT 560 #define NEC_HEADER_MARK (16 * NEC_UNIT) // 8860 #define NEC_HEADER_SPACE (8 * NEC_UNIT) // 4480 #define NEC_BIT_MARK NEC_UNIT #define NEC_ONE_SPACE (3 * NEC_UNIT) // 1680 #define NEC_ZERO_SPACE NEC_UNIT #define NEC_REPEAT_HEADER_SPACE (4 * NEC_UNIT) // 2240 #define NEC_REPEAT_PERIOD 110000 // Commands are repeated every 110 ms (measured from start to start) for as long as the key on the remote control is held down. #define NEC_MINIMAL_DURATION 49900 // NEC_HEADER_MARK + NEC_HEADER_SPACE + 32 * 2 * NEC_UNIT + NEC_UNIT // 2.5 because we assume more zeros than ones #define NEC_MAXIMUM_REPEAT_DISTANCE (NEC_REPEAT_PERIOD - NEC_MINIMAL_DURATION + 10000) // 70 ms #endif /** * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, * leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. */ /* Protocol=FAST Address=0x0 Command=0x76 Raw-Data=0x8976 16 bits LSB first +2100,-1050 + 550,- 500 + 550,-1550 + 550,-1550 + 550,- 500 + 550,-1550 + 550,-1550 + 550,-1550 + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 + 550,-1550 + 550,- 500 + 550,- 500 + 550,- 500 + 550,-1550 + 550 Sum: 28900 */ #define FAST_KHZ 38 #define FAST_ADDRESS_BITS 0 // No address #define FAST_COMMAND_BITS 16 // Command and inverted command (parity) #define FAST_BITS (FAST_ADDRESS_BITS + FAST_COMMAND_BITS) #define FAST_UNIT 526 // 20 periods of 38 kHz (526.315789) #define FAST_BIT_MARK FAST_UNIT #define FAST_ONE_SPACE (3 * FAST_UNIT) // 1578 -> bit period = 2104 #define FAST_ZERO_SPACE FAST_UNIT // 526 -> bit period = 1052 #define FAST_HEADER_MARK (4 * FAST_UNIT) // 2104 #define FAST_HEADER_SPACE (2 * FAST_UNIT) // 1052 #define FAST_REPEAT_PERIOD 50000 // Commands are repeated every 50 ms (measured from start to start) for as long as the key on the remote control is held down. #define FAST_REPEAT_DISTANCE (FAST_REPEAT_PERIOD - (55 * FAST_UNIT)) // 19 ms #define FAST_MAXIMUM_REPEAT_DISTANCE (FAST_REPEAT_DISTANCE + 10000) // 29 ms /* * Definitions to switch between FAST and NEC/ONKYO timing with the same code. */ #if defined(USE_FAST_PROTOCOL) #define ENABLE_NEC2_REPEATS // Disables detection of special short frame NEC repeats. Saves 40 bytes program memory. #define TINY_RECEIVER_ADDRESS_BITS FAST_ADDRESS_BITS #define TINY_RECEIVER_COMMAND_BITS FAST_COMMAND_BITS #if !defined(TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY) #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity //#define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity - not tested #endif #define TINY_RECEIVER_BITS FAST_BITS #define TINY_RECEIVER_UNIT FAST_UNIT #define TINY_RECEIVER_HEADER_MARK FAST_HEADER_MARK #define TINY_RECEIVER_HEADER_SPACE FAST_HEADER_SPACE #define TINY_RECEIVER_MARK_TIMEOUT (2 * FAST_HEADER_MARK) #define TINY_RECEIVER_BIT_MARK FAST_BIT_MARK #define TINY_RECEIVER_ONE_SPACE FAST_ONE_SPACE #define TINY_RECEIVER_ZERO_SPACE FAST_ZERO_SPACE #define TINY_RECEIVER_ONE_THRESHOLD (2 * FAST_UNIT) // 1052 #define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE FAST_MAXIMUM_REPEAT_DISTANCE // for repeat detection #else #define TINY_RECEIVER_ADDRESS_BITS NEC_ADDRESS_BITS // the address bits + parity # if defined(USE_ONKYO_PROTOCOL) #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity # elif defined(USE_EXTENDED_NEC_PROTOCOL) #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY false // 16 bit address without parity # else #define TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity # endif #define TINY_RECEIVER_COMMAND_BITS NEC_COMMAND_BITS // the command bits + parity # if defined(USE_ONKYO_PROTOCOL) #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY false // 16 bit command without parity # else #define TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY true // 8 bit and 8 bit parity # endif #define TINY_RECEIVER_BITS NEC_BITS #define TINY_RECEIVER_UNIT NEC_UNIT #define TINY_RECEIVER_HEADER_MARK NEC_HEADER_MARK #define TINY_RECEIVER_MARK_TIMEOUT (2 * NEC_HEADER_MARK) #define TINY_RECEIVER_HEADER_SPACE NEC_HEADER_SPACE #define TINY_RECEIVER_BIT_MARK NEC_BIT_MARK #define TINY_RECEIVER_ONE_SPACE NEC_ONE_SPACE #define TINY_RECEIVER_ZERO_SPACE NEC_ZERO_SPACE #define TINY_RECEIVER_ONE_THRESHOLD (2 * NEC_UNIT) // 1120 #define TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE NEC_MAXIMUM_REPEAT_DISTANCE #endif #if defined(USE_CALLBACK_FOR_TINY_RECEIVER) /* * This function is called, if a complete command was received and must be implemented in the file (user code) * which includes this library if USE_CALLBACK_FOR_TINY_RECEIVER is activated. */ extern void handleReceivedTinyIRData(); #endif #if !defined(MICROS_IN_ONE_SECOND) #define MICROS_IN_ONE_SECOND 1000000L #endif #if !defined(MICROS_IN_ONE_MILLI) #define MICROS_IN_ONE_MILLI 1000L #endif /* * Macros for comparing timing values */ #define lowerValue25Percent(aDuration) (aDuration - (aDuration / 4)) #define upperValue25Percent(aDuration) (aDuration + (aDuration / 4)) #define lowerValue50Percent(aDuration) (aDuration / 2) // (aDuration - (aDuration / 2)) #define upperValue50Percent(aDuration) (aDuration + (aDuration / 2)) /* * The states for the state machine */ #define IR_RECEIVER_STATE_WAITING_FOR_START_MARK 0 #define IR_RECEIVER_STATE_WAITING_FOR_START_SPACE 1 #define IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK 2 #define IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE 3 #define IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK 4 #define IR_RECEIVER_STATE_WAITING_FOR_STOP_MARK 5 /** * Control and data variables of the state machine for TinyIRReceiver */ struct TinyIRReceiverStruct { /* * State machine */ uint32_t LastChangeMicros; ///< Microseconds of last Pin Change Interrupt. uint8_t IRReceiverState; ///< The state of the state machine. uint8_t IRRawDataBitCounter; ///< How many bits are currently contained in raw data. /* * Data */ #if (TINY_RECEIVER_BITS > 16) uint32_t IRRawDataMask; ///< The corresponding bit mask for IRRawDataBitCounter. LongUnion IRRawData; ///< The current raw data. LongUnion helps with decoding of address and command. #else uint16_t IRRawDataMask; ///< The corresponding bit mask for IRRawDataBitCounter. WordUnion IRRawData; ///< The current raw data. WordUnion helps with decoding of command. #endif uint8_t Flags; ///< One of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT, and IRDATA_FLAGS_PARITY_FAILED }; /* * Definitions for member TinyIRReceiverCallbackDataStruct.Flags * This is a copy of flags from IRremoteInt.h */ #define IRDATA_FLAGS_EMPTY 0x00 #define IRDATA_FLAGS_IS_REPEAT 0x01 #define IRDATA_FLAGS_IS_AUTO_REPEAT 0x02 // not used for TinyIR #define IRDATA_FLAGS_PARITY_FAILED 0x04 ///< the current (autorepeat) frame violated parity check /** * Is filled before calling the user callback to transfer received data to main loop for further processing. */ struct TinyIRReceiverCallbackDataStruct { #if (TINY_RECEIVER_ADDRESS_BITS > 0) # if (TINY_RECEIVER_ADDRESS_BITS == 16) && !TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY uint16_t Address; # else uint8_t Address; # endif #endif # if (TINY_RECEIVER_COMMAND_BITS == 16) && !TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY uint16_t Command; #else uint8_t Command; #endif uint8_t Flags; // Bit coded flags. Can contain one of the bits: IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bool justWritten; ///< Is set true if new data is available. Used by the main loop / TinyIRReceiverDecode(), to avoid multiple evaluations of the same IR frame. }; extern volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; bool isIRReceiverAttachedForTinyReceiver(); bool initPCIInterruptForTinyReceiver(); bool enablePCIInterruptForTinyReceiver(); void disablePCIInterruptForTinyReceiver(); bool isTinyReceiverIdle(); bool TinyReceiverDecode(); void printTinyReceiverResultMinimal(Print *aSerial); bool isIRReceiverAttachedForTinyIRReceiver(); bool initPCIInterruptForTinyIRReceiver(); bool enablePCIInterruptForTinyIRReceiver(); void disablePCIInterruptForTinyIRReceiver(); bool isTinyIRReceiverIdle(); bool TinyIRReceiverDecode(); void printTinyIRReceiverResultMinimal(Print *aSerial); void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats = 0); void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); // Send NEC with 16 bit command, even if aCommand < 0x100 void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0) __attribute__ ((deprecated ("Renamed to sendNEC()."))); void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats = 0, bool aSendNEC2Repeats = false); #if defined(NO_LED_FEEDBACK_CODE) # if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) #define NO_LED_RECEIVE_FEEDBACK_CODE # endif # if !defined(NO_LED_SEND_FEEDBACK_CODE) #define NO_LED_SEND_FEEDBACK_CODE # endif #endif #if !defined(IR_FEEDBACK_LED_PIN) && defined(LED_BUILTIN) #define IR_FEEDBACK_LED_PIN LED_BUILTIN #endif /* * Version 2.3.0 - 3/2026 * - Renamed TinyReceiver*() functions to TinyIRReceiver*(). * * Version 2.2.0 - 7/2024 * - New TinyReceiverDecode() function to be used as drop in for IrReceiver.decode(). * * Version 2.1.0 - 2/2024 * - New sendExtendedNEC() function and new parameter aSendNEC2Repeats. * * Version 2.0.0 - 10/2023 * - New TinyIRReceiverData which is filled with address, command and flags. * - Removed parameters address, command and flags from callback handleReceivedTinyIRData() and printTinyReceiverResultMinimal(). * - Callback function now only enabled if USE_CALLBACK_FOR_TINY_RECEIVER is activated. * * Version 1.2.0 - 01/2023 * - Added ONKYO protocol, NEC with 16 bit address and command, instead of 8 bit + 8 bit parity address and command. * - Renamed functions and macros. * * Version 1.1.0 - 01/2023 * - FAST protocol added. */ /** @}*/ #endif // _TINY_IR_H ================================================ FILE: src/TinyIRReceiver.hpp ================================================ /* * TinyIRReceiver.hpp * * Receives IR data of NEC protocol using pin change interrupts. * NEC is the protocol of most cheap remote controls for Arduino. * * Parity check is done for address and data. * On a completely received IR command, the user function handleReceivedIRData(uint8_t aAddress, uint8_t aCommand, uint8_t aFlags) * is called in interrupt context but with interrupts being enabled to enable use of delay() etc. * !!!!!!!!!!!!!!!!!!!!!! * Functions called in interrupt context should be running as short as possible, * so if you require longer action, save the data (address + command) and handle them in the main loop. * !!!!!!!!!!!!!!!!!!!!! * aFlags can contain one of IRDATA_FLAGS_EMPTY, IRDATA_FLAGS_IS_REPEAT and IRDATA_FLAGS_PARITY_FAILED bits * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, * leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License * * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************************ */ /* * This library can be configured at compile time by the following options / macros: * For more details see: https://github.com/Arduino-IRremote/Arduino-IRremote#compile-options--macros-for-this-library (scroll down) * * - IR_RECEIVE_PIN The pin number for TinyIRReceiver IR input. * - IR_FEEDBACK_LED_PIN The pin number for TinyIRReceiver feedback LED. * - NO_LED_FEEDBACK_CODE Disables the feedback LED function for send and receive. Saves 14 bytes program memory. * - NO_LED_RECEIVE_FEEDBACK_CODE Disables the LED feedback code for receive. * - NO_LED_SEND_FEEDBACK_CODE Disables the LED feedback code for send. * - DISABLE_PARITY_CHECKS Disable parity checks. Saves 48 bytes of program memory. * - USE_EXTENDED_NEC_PROTOCOL Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. * - USE_ONKYO_PROTOCOL Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. * - USE_FAST_PROTOCOL Use FAST protocol (no address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command) instead of NEC. * - ENABLE_NEC2_REPEATS Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. * - USE_CALLBACK_FOR_TINY_RECEIVER Call the user provided function "void handleReceivedTinyIRData()" each time a frame or repeat is received. */ #ifndef _TINY_IR_RECEIVER_HPP #define _TINY_IR_RECEIVER_HPP #include /* * Protocol selection */ //#define USE_EXTENDED_NEC_PROTOCOL // Like NEC, but take the 16 bit address as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_ONKYO_PROTOCOL // Like NEC, but take the 16 bit address and command each as one 16 bit value and not as 8 bit normal and 8 bit inverted value. //#define USE_FAST_PROTOCOL // Use FAST protocol instead of NEC / ONKYO. //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. //#define DISABLE_PARITY_CHECKS // Disable parity checks. Saves 48 bytes of program memory. //#define IR_RECEIVE_PIN 2 //#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN #include "TinyIR.h" #include "digitalWriteFast.h" /** \addtogroup TinyIRReceiver Minimal receiver for NEC and FAST protocol * @{ */ // This block must be located after the includes of other *.hpp files //#define LOCAL_DEBUG // This enables debug output only for this file - only for development //#define LOCAL_TRACE // This enables trace output only for this file - only for development #include "LocalDebugLevelStart.h" #if defined(LOCAL_DEBUG) #define LOCAL_DEBUG_ATTACH_INTERRUPT #else //#define LOCAL_DEBUG_ATTACH_INTERRUPT // To see if attachInterrupt() or static interrupt (by register tweaking) is used and no other debug output #endif //#define _IR_MEASURE_TIMING // Activate this if you want to enable internal hardware timing measurement. //#define _IR_TIMING_TEST_PIN 7 TinyIRReceiverStruct TinyIRReceiverControl; volatile TinyIRReceiverCallbackDataStruct TinyIRReceiverData; // The persistent copy of all IR data after receiving a complete frame. To be used by main program. /* * Set input pin and output pin definitions etc. */ #if defined(IR_INPUT_PIN) #warning "IR_INPUT_PIN is deprecated, use IR_RECEIVE_PIN" #define IR_RECEIVE_PIN IR_INPUT_PIN #endif #if !defined(IR_RECEIVE_PIN) # if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) #warning "IR_RECEIVE_PIN is not defined, so it is set to 10" #define IR_RECEIVE_PIN 10 # elif defined(__AVR_ATtiny816__) #warning "IR_RECEIVE_PIN is not defined, so it is set to 14" #define IR_RECEIVE_PIN 14 # else #warning "IR_RECEIVE_PIN is not defined, so it is set to 2" #define IR_RECEIVE_PIN 2 # endif #endif #if !defined(NO_LED_RECEIVE_FEEDBACK_CODE) #define LED_RECEIVE_FEEDBACK_CODE // Resolve the double negative #endif #if !( \ (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \ || defined(__AVR_ATtiny88__) /* MH-ET LIVE Tiny88 */ \ || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \ || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \ || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \ || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \ /* ATmegas with ports 0,1,2 above and ATtiny167 only 2 pins below */ \ || ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\ || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IR_RECEIVE_PIN == 3) || (IR_RECEIVE_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \ ) /* * Cannot use any static ISR vector here. In other cases we have code provided for generating interrupt on pin change. * Requires additional 112 bytes program memory + 4 bytes RAM */ #define TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT #endif /** * Declaration of the callback function provided by the user application. * It is called every time a complete IR command or repeat was received. */ extern void handleReceivedTinyIRData(); uint32_t sMicrosOfGap; // The length of the gap before the start bit, used for trace /** * The ISR (Interrupt Service Routine) of TinyIRRreceiver. * It handles the NEC protocol decoding and calls the user callback function on complete. * 5 us + 3 us for push + pop for a 16MHz ATmega */ #if defined(ESP8266) || defined(ESP32) IRAM_ATTR #endif void IRPinChangeInterruptHandler(void) { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) digitalWriteFast(_IR_TIMING_TEST_PIN, HIGH); // 2 clock cycles #endif /* * Save IR input level * Negative logic, true / HIGH means inactive / IR space, LOW / false means IR mark. */ uint_fast8_t tIRLevel = digitalReadFast(IR_RECEIVE_PIN); #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, tIRLevel); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, !tIRLevel); # endif #endif /* * 1. compute microseconds after last change */ // Repeats can be sent after a pause, which is longer than 64000 microseconds, so we need a 32 bit value for check of repeats uint32_t tCurrentMicros = micros(); uint32_t tMicrosOfMarkOrSpace32 = tCurrentMicros - TinyIRReceiverControl.LastChangeMicros; // statement is required to force 32 bit arithmetic uint16_t tMicrosOfMarkOrSpace = tMicrosOfMarkOrSpace32; TinyIRReceiverControl.LastChangeMicros = tCurrentMicros; uint8_t tState = TinyIRReceiverControl.IRReceiverState; TRACE_PRINT(tState); TRACE_PRINT(F(" D=")); TRACE_PRINT(tMicrosOfMarkOrSpace); // TRACE_PRINT(F(" I=")); // TRACE_PRINT(tIRLevel); TRACE_PRINT('|'); if (tIRLevel == LOW) { /* * We are at the start of a mark here and tMicrosOfMarkOrSpace is the time of the previous space */ if (tMicrosOfMarkOrSpace > TINY_RECEIVER_MARK_TIMEOUT) { // timeout -> must reset state machine tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK) { // We are at the beginning of the header mark, check timing at the next transition tState = IR_RECEIVER_STATE_WAITING_FOR_START_SPACE; TinyIRReceiverControl.Flags = IRDATA_FLAGS_EMPTY; // If we do it here, it saves 4 bytes #if defined(TRACE) // Do not use LOCAL_TRACE here since sMicrosOfGap is read in a cpp file at TRACE sMicrosOfGap = tMicrosOfMarkOrSpace32; #endif #if defined(ENABLE_NEC2_REPEATS) // Check for repeat, where full frame is sent again after TINY_RECEIVER_REPEAT_PERIOD ms // Not required for NEC, where repeats are detected by a special header space duration // Must use 32 bit arithmetic here! if (tMicrosOfMarkOrSpace32 < TINY_RECEIVER_MAXIMUM_REPEAT_DISTANCE) { TinyIRReceiverControl.Flags = IRDATA_FLAGS_IS_REPEAT; } #endif } else if (tState == IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK) { if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_SPACE) && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_SPACE)) { /* * We had a valid data header space before -> initialize data */ TinyIRReceiverControl.IRRawDataBitCounter = 0; #if (TINY_RECEIVER_BITS > 16) TinyIRReceiverControl.IRRawData.ULong = 0; #else TinyIRReceiverControl.IRRawData.UWord = 0; #endif TinyIRReceiverControl.IRRawDataMask = 1; tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE; #if !defined(ENABLE_NEC2_REPEATS) // Alternatively check for NEC repeat header space length } else if (tMicrosOfMarkOrSpace >= lowerValue25Percent(NEC_REPEAT_HEADER_SPACE) && tMicrosOfMarkOrSpace <= upperValue25Percent(NEC_REPEAT_HEADER_SPACE) && TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS) { /* * We have a repeat header here and no broken receive before -> set repeat flag */ TinyIRReceiverControl.Flags = IRDATA_FLAGS_IS_REPEAT; tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE; #endif } else { // This parts are optimized by the compiler into jumps to one code :-) // Wrong length -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK) { /* * Start of data mark here, check data space length * Maybe the minimum length check could be removed here. */ if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_ZERO_SPACE) && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_ONE_SPACE)) { // We have a valid bit here tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE; if (tMicrosOfMarkOrSpace >= TINY_RECEIVER_ONE_THRESHOLD) { // we received a 1 #if (TINY_RECEIVER_BITS > 16) TinyIRReceiverControl.IRRawData.ULong |= TinyIRReceiverControl.IRRawDataMask; #else TinyIRReceiverControl.IRRawData.UWord |= TinyIRReceiverControl.IRRawDataMask; #endif } else { // we received a 0 - empty code for documentation } // prepare for next bit TinyIRReceiverControl.IRRawDataMask = TinyIRReceiverControl.IRRawDataMask << 1; TinyIRReceiverControl.IRRawDataBitCounter++; } else { // Wrong length -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } else { // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } else { /* * We are at the start of a space here and tMicrosOfMarkOrSpace is the time of the previous mark * */ if (tState == IR_RECEIVER_STATE_WAITING_FOR_START_SPACE) { /* * Check length of header mark here */ if (tMicrosOfMarkOrSpace >= lowerValue25Percent(TINY_RECEIVER_HEADER_MARK) && tMicrosOfMarkOrSpace <= upperValue25Percent(TINY_RECEIVER_HEADER_MARK)) { tState = IR_RECEIVER_STATE_WAITING_FOR_FIRST_DATA_MARK; } else { // Wrong length of header mark -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } else if (tState == IR_RECEIVER_STATE_WAITING_FOR_DATA_SPACE) { // Check data mark length if (tMicrosOfMarkOrSpace >= lowerValue50Percent(TINY_RECEIVER_BIT_MARK) && tMicrosOfMarkOrSpace <= upperValue50Percent(TINY_RECEIVER_BIT_MARK)) { /* * We have a valid mark here, check for transmission complete, i.e. the mark of the stop bit */ if (TinyIRReceiverControl.IRRawDataBitCounter >= TINY_RECEIVER_BITS #if !defined(ENABLE_NEC2_REPEATS) || (TinyIRReceiverControl.Flags & IRDATA_FLAGS_IS_REPEAT) // Do not check for full length received, if we have a short repeat frame #endif ) { /* * Code complete -> optionally check parity */ // Reset state for new start tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_ADDRESS_BITS == 16) && TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY /* * Check address parity * Address is sent first and contained in the lower word */ if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) { #if defined(ENABLE_NEC2_REPEATS) TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; // here we can have the repeat flag already set #else TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; // here we do not check anything, if we have a repeat #endif } #endif #if !defined(DISABLE_PARITY_CHECKS) && (TINY_RECEIVER_COMMAND_BITS == 16) && TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY /* * Check command parity */ #if (TINY_RECEIVER_ADDRESS_BITS > 0) if (TinyIRReceiverControl.IRRawData.UBytes[2] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[3])) { #if defined(ENABLE_NEC2_REPEATS) TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; #else TinyIRReceiverControl.Flags = IRDATA_FLAGS_PARITY_FAILED; #endif DEBUG_PRINT(F("Parity check for command failed. Command=")); DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[2], HEX); DEBUG_PRINT(F(" parity=")); DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[3], HEX); #else // No address, so command and parity are in the lowest bytes if (TinyIRReceiverControl.IRRawData.UBytes[0] != (uint8_t) (~TinyIRReceiverControl.IRRawData.UBytes[1])) { TinyIRReceiverControl.Flags |= IRDATA_FLAGS_PARITY_FAILED; DEBUG_PRINT(F("Parity check for command failed. Command=")); DEBUG_PRINT(TinyIRReceiverControl.IRRawData.UBytes[0], HEX); DEBUG_PRINT(F(" parity=")); DEBUG_PRINTLN(TinyIRReceiverControl.IRRawData.UBytes[1], HEX); #endif } #endif /* * Call user provided callback here * The parameter size is dependent of the code variant used in order to save program memory. * We have 6 cases: 0, 8 bit or 16 bit address, each with 8 or 16 bit command */ #if !defined(ARDUINO_ARCH_MBED) && !defined(ESP32) // no Serial etc. possible in callback for RTOS based cores like ESP, even when interrupts are enabled interrupts(); // enable interrupts, so delay() etc. works in callback #endif TinyIRReceiverData.justWritten = true; TinyIRReceiverData.Flags = TinyIRReceiverControl.Flags; #if (TINY_RECEIVER_ADDRESS_BITS > 0) # if TINY_RECEIVER_ADDRESS_HAS_8_BIT_PARITY // Here we have 8 bit address TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UBytes[0]; # else // Here we have 16 bit address TinyIRReceiverData.Address = TinyIRReceiverControl.IRRawData.UWord.LowWord; # endif # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY // Here we have 8 bit command TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[2]; # else // Here we have 16 bit command TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord.HighWord; # endif #else // Here we have NO address # if TINY_RECEIVER_COMMAND_HAS_8_BIT_PARITY // Here we have 8 bit command TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UBytes[0]; # else // Here we have 16 bit command TinyIRReceiverData.Command = TinyIRReceiverControl.IRRawData.UWord; # endif #endif #if defined(USE_CALLBACK_FOR_TINY_RECEIVER) handleReceivedTinyIRData(); #endif } else { // not finished yet tState = IR_RECEIVER_STATE_WAITING_FOR_DATA_MARK; } } else { // Wrong length -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } else { // error wrong state for the received level, e.g. if we missed one change interrupt -> reset state tState = IR_RECEIVER_STATE_WAITING_FOR_START_MARK; } } TinyIRReceiverControl.IRReceiverState = tState; #ifdef _IR_MEASURE_TIMING digitalWriteFast(_IR_TIMING_TEST_PIN, LOW); // 2 clock cycles #endif } bool isTinyIRReceiverIdle() { return (TinyIRReceiverControl.IRReceiverState == IR_RECEIVER_STATE_WAITING_FOR_START_MARK); } bool isTinyReceiverIdle() { return isTinyIRReceiverIdle(); } /* * Function to be used as drop in for IrReceiver.decode() */ bool TinyIRReceiverDecode() { bool tJustWritten = TinyIRReceiverData.justWritten; if (tJustWritten) { TinyIRReceiverData.justWritten = false; } return tJustWritten; } bool TinyReceiverDecode() { return TinyIRReceiverDecode(); } /* * Checks if IR_RECEIVE_PIN is connected and high * @return true, if IR Receiver is attached */ bool isIRReceiverAttachedForTinyIRReceiver() { pinModeFast(IR_RECEIVE_PIN, OUTPUT); digitalWriteFast(IR_RECEIVE_PIN, LOW); // discharge pin capacity pinModeFast(IR_RECEIVE_PIN, INPUT); return digitalRead(IR_RECEIVE_PIN); // use slow digitalRead here, since the pin capacity is not fully charged again if we use digitalReadFast. } bool isIRReceiverAttachedForTinyReceiver() { return isIRReceiverAttachedForTinyIRReceiver(); } /** * Sets IR_RECEIVE_PIN mode to INPUT, and if IR_FEEDBACK_LED_PIN is defined, sets feedback LED output mode. * Then call enablePCIInterruptForTinyIRReceiver() */ bool initPCIInterruptForTinyIRReceiver() { pinModeFast(IR_RECEIVE_PIN, INPUT); #if defined(LED_RECEIVE_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # endif #endif return enablePCIInterruptForTinyReceiver(); } bool initPCIInterruptForTinyReceiver() { return initPCIInterruptForTinyIRReceiver(); } void printTinyIRReceiverResultMinimal(Print *aSerial) { // Print only very short output, since we are in an interrupt context and do not want to miss the next interrupts of the repeats coming soon #if defined(USE_FAST_PROTOCOL) aSerial->print(F("C=0x")); #else aSerial->print(F("A=0x")); aSerial->print(TinyIRReceiverData.Address, HEX); aSerial->print(F(" C=0x")); #endif aSerial->print(TinyIRReceiverData.Command, HEX); if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) { aSerial->print(F(" R")); } #if !defined(DISABLE_PARITY_CHECKS) if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) { aSerial->print(F(" P")); } #endif aSerial->println(); } void printTinyReceiverResultMinimal(Print *aSerial) { printTinyIRReceiverResultMinimal(aSerial); } #if !defined(STR_HELPER) && !defined(STR) // Helper macro for getting a macro definition as string #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) #endif /************************************************** * Pin to interrupt mapping for different platforms **************************************************/ #if defined(__AVR_ATtiny816__) || defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) #define USE_ATTACH_INTERRUPT_DIRECT #elif !defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT) // Default for all NON AVR platforms #define USE_ATTACH_INTERRUPT #else # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) #define USE_PCIE # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(ARDUINO_AVR_DIGISPARKPRO) # if (IR_RECEIVE_PIN == 3) #define USE_INT0 # elif (IR_RECEIVE_PIN == 9) #define USE_INT1 # else # error "IR_RECEIVE_PIN must be 9 or 3." # endif // if (IR_RECEIVE_PIN == 9) # else // defined(ARDUINO_AVR_DIGISPARKPRO) # if (IR_RECEIVE_PIN == 14) #define USE_INT0 # elif (IR_RECEIVE_PIN == 3) #define USE_INT1 # else # error "IR_RECEIVE_PIN must be 14 or 3." # endif // if (IR_RECEIVE_PIN == 14) # endif # elif (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)) # if (IR_RECEIVE_PIN == 21) #define USE_INT0 # elif (IR_RECEIVE_PIN == 20) #define USE_INT1 # else #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now." #define USE_ATTACH_INTERRUPT # endif # else // defined(__AVR_ATtiny25__) /* * ATmegas + ATtiny88 here */ # if (IR_RECEIVE_PIN == 2) #define USE_INT0 # elif (IR_RECEIVE_PIN == 3) #define USE_INT1 # elif IR_RECEIVE_PIN == 4 || IR_RECEIVE_PIN == 5 || IR_RECEIVE_PIN == 6 || IR_RECEIVE_PIN == 7 //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 20 to 23 for port PD4 to PD7 (Arduino pin 4 to 7) #define USE_PCINT2 # elif IR_RECEIVE_PIN == 8 || IR_RECEIVE_PIN == 9 || IR_RECEIVE_PIN == 10 || IR_RECEIVE_PIN == 11 || IR_RECEIVE_PIN == 12 || IR_RECEIVE_PIN == 13 //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 0 to 5 for port PB0 to PB5 (Arduino pin 8 to 13) #define USE_PCINT0 # elif IR_RECEIVE_PIN == A0 || IR_RECEIVE_PIN == A1 || IR_RECEIVE_PIN == A2 || IR_RECEIVE_PIN == A3 || IR_RECEIVE_PIN == A4 || IR_RECEIVE_PIN == A5 //ATmega328 (Uno, Nano ) etc. Enable pin change interrupt 8 to 13 for port PC0 to PC5 (Arduino pin A0 to A5) #define USE_PCINT1 # else #warning "No pin mapping for IR_RECEIVE_PIN to interrupt found -> attachInterrupt() is used now." #define USE_ATTACH_INTERRUPT # endif // if (IR_RECEIVE_PIN == 2) # endif // defined(__AVR_ATtiny25__) #endif // ! defined(__AVR__) || defined(TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT) /** * Initializes hardware interrupt generation according to IR_RECEIVE_PIN or use attachInterrupt() function. * @return true if interrupt was successfully enabled */ bool enablePCIInterruptForTinyIRReceiver() { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT) # if defined(USE_ATTACH_INTERRUPT) # if defined(NOT_AN_INTERRUPT) // check if IDE has defined the check of digitalPinToInterrupt if(digitalPinToInterrupt(IR_RECEIVE_PIN) == NOT_AN_INTERRUPT){ return false; } # endif // costs 112 bytes program memory + 4 bytes RAM # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here :-( # else attachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN), IRPinChangeInterruptHandler, CHANGE); // CHANGE can be an enum :-( # endif # else // USE_ATTACH_INTERRUPT_DIRECT here, only defined for ATtinies *16, see above // 2.2 us more than version configured with macros and not compatible attachInterrupt(IR_RECEIVE_PIN, IRPinChangeInterruptHandler, CHANGE); // no extra pin mapping here # endif # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT) Serial.println(F("Use attachInterrupt for pin=" STR(IR_RECEIVE_PIN))); # endif #else # if defined(LOCAL_DEBUG_ATTACH_INTERRUPT) Serial.println(F("Use hardware/static interrupt for pin=" STR(IR_RECEIVE_PIN))); # endif # if defined(USE_INT0) // interrupt on any logical change EICRA |= _BV(ISC00); // clear interrupt bit EIFR |= 1 << INTF0; // enable interrupt on next change EIMSK |= 1 << INT0; # elif defined(USE_INT1) EICRA |= _BV(ISC10); // clear interrupt bit EIFR |= 1 << INTF1; // enable interrupt on next change EIMSK |= 1 << INT1; # elif defined(USE_PCIE) // For ATtiny85 etc. // use PinChangeInterrupt no INT0 for pin PB2 PCMSK = _BV(IR_RECEIVE_PIN); // clear interrupt bit GIFR |= 1 << PCIF; // enable interrupt on next change GIMSK |= 1 << PCIE; # elif defined(USE_PCINT0) PCICR |= _BV(PCIE0); PCMSK0 = digitalPinToBitMask(IR_RECEIVE_PIN); # elif defined(USE_PCINT1) PCICR |= _BV(PCIE1); PCMSK1 = digitalPinToBitMask(IR_RECEIVE_PIN); # elif defined(USE_PCINT2) PCICR |= _BV(PCIE2); PCMSK2 = digitalPinToBitMask(IR_RECEIVE_PIN); # else return false; # endif #endif // defined(USE_ATTACH_INTERRUPT) return true; } bool enablePCIInterruptForTinyReceiver() { return enablePCIInterruptForTinyIRReceiver(); } void disablePCIInterruptForTinyIRReceiver() { #if defined(_IR_MEASURE_TIMING) && defined(_IR_TIMING_TEST_PIN) pinModeFast(_IR_TIMING_TEST_PIN, OUTPUT); #endif #if defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT) # if defined(USE_ATTACH_INTERRUPT) detachInterrupt(digitalPinToInterrupt(IR_RECEIVE_PIN)); # else detachInterrupt(IR_RECEIVE_PIN); # endif #else # if defined(USE_INT0) // clear interrupt bit EIFR |= 1 << INTF0; // disable interrupt on next change EIMSK &= ~(1 << INT0); # elif defined(USE_INT1) // clear interrupt bit EIFR |= 1 << INTF1; // disable interrupt on next change EIMSK &= ~(1 << INT1); # elif defined(USE_PCIE) // For ATtiny85 etc. // clear interrupt bit GIFR |= 1 << PCIF; // disable interrupt on next change GIMSK &= ~(1 << PCIE); # elif defined(USE_PCINT0) PCICR &= ~(_BV(PCIE0)); # elif defined(USE_PCINT1) PCICR &= ~(_BV(PCIE1)); # elif defined(USE_PCINT2) PCICR &= ~(_BV(PCIE2)); # endif #endif // defined(USE_ATTACH_INTERRUPT) } void disablePCIInterruptForTinyReceiver() { disablePCIInterruptForTinyIRReceiver(); } /* * Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores. * The default value of TINY_RECEIVER_USE_ARDUINO_ATTACH_INTERRUPT is set in TinyIRReceiver.h */ #if !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)) # if defined(USE_INT0) ISR(INT0_vect) # elif defined(USE_INT1) ISR(INT1_vect) # elif defined(USE_PCIE) // For ATtiny85 etc. // on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect ISR(PCINT0_vect) # elif defined(USE_PCINT0) ISR(PCINT0_vect) # elif defined(USE_PCINT1) ISR(PCINT1_vect) # elif defined(USE_PCINT2) ISR(PCINT2_vect) # else void dummyFunctionToAvoidCompilerErrors() # endif { IRPinChangeInterruptHandler(); } #endif // !(defined(USE_ATTACH_INTERRUPT) || defined(USE_ATTACH_INTERRUPT_DIRECT)) /** @}*/ #if defined(LOCAL_DEBUG_ATTACH_INTERRUPT) #undef LOCAL_DEBUG_ATTACH_INTERRUPT #endif #include "LocalDebugLevelEnd.h" #endif // _TINY_IR_RECEIVER_HPP ================================================ FILE: src/TinyIRSender.hpp ================================================ /* * TinyIRSender.hpp * * Sends IR protocol data of NEC and FAST protocol using bit banging. * NEC is the protocol of most cheap remote controls for Arduino. * * The FAST protocol is a proprietary modified JVC protocol without address, with parity and with a shorter header. * FAST Protocol characteristics: * - Bit timing is like NEC or JVC * - The header is shorter, 3156 vs. 12500 * - No address and 16 bit data, interpreted as 8 bit command and 8 bit inverted command, * leading to a fixed protocol length of (6 + (16 * 3) + 1) * 526 = 55 * 526 = 28930 microseconds or 29 ms. * - Repeats are sent as complete frames but in a 50 ms period / with a 21 ms distance. * * * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote. * This file is also part of IRMP https://github.com/IRMP-org/IRMP. * ************************************************************************************ * MIT License * * Copyright (c) 2022-2026 Armin Joachimsmeyer * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is furnished * to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * ************************************************************************************ */ #ifndef _TINY_IR_SENDER_HPP #define _TINY_IR_SENDER_HPP #include //#define ENABLE_NEC2_REPEATS // Instead of sending / receiving the NEC special repeat code, send / receive the original frame for repeat. //#define NO_LED_SEND_FEEDBACK_CODE // Disables the LED feedback code for receive. //#define IR_FEEDBACK_LED_PIN 12 // Use this, to disable use of LED_BUILTIN definition for IR_FEEDBACK_LED_PIN #include "TinyIR.h" // Defines protocol timings #include "digitalWriteFast.h" /** \addtogroup TinySender Minimal sender for NEC and FAST protocol * @{ */ #if !defined(IR_SEND_PIN) #warning "IR_SEND_PIN is not defined, so it is set to 3" #define IR_SEND_PIN 3 #endif #if !defined(NO_LED_SEND_FEEDBACK_CODE) #define LED_SEND_FEEDBACK_CODE // Resolve the double negative #endif /* * Generate 38 kHz IR signal by bit banging and using delayMicroseconds() and micros() */ void sendMark(uint8_t aSendPin, unsigned int aMarkMicros) { unsigned long tMicros = micros(); unsigned long tNextPeriodEnding = tMicros; #if defined(F_CPU) unsigned long tEndMicros = tMicros + (112 / (F_CPU / MICROS_IN_ONE_SECOND)) + aMarkMicros; // To compensate for call duration - 112 is an empirical value #else unsigned long tEndMicros = tMicros + aMarkMicros; #endif do { /* * Generate pulse */ noInterrupts(); // do not let interrupts extend the short on period digitalWriteFast(aSendPin, HIGH); delayMicroseconds(8); // 8 us for a 30 % duty cycle for 38 kHz digitalWriteFast(aSendPin, LOW); interrupts(); // Enable interrupts - to keep micros correct- for the longer off period 3.4 us until receive ISR is active (for 7 us + pop's) /* * PWM pause timing and end check * Minimal pause duration is 4.3 us */ tNextPeriodEnding += 26; // 26.3 us period for 38 kHz; 26 us -> 38.48 kHz do { tMicros = micros(); // we have only 4 us resolution for AVR @16MHz /* * Exit the forever loop if aMarkMicros has reached */ if (tMicros >= tEndMicros) { return; } } while (tMicros < tNextPeriodEnding); } while (true); } /* * Send NEC with 16 bit address and command, even if aCommand < 0x100 (I.E. ONKYO) * @param aAddress - The 16 bit address to send. * @param aCommand - The 16 bit command to send. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ void sendONKYO(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); #if !defined(NO_LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # endif #endif uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250 } else { // send header delayMicroseconds (NEC_HEADER_SPACE); LongUnion tData; tData.UWord.LowWord = aAddress; tData.UWord.HighWord = aCommand; // Send data for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { sendMark(aSendPin, NEC_BIT_MARK); // constant mark length if (tData.ULong & 1) { delayMicroseconds (NEC_ONE_SPACE); } else { delayMicroseconds (NEC_ZERO_SPACE); } tData.ULong >>= 1; // shift command for next bit } } // send stop bit sendMark(aSendPin, NEC_BIT_MARK); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { /* * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ auto tFrameDurationMillis = millis() - tStartOfFrameMillis; if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis); } } } #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # endif #endif } /* * Send NEC with 8 or 16 bit address or command depending on the values of aAddress and aCommand. * @param aAddress - If aAddress < 0x100 send 8 bit address and 8 bit inverted address, else send 16 bit address. * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ void sendNECMinimal(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { sendNEC(aSendPin, aAddress, aCommand, aNumberOfRepeats); // sendNECMinimal() is deprecated } void sendNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # endif #endif uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250 } else { // send header delayMicroseconds (NEC_HEADER_SPACE); LongUnion tData; /* * The compiler is intelligent and removes the code for "(aAddress > 0xFF)" if we are called with an uint8_t address :-). * Using an uint16_t address requires additional 28 bytes program memory. */ if (aAddress > 0xFF) { tData.UWord.LowWord = aAddress; } else { tData.UByte.LowByte = aAddress; // LSB first tData.UByte.MidLowByte = ~aAddress; } if (aCommand > 0xFF) { tData.UWord.HighWord = aCommand; } else { tData.UByte.MidHighByte = aCommand; tData.UByte.HighByte = ~aCommand; // LSB first } // Send data for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { sendMark(aSendPin, NEC_BIT_MARK); // constant mark length if (tData.ULong & 1) { delayMicroseconds (NEC_ONE_SPACE); } else { delayMicroseconds (NEC_ZERO_SPACE); } tData.ULong >>= 1; // shift command for next bit } } // send stop bit sendMark(aSendPin, NEC_BIT_MARK); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { /* * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ auto tFrameDurationMillis = millis() - tStartOfFrameMillis; if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis); } } } #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # endif #endif } /* * Send Extended NEC with a forced 16 bit address and 8 or 16 bit command depending on the value of aCommand. * @param aAddress - Send 16 bit address. * @param aCommand - If aCommand < 0x100 send 8 bit command and 8 bit inverted command, else send 16 bit command. * @param aNumberOfRepeats - Number of repeats send at a period of 110 ms. * @param aSendNEC2Repeats - Instead of sending the NEC special repeat code, send the original frame for repeat. */ void sendExtendedNEC(uint8_t aSendPin, uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendNEC2Repeats) { pinModeFast(aSendPin, OUTPUT); #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # endif #endif uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); sendMark(aSendPin, NEC_HEADER_MARK); if ((!aSendNEC2Repeats) && (tNumberOfCommands < aNumberOfRepeats + 1)) { // send the NEC special repeat delayMicroseconds (NEC_REPEAT_HEADER_SPACE); // - 2250 } else { // send header delayMicroseconds (NEC_HEADER_SPACE); LongUnion tData; tData.UWord.LowWord = aAddress; if (aCommand > 0xFF) { tData.UWord.HighWord = aCommand; } else { tData.UByte.MidHighByte = aCommand; tData.UByte.HighByte = ~aCommand; // LSB first } // Send data for (uint_fast8_t i = 0; i < NEC_BITS; ++i) { sendMark(aSendPin, NEC_BIT_MARK); // constant mark length if (tData.ULong & 1) { delayMicroseconds (NEC_ONE_SPACE); } else { delayMicroseconds (NEC_ZERO_SPACE); } tData.ULong >>= 1; // shift command for next bit } } // send stop bit sendMark(aSendPin, NEC_BIT_MARK); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { /* * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ auto tFrameDurationMillis = millis() - tStartOfFrameMillis; if (NEC_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { delay(NEC_REPEAT_PERIOD / 1000 - tFrameDurationMillis); } } } #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # endif #endif } /* * LSB first, send header, command, inverted command and stop bit */ void sendFast8BitAndParity(uint8_t aSendPin, uint8_t aCommand, uint_fast8_t aNumberOfRepeats) { sendFAST(aSendPin, aCommand, aNumberOfRepeats); } /* * LSB first, send header, 16 bit command or 8 bit command, inverted command and stop bit */ void sendFAST(uint8_t aSendPin, uint16_t aCommand, uint_fast8_t aNumberOfRepeats) { pinModeFast(aSendPin, OUTPUT); #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # endif #endif uint_fast8_t tNumberOfCommands = aNumberOfRepeats + 1; while (tNumberOfCommands > 0) { unsigned long tStartOfFrameMillis = millis(); // send header sendMark(aSendPin, FAST_HEADER_MARK); delayMicroseconds(FAST_HEADER_SPACE); uint16_t tData; /* * The compiler is intelligent and removes the code for "(aCommand > 0xFF)" if we are called with an uint8_t command :-). * Using an uint16_t command requires additional 56 bytes program memory. */ if (aCommand > 0xFF) { tData = aCommand; } else { tData = aCommand | (((uint8_t) (~aCommand)) << 8); // LSB first } // Send data for (uint_fast8_t i = 0; i < FAST_BITS; ++i) { sendMark(aSendPin, FAST_BIT_MARK); // constant mark length if (tData & 1) { delayMicroseconds(FAST_ONE_SPACE); } else { delayMicroseconds(FAST_ZERO_SPACE); } tData >>= 1; // shift command for next bit } // send stop bit sendMark(aSendPin, FAST_BIT_MARK); tNumberOfCommands--; // skip last delay! if (tNumberOfCommands > 0) { /* * Check and fallback for wrong RepeatPeriodMillis parameter. I.e the repeat period must be greater than each frame duration. */ auto tFrameDurationMillis = millis() - tStartOfFrameMillis; if (FAST_REPEAT_PERIOD / 1000 > tFrameDurationMillis) { delay(FAST_REPEAT_PERIOD / 1000 - tFrameDurationMillis); } } } #if defined(LED_SEND_FEEDBACK_CODE) && defined(IR_FEEDBACK_LED_PIN) pinModeFast(IR_FEEDBACK_LED_PIN, OUTPUT); # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) digitalWriteFast(IR_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IR_FEEDBACK_LED_PIN, LOW); # endif #endif } /** @}*/ #endif // _TINY_IR_SENDER_HPP ================================================ FILE: src/digitalWriteFast.h ================================================ /* * digitalWriteFast.h * * Optimized digital functions for AVR microcontrollers * by Watterott electronic (www.watterott.com) * based on https://code.google.com/p/digitalwritefast * * The value of DigitalReadFast() is the content of the input register e.g. 0x04 for pin2 and NOT always 0 or 1. * * License: BSD 3-Clause License (https://opensource.org/licenses/BSD-3-Clause) */ #ifndef __digitalWriteFast_h_ #define __digitalWriteFast_h_ 1 //#define THROW_ERROR_IF_NOT_FAST // If activated, an error is thrown if pin is not a compile time constant void NonConstantsUsedForPinModeFast( void ) __attribute__ (( error("Parameter for pinModeFast() function is not constant") )); void NonConstantsUsedForDigitalWriteFast( void ) __attribute__ (( error("Parameter for digitalWriteFast() function is not constant") )); void NonConstantsUsedForDigitalToggleFast( void ) __attribute__ (( error("Parameter for digitalToggleFast() function is not constant") )); int NonConstantsUsedForDigitalReadFast( void ) __attribute__ (( error("Parameter for digitalReadFast() function is not constant") )); #if !defined(MEGATINYCORE) // megaTinyCore has it own digitalWriteFast function set, except digitalToggleFast(). //#define SANGUINO_PINOUT // define for Sanguino pinout // general macros/defines #if !defined(BIT_READ) # define BIT_READ(value, bit) ((value) & (1UL << (bit))) #endif #if !defined(BIT_SET) # define BIT_SET(value, bit) ((value) |= (1UL << (bit))) #endif #if !defined(BIT_CLEAR) # define BIT_CLEAR(value, bit) ((value) &= ~(1UL << (bit))) #endif #if !defined(BIT_WRITE) # define BIT_WRITE(value, bit, bitvalue) (bitvalue ? BIT_SET(value, bit) : BIT_CLEAR(value, bit)) #endif #include // declarations for the fallback to digitalWrite(), digitalRead() etc. // --- Arduino Mega and ATmega128x/256x based boards --- #if (defined(ARDUINO_AVR_MEGA) || \ defined(ARDUINO_AVR_MEGA1280) || \ defined(ARDUINO_AVR_MEGA2560) || \ defined(__AVR_ATmega1280__) || \ defined(__AVR_ATmega1281__) || \ defined(__AVR_ATmega2560__) || \ defined(__AVR_ATmega2561__)) #define __digitalPinToPortReg(P) \ (((P) >= 22 && (P) <= 29) ? &PORTA : \ ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PORTB : \ (((P) >= 30 && (P) <= 37) ? &PORTC : \ ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PORTD : \ ((((P) <= 3) || (P) == 5) ? &PORTE : \ (((P) >= 54 && (P) <= 61) ? &PORTF : \ ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PORTG : \ ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PORTH : \ (((P) == 14 || (P) == 15) ? &PORTJ : \ (((P) >= 62 && (P) <= 69) ? &PORTK : &PORTL)))))))))) #define __digitalPinToDDRReg(P) \ (((P) >= 22 && (P) <= 29) ? &DDRA : \ ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &DDRB : \ (((P) >= 30 && (P) <= 37) ? &DDRC : \ ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &DDRD : \ ((((P) <= 3) || (P) == 5) ? &DDRE : \ (((P) >= 54 && (P) <= 61) ? &DDRF : \ ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &DDRG : \ ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &DDRH : \ (((P) == 14 || (P) == 15) ? &DDRJ : \ (((P) >= 62 && (P) <= 69) ? &DDRK : &DDRL)))))))))) #define __digitalPinToPINReg(P) \ (((P) >= 22 && (P) <= 29) ? &PINA : \ ((((P) >= 10 && (P) <= 13) || ((P) >= 50 && (P) <= 53)) ? &PINB : \ (((P) >= 30 && (P) <= 37) ? &PINC : \ ((((P) >= 18 && (P) <= 21) || (P) == 38) ? &PIND : \ ((((P) <= 3) || (P) == 5) ? &PINE : \ (((P) >= 54 && (P) <= 61) ? &PINF : \ ((((P) >= 39 && (P) <= 41) || (P) == 4) ? &PING : \ ((((P) >= 6 && (P) <= 9) || (P) == 16 || (P) == 17) ? &PINH : \ (((P) == 14 || (P) == 15) ? &PINJ : \ (((P) >= 62 && (P) <= 69) ? &PINK : &PINL)))))))))) #define __digitalPinToBit(P) \ (((P) >= 7 && (P) <= 9) ? (P) - 3 : \ (((P) >= 10 && (P) <= 13) ? (P) - 6 : \ (((P) >= 22 && (P) <= 29) ? (P) - 22 : \ (((P) >= 30 && (P) <= 37) ? 37 - (P) : \ (((P) >= 39 && (P) <= 41) ? 41 - (P) : \ (((P) >= 42 && (P) <= 49) ? 49 - (P) : \ (((P) >= 50 && (P) <= 53) ? 53 - (P) : \ (((P) >= 54 && (P) <= 61) ? (P) - 54 : \ (((P) >= 62 && (P) <= 69) ? (P) - 62 : \ (((P) == 0 || (P) == 15 || (P) == 17 || (P) == 21) ? 0 : \ (((P) == 1 || (P) == 14 || (P) == 16 || (P) == 20) ? 1 : \ (((P) == 19) ? 2 : \ (((P) == 5 || (P) == 6 || (P) == 18) ? 3 : \ (((P) == 2) ? 4 : \ (((P) == 3 || (P) == 4) ? 5 : 7))))))))))))))) // --- Arduino MightyCore standard pinout --- #elif (defined(__AVR_ATmega1284P__) || \ defined(__AVR_ATmega1284__) || \ defined(__AVR_ATmega644P__) || \ defined(__AVR_ATmega644A__) || \ defined(__AVR_ATmega644__) || \ defined(__AVR_ATmega324PB__) || \ defined(__AVR_ATmega324PA__) || \ defined(__AVR_ATmega324P__) || \ defined(__AVR_ATmega324A__) || \ defined(__AVR_ATmega164P__) || \ defined(__AVR_ATmega164A__) || \ defined(__AVR_ATmega32__) || \ defined(__AVR_ATmega16__) || \ defined(__AVR_ATmega8535__)) && \ !defined(BOBUINO_PINOUT) #if defined(__AVR_ATmega324PB__) #define __digitalPinToPortReg(P) \ (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : (((P) >= 24 && (P) <= 31) ? &PORTA : &PORTE)))) #define __digitalPinToDDRReg(P) \ (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : (((P) >= 24 && (P) <= 31) ? &DDRA : &DDRE)))) #define __digitalPinToPINReg(P) \ (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : (((P) >= 24 && (P) <= 31) ? &PINA : &PINE)))) # if defined(SANGUINO_PINOUT) #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (7 - ((P) - 24)) : (P) - 32)))) # else //MightyCore Pinout #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (((P) >= 16 && (P) <= 23) ? (P) - 24 : (P) - 32)))) # endif #elif defined(PORTA) #define __digitalPinToPortReg(P) \ (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : (((P) >= 16 && (P) <= 23) ? &PORTC : &PORTA))) #define __digitalPinToDDRReg(P) \ (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : (((P) >= 16 && (P) <= 23) ? &DDRC : &DDRA))) #define __digitalPinToPINReg(P) \ (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : (((P) >= 16 && (P) <= 23) ? &PINC : &PINA))) # if defined(SANGUINO_PINOUT) #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24))))) # else //MightyCore Pinout #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24))) # endif #else #define __digitalPinToPortReg(P) \ (((P) <= 7) ? &PORTB : (((P) >= 8 && (P) <= 15) ? &PORTD : &PORTC)) #define __digitalPinToDDRReg(P) \ (((P) <= 7) ? &DDRB : (((P) >= 8 && (P) <= 15) ? &DDRD : &DDRC)) #define __digitalPinToPINReg(P) \ (((P) <= 7) ? &PINB : (((P) >= 8 && (P) <= 15) ? &PIND : &PINC)) # if defined(SANGUINO_PINOUT) #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (7 - ((P) - 24))))) # else //MightyCore Pinout #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 15) ? (P) - 8 : (((P) >= 16 && (P) <= 23) ? (P) - 16 : (P) - 24))) # endif #endif // --- Arduino Leonardo and ATmega16U4/32U4 based boards --- #elif (defined(ARDUINO_AVR_LEONARDO) || \ defined(__AVR_ATmega16U4__) || \ defined(__AVR_ATmega32U4__)) # if defined(TEENSYDUINO) #define __digitalPinToPortReg(P) \ ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PORTB : (((P) == 9 || (P) == 10) ? &PORTC : (((P) >= 16 && (P) <= 21)) ? &PORTF : &PORTD)) #define __digitalPinToDDRReg(P) \ ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &DDRB : (((P) == 9 || (P) == 10) ? &DDRC : (((P) >= 16 && (P) <= 21)) ? &DDRF : &DDRD)) #define __digitalPinToPINReg(P) \ ((((P) <= 4) || ((P) >= 13 && (P) <= 15)) ? &PINB : (((P) == 9 || (P) == 10) ? &PINC : (((P) >= 16 && (P) <= 21)) ? &PINF : &PIND)) #define __digitalPinToBit(P) \ (((P) <= 3) ? (P) : \ (((P) == 4 || (P) == 12) ? 7 : \ (((P) <= 8) ? (P) - 5 : \ (((P) <= 10) ? (P) - 3 : \ (((P) == 11) ? 6 : \ (((P) <= 15) ? (P) - 9 : \ (((P) <= 19) ? 23 - (P) : \ (((P) <= 21) ? 21 - (P) : (P) - 18)))))))) # else #define __digitalPinToPortReg(P) \ ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PORTD : (((P) == 5 || (P) == 13) ? &PORTC : (((P) >= 18 && (P) <= 23)) ? &PORTF : (((P) == 7) ? &PORTE : &PORTB))) #define __digitalPinToDDRReg(P) \ ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &DDRD : (((P) == 5 || (P) == 13) ? &DDRC : (((P) >= 18 && (P) <= 23)) ? &DDRF : (((P) == 7) ? &DDRE : &DDRB))) #define __digitalPinToPINReg(P) \ ((((P) <= 4) || (P) == 6 || (P) == 12 || (P) == 24 || (P) == 25 || (P) == 29) ? &PIND : (((P) == 5 || (P) == 13) ? &PINC : (((P) >= 18 && (P) <= 23)) ? &PINF : (((P) == 7) ? &PINE : &PINB))) #define __digitalPinToBit(P) \ (((P) >= 8 && (P) <= 11) ? (P) - 4 : \ (((P) >= 18 && (P) <= 21) ? 25 - (P) : \ (((P) == 0) ? 2 : (((P) == 1) ? 3 : (((P) == 2) ? 1 : (((P) == 3) ? 0 : (((P) == 4) ? 4 : (((P) == 6) ? 7 : (((P) == 13) ? 7 : \ (((P) == 14) ? 3 : (((P) == 15) ? 1 : (((P) == 16) ? 2 : (((P) == 17) ? 0 : (((P) == 22) ? 1 : (((P) == 23) ? 0 : \ (((P) == 24) ? 4 : (((P) == 25) ? 7 : (((P) == 26) ? 4 : (((P) == 27) ? 5 : 6 ))))))))))))))))))) # endif // --- Arduino Uno and ATmega168/328 based boards --- #elif (defined(ARDUINO_AVR_UNO) || \ defined(ARDUINO_AVR_DUEMILANOVE) || \ defined(__AVR_ATmega8__) || \ defined(__AVR_ATmega48__) || \ defined(__AVR_ATmega48P__) || \ defined(__AVR_ATmega48PB__) || \ defined(__AVR_ATmega88P__) || \ defined(__AVR_ATmega88PB__) || \ defined(__AVR_ATmega168__) || \ defined(__AVR_ATmega168PA__) || \ defined(__AVR_ATmega168PB__) || \ defined(__AVR_ATmega328__) || \ defined(__AVR_ATmega328P__) || \ defined(__AVR_ATmega328PB__)) #if defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88PB__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328PB__) #define __digitalPinToPortReg(P) \ (((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : (((P) >= 14 && (P) <= 19) ? &PORTC : &PORTE))) #define __digitalPinToDDRReg(P) \ (((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : (((P) >= 14 && (P) <= 19) ? &DDRC : &DDRE))) #define __digitalPinToPINReg(P) \ (((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : (((P) >= 14 && (P) <= 19) ? &PINC : &PINE))) #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (((P) >= 14 && (P) <= 19) ? (P) - 14 : (((P) >= 20 && (P) <= 21) ? (P) - 18 : (P) - 22)))) #else #define __digitalPinToPortReg(P) \ (((P) <= 7) ? &PORTD : (((P) >= 8 && (P) <= 13) ? &PORTB : &PORTC)) #define __digitalPinToDDRReg(P) \ (((P) <= 7) ? &DDRD : (((P) >= 8 && (P) <= 13) ? &DDRB : &DDRC)) #define __digitalPinToPINReg(P) \ (((P) <= 7) ? &PIND : (((P) >= 8 && (P) <= 13) ? &PINB : &PINC)) #define __digitalPinToBit(P) \ (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14)) #endif // --- Arduino Uno WiFi Rev 2, Nano Every --- #elif defined(__AVR_ATmega4809__) #define __digitalPinToPortReg(P) \ (((P) == 2 || (P) == 7 ) ? &VPORTA.OUT : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.OUT : ((P) == 4) ? &VPORTC.OUT : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.OUT : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.OUT : &VPORTF.OUT) #define __digitalPinToDDRReg(P) \ (((P) == 2 || (P) == 7 ) ? &VPORTA.DIR : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.DIR : ((P) == 4) ? &VPORTC.DIR : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.DIR : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.DIR : &VPORTF.DIR) #define __digitalPinToPINReg(P) \ (((P) == 2 || (P) == 7 ) ? &VPORTA.IN : ((P) == 5 || (P) == 9 || (P) == 10) ? &VPORTB.IN : ((P) == 4) ? &VPORTC.IN : (((P) >= 14 && (P) <= 17) || (P) == 20 || (P) == 21) ? &VPORTD.IN : ((P) == 8 || (P) == 11 || (P) == 12 || (P) == 13) ? &VPORTE.IN : &VPORTF.IN) #define __digitalPinToBit(P) \ (((P) == 2 || (P) == 9 || (P) == 11 || (P) == 17) ? 0 : ((P) == 7 || (P) == 10 || (P) == 12 || (P) == 16) ? 1 : ((P) == 5 || (P) == 13 || (P) == 15 || (P) == 18) ? 2 : ((P) == 9 || (P) == 14 || (P) == 19) ? 3 : ((P) == 6 || (P) == 20) ? 4 : ((P) == 3 || (P) == 21) ? 5 : 6 ) // TinyCore // https://raw.githubusercontent.com/xukangmin/TinyCore/master/avr/package/package_tinycore_index.json // https://docs.tinycore.dev/en/latest/ #elif defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) #define __digitalPinToPortReg(P) ((P) <= 5 ? &VPORTB.OUT : ((P) <= 9 ? &VPORTC.OUT : ((P) <= 16 ? &VPORTA.OUT : ((P) <= 18 ? &VPORTB.OUT : &VPORTC.OUT)))) #define __digitalPinToDDRReg(P) ((P) <= 5 ? &VPORTB.DIR : ((P) <= 9 ? &VPORTC.DIR : ((P) <= 16 ? &VPORTA.DIR : ((P) <= 18 ? &VPORTB.DIR : &VPORTC.DIR)))) #define __digitalPinToPINReg(P) ((P) <= 5 ? &VPORTB.IN : ((P) <= 9 ? &VPORTC.IN : ((P) <= 16 ? &VPORTA.IN : ((P) <= 18 ? &VPORTB.IN : &VPORTC.IN)))) #define __digitalPinToBit(P) ( (P) <= 3 ? (3 - P) : ((P) <= 5 ? (P) : ((P) <= 9 ? (P - 6) : ((P) <= 16 ? ((P) - 9) : ((P) <= 18 ? ((P) - 11) : ((P) - 15))))) ) #elif defined(__AVR_ATtiny1614__) #define __digitalPinToPortReg(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 7 ? &VPORTB.OUT : &VPORTA.OUT)) #define __digitalPinToDDRReg(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 7 ? &VPORTB.DIR : &VPORTA.DIR)) #define __digitalPinToPINReg(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 7 ? &VPORTB.IN : &VPORTA.IN)) #define __digitalPinToBit(P) ( (P) <= 3 ? (P + 4) : ((P) <= 7 ? (7 - P) : ((P) <= 10 ? (P - 7) : (P) - 11)) ) #elif defined(__AVR_ATtiny816__) // https://github.com/Arduino-IRremote/Arduino-IRremote/discussions/1029 #define __digitalPinToPortReg(P) ((P) <= 3 ? &VPORTA.OUT : ((P) <= 9 ? &VPORTB.OUT : ((P) <= 13 ? &VPORTC.OUT : ((P) <= 17 ? &VPORTA.OUT : &VPORTC.OUT)))) #define __digitalPinToDDRReg(P) ((P) <= 3 ? &VPORTA.DIR : ((P) <= 9 ? &VPORTB.DIR : ((P) <= 13 ? &VPORTC.DIR : ((P) <= 17 ? &VPORTA.DIR : &VPORTC.DIR)))) #define __digitalPinToPINReg(P) ((P) <= 3 ? &VPORTA.IN : ((P) <= 9 ? &VPORTB.IN : ((P) <= 13 ? &VPORTC.IN : ((P) <= 17 ? &VPORTA.IN : &VPORTC.IN)))) #define __digitalPinToBit(P) ( (P) <= 3 ? (P + 4) : ((P) <= 9 ? (9 - P) : ((P) <= 13 ? (P - 10) : ((P) <= 16 ? (P - 13) : ((P) - 17)))) ) // --- ATtinyX5 --- #elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // we have only PORTB #define __digitalPinToPortReg(P) (&PORTB) #define __digitalPinToDDRReg(P) (&DDRB) #define __digitalPinToPINReg(P) (&PINB) #define __digitalPinToBit(P) (((P) <= 7) ? (P) : (((P) >= 8 && (P) <= 13) ? (P) - 8 : (P) - 14)) // --- ATtiny88 --- #elif defined(__AVR_ATtiny88__) # if defined(ARDUINO_AVR_DIGISPARKPRO) #define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 14 ? &PORTB : ((P) <= 18 ? &PORTA : &PORTC))) #define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 14 ? &DDRB : ((P) <= 18 ? &DDRA : &DDRC))) #define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 14 ? &PINB : ((P) <= 18 ? &PINA : &PINC))) #define __digitalPinToBit(P) ( (P) <= 7 ? (P) : ((P) <= 13 ? ((P) - 8) : ((P) == 14 ? 7 : ((P) <= 16 ? ((P) - 14) : ((P) <= 18 ? ((P) - 17) : ((P) == 25 ? 7 : ((P) - 19)))))) ) # else #define __digitalPinToPortReg(P) ((P) <= 7 ? &PORTD : ((P) <= 15 ? &PORTB : ((P) <= 22 ? &PORTC : ((P) <= 26 ? &PORTA : &PORTC)))) #define __digitalPinToDDRReg(P) ((P) <= 7 ? &DDRD : ((P) <= 15 ? &DDRB : ((P) <= 22 ? &DDRC : ((P) <= 26 ? &DDRA : &DDRC)))) #define __digitalPinToPINReg(P) ((P) <= 7 ? &PIND : ((P) <= 15 ? &PINB : ((P) <= 22 ? &PINC : ((P) <= 26 ? &PINA : &PINC)))) #define __digitalPinToBit(P) ((P) <= 15 ? ((P) & 0x7) : ((P) == 16 ? (7) : ((P) <= 22 ? ((P) - 17) : ((P) == 27 ? (6) : ((P) - 23))))) # endif // --- ATtinyX4 + ATtinyX7 --- #elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) \ || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) || defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(ARDUINO_AVR_DIGISPARKPRO) || PIN_PA7 == 5 // Strange enumeration of pins on Digispark board and core library #define __digitalPinToPortReg(P) (((P) <= 4) ? &PORTB : &PORTA) #define __digitalPinToDDRReg(P) (((P) <= 4) ? &DDRB : &DDRA) #define __digitalPinToPINReg(P) (((P) <= 4) ? &PINB : &PINA) #define __digitalPinToBit(P) (((P) <= 2) ? (P) : (((P) == 3) ? 6 : (((P) == 4) ? 3 : (((P) == 5) ? 7 : (P) - 6 )))) # else // ATtinyX4: PORTA for 0 to 7, PORTB for 8 to 11 // ATtinyX7: PORTA for 0 to 7, PORTB for 8 to 15 #define __digitalPinToPortReg(P) (((P) <= 7) ? &PORTA : &PORTB) #define __digitalPinToDDRReg(P) (((P) <= 7) ? &DDRA : &DDRB) #define __digitalPinToPINReg(P) (((P) <= 7) ? &PINA : &PINB) # if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny441__) || defined(__AVR_ATtiny841__) // https://github.com/SpenceKonde/ATTinyCore/blob/v2.0.0-devThis-is-the-head-submit-PRs-against-this/avr/variants/tinyx41_cw/pins_arduino.h#L334 // Clockwise layout #define __digitalPinToBit(P) (((P) <= 7) ? (P) : ((P) == 11 ? (3) : 10 - (P))) # else #define __digitalPinToBit(P) (((P) <= 7) ? (P) : (P) - 8 ) # endif # endif #endif #if !defined(digitalWriteFast) # if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg) # if defined(THROW_ERROR_IF_NOT_FAST) #define digitalWriteFast(P, V) \ do { \ if (__builtin_constant_p(P)) { \ BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \ } else { \ NonConstantsUsedForDigitalWriteFast(); \ } \ } while (0) # else #define digitalWriteFast(P, V) \ do { \ if (__builtin_constant_p(P)) { \ BIT_WRITE(*__digitalPinToPortReg(P), __digitalPinToBit(P), (V)); \ } else { \ digitalWrite((P), (V)); \ } \ } while (0) # endif // defined(THROW_ERROR_IF_NOT_FAST) # else #define digitalWriteFast digitalWrite # endif #endif #if !defined(pinModeFast) # if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPortReg) # if defined(THROW_ERROR_IF_NOT_FAST) #define pinModeFast(P, V) \ do { \ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \ if (V == INPUT_PULLUP) {\ BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \ BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \ } else { \ BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \ } \ } else { \ NonConstantsUsedForPinModeFast(); \ } \ } while (0) # else #define pinModeFast(P, V) \ do { \ if (__builtin_constant_p(P) && __builtin_constant_p(V)) { \ if (V == INPUT_PULLUP) {\ BIT_CLEAR(*__digitalPinToDDRReg(P), __digitalPinToBit(P)); \ BIT_SET(*__digitalPinToPortReg(P), __digitalPinToBit(P)); \ } else { \ BIT_WRITE(*__digitalPinToDDRReg(P), __digitalPinToBit(P), (V)); \ } \ } else { \ pinMode((P), (V)); \ } \ } while (0) # endif // defined(THROW_ERROR_IF_NOT_FAST) # else #define pinModeFast pinMode # endif #endif // !defined(pinModeFast) #if !defined(digitalReadFast) # if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPINReg) # if defined(THROW_ERROR_IF_NOT_FAST) #define digitalReadFast(P) ( (int) __digitalReadFast((P)) ) // since we have return values, it is easier to implement it by ?: #define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : NonConstantsUsedForDigitalReadFast() ) # else #define digitalReadFast(P) ( (int) __digitalReadFast((P)) ) // since we have return values, it is easier to implement it by ?: #define __digitalReadFast(P ) ( (__builtin_constant_p(P) ) ? (( BIT_READ(*__digitalPinToPINReg(P), __digitalPinToBit(P))) ? HIGH:LOW ) : digitalRead((P)) ) # endif // defined(THROW_ERROR_IF_NOT_FAST) # else #define digitalReadFast digitalRead # endif #endif // !defined(digitalReadFast) #if !defined(digitalToggleFast) # if (defined(__AVR__) || defined(ARDUINO_ARCH_AVR)) && defined(__digitalPinToPINReg) # if defined(THROW_ERROR_IF_NOT_FAST) #define digitalToggleFast(P) \ do { \ if (__builtin_constant_p(P)) { \ BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \ } else { \ NonConstantsUsedForDigitalToggleFast(); \ } \ } while (0) # else #define digitalToggleFast(P) \ do { \ if (__builtin_constant_p(P)) { \ BIT_SET(*__digitalPinToPINReg(P), __digitalPinToBit(P)); \ } else { \ digitalWrite(P, ! digitalRead(P)); \ } \ } while (0) # endif // defined(THROW_ERROR_IF_NOT_FAST) # else #define digitalToggleFast(P) digitalWrite(P, ! digitalRead(P)) # endif #endif // !defined(digitalToggleFast) #endif // !defined(MEGATINYCORE) #endif //__digitalWriteFast_h_ ================================================ FILE: src/irmp.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmp.h * * Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_H_ #define _IRMP_H_ #if !defined(IRMP_USE_AS_LIB) # define IRMPCONFIG_STAGE1_H # include "irmpconfig.h" # undef IRMPCONFIG_STAGE1_H #endif #include "irmpsystem.h" #if !defined(IRMP_USE_AS_LIB) # define IRMPCONFIG_STAGE2_H # include "irmpconfig.h" # undef IRMPCONFIG_STAGE2_H #endif #if defined(ARDUINO) # include "irmpArduinoExt.h" #elif defined (__AVR_XMEGA__) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_PORT_PRE CONCAT(PORT, IRMP_PORT_LETTER) # define IRMP_DDR_PRE CONCAT(PORT, IRMP_PORT_LETTER) # define IRMP_PIN_PRE CONCAT(PORT, IRMP_PORT_LETTER) # define IRMP_PORT IRMP_PORT_PRE.OUT # define IRMP_DDR IRMP_DDR_PRE.DIR # define IRMP_PIN IRMP_PIN_PRE.IN # define IRMP_BIT IRMP_BIT_NUMBER # define input(x) ((x) & (1 << IRMP_BIT)) #elif defined (ATMEL_AVR) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_PORT CONCAT(PORT, IRMP_PORT_LETTER) # define IRMP_DDR CONCAT(DDR, IRMP_PORT_LETTER) # define IRMP_PIN CONCAT(PIN, IRMP_PORT_LETTER) # define IRMP_BIT IRMP_BIT_NUMBER # define input(x) ((x) & (1 << IRMP_BIT)) #elif defined (PIC_C18) || defined (PIC_CCS) || defined(PIC_XC32) # define input(x) (x) #elif defined (ARM_STM32) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_PORT CONCAT(GPIO, IRMP_PORT_LETTER) # if defined (ARM_STM32L1XX) # define IRMP_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRMP_PORT_LETTER) # elif defined (ARM_STM32F10X) # define IRMP_PORT_RCC CONCAT(RCC_APB2Periph_GPIO, IRMP_PORT_LETTER) # elif defined (ARM_STM32F30X) # define IRMP_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRMP_PORT_LETTER) # elif defined (ARM_STM32F4XX) # define IRMP_PORT_RCC CONCAT(RCC_AHB1Periph_GPIO, IRMP_PORT_LETTER) # endif # define IRMP_BIT CONCAT(GPIO_Pin_, IRMP_BIT_NUMBER) # define IRMP_PIN IRMP_PORT // for use with input(x) below # define input(x) (GPIO_ReadInputDataBit(x, IRMP_BIT)) # if !defined(USE_STDPERIPH_DRIVER) # warning The STM32 port of IRMP uses the ST standard peripheral drivers which are not enabled in your build configuration. # endif #elif defined (ARM_STM32_OPENCM3) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_PORT CONCAT(GPIO, IRMP_PORT_LETTER) # define IRMP_PORT_RCC CONCAT(RCC_GPIO, IRMP_PORT_LETTER) # define IRMP_BIT CONCAT(GPIO, IRMP_BIT_NUMBER) # define IRMP_PIN IRMP_PORT // for use with input(x) below # define input(x) (gpio_get(x, IRMP_BIT)) #elif defined (ARM_STM32_HAL) # define IRMP_BIT IRMP_BIT_NUMBER # define IRMP_PIN IRMP_BIT_NUMBER // for use with input(x) below # define input(x) HAL_GPIO_ReadPin(IRMP_PORT_LETTER, x) #elif defined (STELLARIS_ARM_CORTEX_M4) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_PORT_PERIPH CONCAT(SYSCTL_PERIPH_GPIO, IRMP_PORT_LETTER) # define IRMP_PORT_BASE CONCAT(GPIO_PORT, CONCAT(IRMP_PORT_LETTER, _BASE)) # define IRMP_PORT_PIN CONCAT(GPIO_PIN_, IRMP_BIT_NUMBER) # define IRMP_PIN IRMP_PORT_PIN # define input(x) ((uint8_t)(ROM_GPIOPinRead(IRMP_PORT_BASE, IRMP_PORT_PIN))) # define sei() IntMasterEnable() #elif defined(__SDCC_stm8) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRMP_GPIO_STRUCT CONCAT(GPIO, IRMP_PORT_LETTER) # define IRMP_BIT IRMP_BIT_NUMBER # define IRMP_PIN IRMP_GPIO_STRUCT->IDR # define input(x) ((x) & (1 << IRMP_BIT)) #elif defined (PICO_RP2040) # define IRMP_BIT IRMP_BIT_NUMBER # define IRMP_PIN IRMP_BIT_NUMBER // for use with input(x) below # define input(x) (gpio_get(x)) #elif defined (TEENSY_ARM_CORTEX_M4) # define input(x) ((uint8_t)(digitalReadFast(x))) #elif defined (__MBED__) # define IRMP_BIT gpioIRin # define input(x) (gpio_read (&x)) #elif defined(__xtensa__) # define IRMP_BIT IRMP_BIT_NUMBER # define input(x) GPIO_INPUT_GET(IRMP_BIT_NUMBER) #elif defined(_CHIBIOS_HAL_) # define input(x) palReadLine(x) #endif #if IRMP_USE_IDLE_CALL == 1 void irmp_idle(void); // the user has to provide an implementation of the irmp_idle() function and link it #endif #if IRMP_USE_COMPLETE_CALLBACK == 1 void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void)); #endif #if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 # undef IRMP_SUPPORT_MATSUSHITA_PROTOCOL # define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 #endif #if IRMP_32_BIT == 0 && IRMP_SUPPORT_MERLIN_PROTOCOL == 1 # undef IRMP_SUPPORT_MERLIN_PROTOCOL # warning MERLIN protocol disabled, IRMP_32_BIT=1 needed #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 # warning DENON protocol conflicts wih RUWIDO, please enable only one of both protocols # warning RUWIDO protocol disabled # undef IRMP_SUPPORT_RUWIDO_PROTOCOL # define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 && IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 # warning KASEIKYO protocol conflicts wih PANASONIC, please enable only one of both protocols # warning PANASONIC protocol disabled # undef IRMP_SUPPORT_PANASONIC_PROTOCOL # define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 && IRMP_SUPPORT_ACP24_PROTOCOL == 1 # warning DENON protocol conflicts wih ACP24, please enable only one of both protocols # warning ACP24 protocol disabled # undef IRMP_SUPPORT_ACP24_PROTOCOL # define IRMP_SUPPORT_ACP24_PROTOCOL 0 #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 && IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 # warning RC6 protocol conflicts wih ROOMBA, please enable only one of both protocols # warning ROOMBA protocol disabled # undef IRMP_SUPPORT_ROOMBA_PROTOCOL # define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 #endif #if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 && IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 # warning PANASONIC protocol conflicts wih MITSU_HEAVY, please enable only one of both protocols # warning MITSU_HEAVY protocol disabled # undef IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL # define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 && IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 # warning KASEIKYO protocol conflicts wih MITSU_HEAVY, please enable only one of both protocols # warning MITSU_HEAVY protocol disabled # undef IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL # define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1 # warning RC5 protocol conflicts wih ORTEK, please enable only one of both protocols # warning ORTEK protocol disabled # undef IRMP_SUPPORT_ORTEK_PROTOCOL # define IRMP_SUPPORT_ORTEK_PROTOCOL 0 #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_S100_PROTOCOL == 1 # warning RC5 protocol conflicts wih S100, please enable only one of both protocols # warning S100 protocol disabled # undef IRMP_SUPPORT_S100_PROTOCOL # define IRMP_SUPPORT_S100_PROTOCOL 0 #endif #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 && IRMP_SUPPORT_FAN_PROTOCOL == 1 # warning NUBERT protocol conflicts wih FAN, please enable only one of both protocols # warning FAN protocol disabled # undef IRMP_SUPPORT_FAN_PROTOCOL # define IRMP_SUPPORT_FAN_PROTOCOL 0 #endif #if IRMP_SUPPORT_FDC_PROTOCOL == 1 && IRMP_SUPPORT_ORTEK_PROTOCOL == 1 # warning FDC protocol conflicts wih ORTEK, please enable only one of both protocols # warning ORTEK protocol disabled # undef IRMP_SUPPORT_ORTEK_PROTOCOL # define IRMP_SUPPORT_ORTEK_PROTOCOL 0 #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 && IRMP_SUPPORT_NETBOX_PROTOCOL == 1 # warning ORTEK protocol conflicts wih NETBOX, please enable only one of both protocols # warning NETBOX protocol disabled # undef IRMP_SUPPORT_NETBOX_PROTOCOL # define IRMP_SUPPORT_NETBOX_PROTOCOL 0 #endif #if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 # warning GRUNDIG protocol conflicts wih RCII, please enable only one of both protocols # warning RCII protocol disabled # undef IRMP_SUPPORT_RCII_PROTOCOL # define IRMP_SUPPORT_RCII_PROTOCOL 0 #endif #if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 # warning NOKIA protocol conflicts wih RCII, please enable only one of both protocols # warning RCII protocol disabled # undef IRMP_SUPPORT_RCII_PROTOCOL # define IRMP_SUPPORT_RCII_PROTOCOL 0 #endif #if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000) # undef IRMP_SUPPORT_SIEMENS_PROTOCOL # define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 #endif #if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, RUWIDO protocol disabled (should be at least 15000) # undef IRMP_SUPPORT_RUWIDO_PROTOCOL # define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 #endif #if IRMP_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000) # undef IRMP_SUPPORT_RECS80_PROTOCOL # define IRMP_SUPPORT_RECS80_PROTOCOL 0 #endif #if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000) # undef IRMP_SUPPORT_RECS80EXT_PROTOCOL # define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 #endif #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 19000 # warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 19000) # undef IRMP_SUPPORT_LEGO_PROTOCOL # define IRMP_SUPPORT_LEGO_PROTOCOL 0 #endif #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 0 # warning SAMSUNG48 protocol needs also SAMSUNG protocol, SAMSUNG protocol enabled # undef IRMP_SUPPORT_SAMSUNG_PROTOCOL # define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 #endif #if IRMP_SUPPORT_JVC_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 # warning JVC protocol needs also NEC protocol, NEC protocol enabled # undef IRMP_SUPPORT_NEC_PROTOCOL # define IRMP_SUPPORT_NEC_PROTOCOL 1 #endif #if IRMP_SUPPORT_NEC16_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 # warning NEC16 protocol needs also NEC protocol, NEC protocol enabled # undef IRMP_SUPPORT_NEC_PROTOCOL # define IRMP_SUPPORT_NEC_PROTOCOL 1 #endif #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 # warning NEC42 protocol needs also NEC protocol, NEC protocol enabled # undef IRMP_SUPPORT_NEC_PROTOCOL # define IRMP_SUPPORT_NEC_PROTOCOL 1 #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 # warning LGAIR protocol needs also NEC protocol, NEC protocol enabled # undef IRMP_SUPPORT_NEC_PROTOCOL # define IRMP_SUPPORT_NEC_PROTOCOL 1 #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 && IRMP_SUPPORT_NEC_PROTOCOL == 0 # warning MELINERA protocol needs also NEC protocol, NEC protocol enabled # undef IRMP_SUPPORT_NEC_PROTOCOL # define IRMP_SUPPORT_NEC_PROTOCOL 1 #endif #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 && F_INTERRUPTS < 19000 # warning F_INTERRUPTS too low, RCMM protocol disabled (should be at least 19000) # undef IRMP_SUPPORT_RCMM_PROTOCOL # define IRMP_SUPPORT_RCMM_PROTOCOL 0 #endif #if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 && F_INTERRUPTS > 17000 && __SIZEOF_INT__ < 4 # warning F_INTERRUPTS too high, PENTAX protocol disabled (should be max 17000) # undef IRMP_SUPPORT_PENTAX_PROTOCOL # define IRMP_SUPPORT_PENTAX_PROTOCOL 0 #endif #if IRMP_SUPPORT_GREE_PROTOCOL == 1 && F_INTERRUPTS > 17000 && __SIZEOF_INT__ < 4 # warning F_INTERRUPTS too high, GREE protocol disabled (should be max 17000) # undef IRMP_SUPPORT_GREE_PROTOCOL # define IRMP_SUPPORT_GREE_PROTOCOL 0 #endif #if F_INTERRUPTS > 20000 # warning F_INTERRUPTS too high (should be not greater than 20000) #endif #include "irmpprotocols.h" #define IRMP_FLAG_NEW 0x00 #define IRMP_FLAG_REPETITION 0x01 #define IRMP_FLAG_RELEASE 0x02 // see IRMP_ENABLE_RELEASE_DETECTION in irmpconfig.h #ifdef __cplusplus extern "C" { #endif extern void irmp_init (void); #ifdef __cplusplus extern bool irmp_get_data (IRMP_DATA *); extern bool irmp_ISR (void); #else extern uint_fast8_t irmp_get_data (IRMP_DATA *); extern uint_fast8_t irmp_ISR (void); #endif #if IRMP_AUTODETECT_REPEATRATE extern volatile uint_fast8_t delta, min_delta, keep_same_key, timeout, upper_border; extern volatile uint_fast16_t tmp_delta; extern volatile uint32_t pass_on_delta_detection; #endif #if IRMP_PROTOCOL_NAMES == 1 extern const char * const irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM; #endif #if IRMP_USE_CALLBACK == 1 extern void irmp_set_callback_ptr (void (*cb)(uint_fast8_t)); #endif // IRMP_USE_CALLBACK == 1 #ifdef __cplusplus } #endif #endif /* _IRMP_H_ */ ================================================ FILE: src/irmp.hpp ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmp.hpp - infrared multi-protocol decoder, supports several remote control protocols * * Copyright (c) 2009-2019 Frank Meyer - frank(at)fli4l.de * 2020 Arduino porting by Armin Joachimsmeyer * * Supported AVR mikrocontrollers: * * ATtiny87, ATtiny167 * ATtiny45, ATtiny85 * ATtiny44, ATtiny84 * ATmega8, ATmega16, ATmega32 * ATmega162 * ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284, ATmega1284P * ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #include "irmp.h" #if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRMP_SUPPORT_NOKIA_PROTOCOL == 1 || IRMP_SUPPORT_IR60_PROTOCOL == 1 # define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 1 #else # define IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL 0 #endif #if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 || IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 # define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 1 #else # define IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL 0 #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 || \ IRMP_SUPPORT_RCII_PROTOCOL == 1 || \ IRMP_SUPPORT_S100_PROTOCOL == 1 || \ IRMP_SUPPORT_RC6_PROTOCOL == 1 || \ IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 || \ IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 || \ IRMP_SUPPORT_IR60_PROTOCOL == 1 || \ IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 || \ IRMP_SUPPORT_MERLIN_PROTOCOL == 1 || \ IRMP_SUPPORT_ORTEK_PROTOCOL == 1 # define IRMP_SUPPORT_MANCHESTER 1 #else # define IRMP_SUPPORT_MANCHESTER 0 #endif #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 # define IRMP_SUPPORT_SERIAL 1 #else # define IRMP_SUPPORT_SERIAL 0 #endif #define IRMP_KEY_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * 150.0e-3 + 0.5) // autodetect key repetition within 150 msec #define MIN_TOLERANCE_00 1.0 // -0% #define MAX_TOLERANCE_00 1.0 // +0% #define MIN_TOLERANCE_02 0.98 // -2% #define MAX_TOLERANCE_02 1.02 // +2% #define MIN_TOLERANCE_03 0.97 // -3% #define MAX_TOLERANCE_03 1.03 // +3% #define MIN_TOLERANCE_05 0.95 // -5% #define MAX_TOLERANCE_05 1.05 // +5% #define MIN_TOLERANCE_10 0.9 // -10% #define MAX_TOLERANCE_10 1.1 // +10% #define MIN_TOLERANCE_15 0.85 // -15% #define MAX_TOLERANCE_15 1.15 // +15% #define MIN_TOLERANCE_20 0.8 // -20% #define MAX_TOLERANCE_20 1.2 // +20% #define MIN_TOLERANCE_25 0.75 // -25% #define MAX_TOLERANCE_25 1.25 // +25% #define MIN_TOLERANCE_30 0.7 // -30% #define MAX_TOLERANCE_30 1.3 // +30% #define MIN_TOLERANCE_40 0.6 // -40% #define MAX_TOLERANCE_40 1.4 // +40% #define MIN_TOLERANCE_50 0.5 // -50% #define MAX_TOLERANCE_50 1.5 // +50% #define MIN_TOLERANCE_60 0.4 // -60% #define MAX_TOLERANCE_60 1.6 // +60% #define MIN_TOLERANCE_70 0.3 // -70% #define MAX_TOLERANCE_70 1.7 // +70% #define SIRCS_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SIRCS_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIRCS_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #if IRMP_SUPPORT_NETBOX_PROTOCOL // only 5% to avoid conflict with NETBOX: # define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) #else // only 5% + 1 to avoid conflict with RC6: # define SIRCS_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #endif #define SIRCS_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SIRCS_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIRCS_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SIRCS_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIRCS_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SIRCS_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define NEC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define NEC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define NEC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define NEC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define NEC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define NEC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define NEC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) // autodetect nec repetition frame within 50 msec: // NEC seems to send the first repetition frame after 40ms, further repetition frames after 100 ms #if 0 #define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) #else #define NEC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) #endif #define MELINERA_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MELINERA_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define MELINERA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MELINERA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define MELINERA_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MELINERA_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define MELINERA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MELINERA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNG_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SAMSUNG_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SAMSUNG_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SAMSUNG_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SAMSUNG_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNG_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNG_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNG_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNG_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNG_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNGAH_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SAMSUNGAH_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SAMSUNGAH_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define SAMSUNGAH_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SAMSUNGAH_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNGAH_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNGAH_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNGAH_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define SAMSUNGAH_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define SAMSUNGAH_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SAMSUNGAH_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define MATSUSHITA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define MATSUSHITA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define MATSUSHITA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define MATSUSHITA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define MATSUSHITA_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define MATSUSHITA_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define MATSUSHITA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define MATSUSHITA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define MATSUSHITA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define MATSUSHITA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define KASEIKYO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define KASEIKYO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define KASEIKYO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define KASEIKYO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define KASEIKYO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define KASEIKYO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define KASEIKYO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define KASEIKYO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define KASEIKYO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define KASEIKYO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define MITSU_HEAVY_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define MITSU_HEAVY_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define MITSU_HEAVY_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define MITSU_HEAVY_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define MITSU_HEAVY_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define MITSU_HEAVY_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define MITSU_HEAVY_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define MITSU_HEAVY_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define PANASONIC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define PANASONIC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define PANASONIC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define PANASONIC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define PANASONIC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define PANASONIC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define PANASONIC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PANASONIC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define PANASONIC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PANASONIC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define VINCENT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define VINCENT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define VINCENT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define VINCENT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define VINCENT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define VINCENT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define VINCENT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define VINCENT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define VINCENT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define VINCENT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * VINCENT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RECS80_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define RECS80_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RECS80_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RECS80_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define RECS80_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RECS80_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RECS80_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #if (0) // IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with RC5, so keep tolerance for RC5 minimal here: // start pause is well separated, so overlap in start pulse does not disturb, but reducing tolerance leads to worse RC5 recognition #define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #else #define RC5_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC5_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #endif #define RC5_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC5_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC5_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RCII_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCII_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCII_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCII_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCII_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCII_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_START_BIT2_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCII_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RCII_BIT_LEN ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME)) #define RCII_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCII_BIT_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 // BOSE conflicts with S100, so keep tolerance for S100 minimal here: #define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #else #define S100_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define S100_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #endif #define S100_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define S100_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * S100_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define DENON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define DENON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define DENON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define DENON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) // RUWIDO (see t-home-mediareceiver-15kHz.txt) conflicts here with DENON #define DENON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define DENON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define DENON_AUTO_REPETITION_PAUSE_LEN ((uint_fast16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define THOMSON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define THOMSON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define THOMSON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define THOMSON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define THOMSON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define THOMSON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RC6_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC6_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RC6_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC6_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RC6_TOGGLE_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC6_TOGGLE_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_TOGGLE_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RC6_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC6_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_60 + 0.5) + 1) // pulses: 300 - 800 #define RC6_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RC6_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RC6_BIT_TIME * MAX_TOLERANCE_20 + 0.5) + 1) // pauses: 300 - 600 #define RECS80EXT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define RECS80EXT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RECS80EXT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80EXT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RECS80EXT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define RECS80EXT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RECS80EXT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80EXT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RECS80EXT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RECS80EXT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define NUBERT_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NUBERT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NUBERT_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NUBERT_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NUBERT_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NUBERT_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NUBERT_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define FAN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FAN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SPEAKER_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define SPEAKER_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX ((PAUSE_LEN)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) // value must be below IRMP_TIMEOUT #define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT4_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_R_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_R_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define IR60_TIMEOUT_LEN ((uint_fast8_t)(F_INTERRUPTS * IR60_TIMEOUT_TIME * 0.5)) #define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define GRUNDIG_NOKIA_IR60_BIT_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define GRUNDIG_NOKIA_IR60_BIT_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) + 1) #define GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 0) #define SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) #define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) #define SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 1) #define SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define FDC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) // 5%: avoid conflict with NETBOX #define FDC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5)) #define FDC_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define FDC_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5)) #define FDC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define FDC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_PULSE_TIME * MAX_TOLERANCE_50 + 0.5) + 1) #define FDC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define FDC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #if 0 #define FDC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) // could be negative: 255 #else #define FDC_0_PAUSE_LEN_MIN (1) // simply use 1 #endif #define FDC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RCCAR_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RCCAR_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RCCAR_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RCCAR_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RCCAR_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define RCCAR_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RCCAR_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RCCAR_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME * MAX_TOLERANCE_25 + 0.5) + 1) #define RCCAR_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MIN_TOLERANCE_25 + 0.5) - 1) #define RCCAR_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define JVC_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define JVC_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define JVC_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MIN_TOLERANCE_40 + 0.5) - 1) // HACK! #define JVC_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (JVC_FRAME_REPEAT_PAUSE_TIME - IRMP_TIMEOUT_TIME) * MAX_TOLERANCE_70 + 0.5) - 1) // HACK! #define JVC_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define JVC_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define JVC_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define JVC_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define JVC_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define JVC_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) // autodetect JVC repetition frame within 50 msec: #define JVC_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) #define NIKON_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_START_BIT_PAUSE_LEN_MIN ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_START_BIT_PAUSE_LEN_MAX ((uint_fast16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_REPEAT_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_REPEAT_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define NIKON_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define NIKON_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) #define KATHREIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define KATHREIN_SYNC_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define KATHREIN_SYNC_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * KATHREIN_SYNC_BIT_PAUSE_LEN_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define NETBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define NETBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define NETBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define NETBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * NETBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define NETBOX_PULSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME)) #define NETBOX_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME)) #define NETBOX_PULSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PULSE_TIME / 4)) #define NETBOX_PAUSE_REST_LEN ((uint_fast8_t)(F_INTERRUPTS * NETBOX_PAUSE_TIME / 4)) #define LEGO_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define LEGO_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define LEGO_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define LEGO_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define LEGO_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define LEGO_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_PULSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define LEGO_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MIN_TOLERANCE_25 + 0.5) - 1) #define LEGO_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME * MAX_TOLERANCE_40 + 0.5) + 1) #define LEGO_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MIN_TOLERANCE_40 + 0.5) - 1) #define LEGO_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define IRMP16_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define IRMP16_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define IRMP16_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define IRMP16_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define IRMP16_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define IRMP16_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define IRMP16_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define IRMP16_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define IRMP16_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define IRMP16_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define GREE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define GREE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define GREE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define GREE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define GREE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define GREE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define GREE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define GREE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define GREE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define GREE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * GREE_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define BOSE_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define BOSE_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define BOSE_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define BOSE_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define BOSE_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define BOSE_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define BOSE_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define BOSE_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define BOSE_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define BOSE_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define BOSE_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * 100.0e-3 * MAX_TOLERANCE_20 + 0.5) #define A1TVBOX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define A1TVBOX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define A1TVBOX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define A1TVBOX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_00 + 0.5) + 1) #define A1TVBOX_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define A1TVBOX_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define A1TVBOX_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MIN_TOLERANCE_00 + 0.5) - 0) #define A1TVBOX_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define MERLIN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define MERLIN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define MERLIN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define MERLIN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define MERLIN_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MERLIN_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define MERLIN_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define MERLIN_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * MERLIN_BIT_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define ORTEK_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ORTEK_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define ORTEK_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ORTEK_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define ORTEK_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ORTEK_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define ORTEK_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ORTEK_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ORTEK_BIT_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define TELEFUNKEN_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define TELEFUNKEN_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define TELEFUNKEN_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MIN_TOLERANCE_10 + 0.5) - 1) #define TELEFUNKEN_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * (TELEFUNKEN_START_BIT_PAUSE_TIME) * MAX_TOLERANCE_10 + 0.5) - 1) #define TELEFUNKEN_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define TELEFUNKEN_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define TELEFUNKEN_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define TELEFUNKEN_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define TELEFUNKEN_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define TELEFUNKEN_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) // autodetect TELEFUNKEN repetition frame within 50 msec: // #define TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) #define ROOMBA_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ROOMBA_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define ROOMBA_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define ROOMBA_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define ROOMBA_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME + 0.5)) #define ROOMBA_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define ROOMBA_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define ROOMBA_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define ROOMBA_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define ROOMBA_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME)) #define ROOMBA_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define ROOMBA_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define ROOMBA_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define ROOMBA_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define RCMM32_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_BIT_00_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_BIT_00_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_00_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_BIT_01_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_BIT_01_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_01_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_BIT_10_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_BIT_10_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_10_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RCMM32_BIT_11_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RCMM32_BIT_11_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RCMM32_11_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define PENTAX_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define PENTAX_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define PENTAX_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define PENTAX_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define PENTAX_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME + 0.5)) #define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define PENTAX_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PENTAX_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define PENTAX_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME)) #define PENTAX_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PENTAX_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define PENTAX_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define PENTAX_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define ACP24_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) #define ACP24_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) #define ACP24_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) #define ACP24_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) #define ACP24_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) #define ACP24_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_PULSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) #define ACP24_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) #define ACP24_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) #define ACP24_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MIN_TOLERANCE_15 + 0.5) - 1) #define ACP24_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME * MAX_TOLERANCE_15 + 0.5) + 1) #define METZ_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define METZ_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define METZ_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define METZ_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define METZ_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_PULSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define METZ_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_PULSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define METZ_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_1_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define METZ_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_1_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define METZ_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * METZ_0_PAUSE_TIME * MIN_TOLERANCE_20 + 0.5) - 1) #define METZ_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * METZ_0_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) + 1) #define METZ_FRAME_REPEAT_PAUSE_LEN_MAX (uint_fast16_t)(F_INTERRUPTS * METZ_FRAME_REPEAT_PAUSE_TIME * MAX_TOLERANCE_20 + 0.5) #define RF_GEN24_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME + 0.5)) #define RF_GEN24_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RF_GEN24_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define RF_GEN24_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RF_GEN24_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_1_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define RF_GEN24_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME)) #define RF_GEN24_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PULSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RF_GEN24_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PULSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define RF_GEN24_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME * MIN_TOLERANCE_30 + 0.5) - 1) #define RF_GEN24_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_GEN24_0_PAUSE_TIME * MAX_TOLERANCE_30 + 0.5) + 1) #define RF_X10_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RF_X10_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RF_X10_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RF_X10_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RF_X10_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME + 0.5)) #define RF_X10_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_X10_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_X10_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_X10_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_X10_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME)) #define RF_X10_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_X10_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_X10_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_X10_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_X10_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_MEDION_START_BIT_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PULSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RF_MEDION_START_BIT_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PULSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RF_MEDION_START_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PAUSE_TIME * MIN_TOLERANCE_05 + 0.5) - 1) #define RF_MEDION_START_BIT_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_START_BIT_PAUSE_TIME * MAX_TOLERANCE_05 + 0.5) + 1) #define RF_MEDION_1_PAUSE_LEN_EXACT ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME + 0.5)) #define RF_MEDION_1_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_MEDION_1_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_MEDION_1_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_MEDION_1_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_1_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_MEDION_0_PAUSE_LEN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME)) #define RF_MEDION_0_PULSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PULSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_MEDION_0_PULSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PULSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define RF_MEDION_0_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME * MIN_TOLERANCE_10 + 0.5) - 1) #define RF_MEDION_0_PAUSE_LEN_MAX ((uint_fast8_t)(F_INTERRUPTS * RF_MEDION_0_PAUSE_TIME * MAX_TOLERANCE_10 + 0.5) + 1) #define AUTO_FRAME_REPETITION_LEN (uint_fast16_t)(F_INTERRUPTS * AUTO_FRAME_REPETITION_TIME + 0.5) // use uint_fast16_t! #define STOP_BIT_PAUSE_TIME_MIN 3000.0e-6 // minimum stop bit pause time: 3.0 msec #define STOP_BIT_PAUSE_LEN_MIN ((uint_fast8_t)(F_INTERRUPTS * STOP_BIT_PAUSE_TIME_MIN + 0.5) + 1) // minimum stop bit pause len // XC8 Compiler does not support variadic macros #if defined(ANALYZE) # define ANALYZE_PUTCHAR(a) { if (! silent) { putchar (a); } } # define ANALYZE_ONLY_NORMAL_PUTCHAR(a) { if (! silent && !verbose) { putchar (a); } } // # define ANALYZE_PRINTF(...) { if (verbose) { printf (__VA_ARGS__); } } # define ANALYZE_PRINTF1(a) { if (verbose) { printf (a); } } # define ANALYZE_PRINTF2(a,b) { if (verbose) { printf (a,b); } } # define ANALYZE_PRINTF3(a,b,c) { if (verbose) { printf (a,b,c); } } # define ANALYZE_PRINTF4(a,b,c,d) { if (verbose) { printf (a,b,c,d); } } # define ANALYZE_PRINTF5(a,b,c,d,e) { if (verbose) { printf (a,b,c,d,e); } } # define ANALYZE_PRINTF6(a,b,c,d,e,f) { if (verbose) { printf (a,b,c,d,e,f); } } # define ANALYZE_PRINTF7(a,b,c,d,e,f,g) { if (verbose) { printf (a,b,c,d,e,f,g); } } # define ANALYZE_PRINTF8(a,b,c,d,e,f,g,h) { if (verbose) { printf (a,b,c,d,e,f,g,h); } } # define ANALYZE_PRINTF9(a,b,c,d,e,f,g,h,i) { if (verbose) { printf (a,b,c,d,e,f,g,h,i); } } //# define ANALYZE_ONLY_NORMAL_PRINTF(...) { if (! silent && !verbose) { printf (__VA_ARGS__); } } # define ANALYZE_ONLY_NORMAL_PRINTF1(a) { if (! silent && !verbose) { printf (a); } } # define ANALYZE_NEWLINE() { if (verbose) { putchar ('\n'); } } static int silent; static int time_counter; static int verbose; #else # define ANALYZE_PUTCHAR(a) # define ANALYZE_ONLY_NORMAL_PUTCHAR(a) // # define ANALYZE_PRINTF(...) # define ANALYZE_PRINTF1(a) # define ANALYZE_PRINTF2(a,b) # define ANALYZE_PRINTF3(a,b,c) # define ANALYZE_PRINTF4(a,b,c,d) # define ANALYZE_PRINTF5(a,b,c,d,e) # define ANALYZE_PRINTF6(a,b,c,d,e,f) # define ANALYZE_PRINTF7(a,b,c,d,e,f,g) # define ANALYZE_PRINTF8(a,b,c,d,e,f,g,h) # define ANALYZE_PRINTF9(a,b,c,d,e,f,g,h,i) //# define ANALYZE_ONLY_NORMAL_PRINTF(...) # define ANALYZE_ONLY_NORMAL_PRINTF1(a) # define ANALYZE_NEWLINE() #endif #if IRMP_USE_CALLBACK == 1 static void (*irmp_callback_ptr) (uint_fast8_t); #endif // IRMP_USE_CALLBACK == 1 #if IRMP_USE_COMPLETE_CALLBACK == 1 static void (*irmp_complete_callback_function)(void); void irmp_register_complete_callback_function(void (*aCompleteCallbackFunction)(void)) { irmp_complete_callback_function = aCompleteCallbackFunction; } #endif // IRMP_USE_COMPLETE_CALLBACK == 1 #define PARITY_CHECK_OK 1 #define PARITY_CHECK_FAILED 0 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocol names *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1 #include "irmpprotocols.hpp" // include protocol strings and array of strings #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Logging *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if IRMP_LOGGING == 1 // logging via UART #if defined(ARM_STM32F4XX) # define STM32_GPIO_CLOCK RCC_AHB1Periph_GPIOA // UART2 on PA2 # define STM32_UART_CLOCK RCC_APB1Periph_USART2 # define STM32_GPIO_PORT GPIOA # define STM32_GPIO_PIN GPIO_Pin_2 # define STM32_GPIO_SOURCE GPIO_PinSource2 # define STM32_UART_AF GPIO_AF_USART2 # define STM32_UART_COM USART2 # define STM32_UART_BAUD 115200 // 115200 Baud # include "stm32f4xx_usart.h" #elif defined(ARM_STM32F10X) || defined(ARM_STM32F30X) # define STM32_UART_COM USART3 // UART3 on PB10 #elif defined(ARDUINO) // Arduino Serial implementation # include "HardwareSerial.h" #elif defined(_CHIBIOS_HAL_) // ChibiOS HAL # if IRMP_EXT_LOGGING == 1 # error IRMP_EXT_LOGGING not implemented for ChibiOS HAL, use regular logging instead # endif #else # if IRMP_EXT_LOGGING == 1 // use external logging # include "irmpextlog.h" # else // normal UART log (IRMP_EXT_LOGGING == 0) # define BAUD 9600L # if !defined(UNIX_OR_WINDOWS) # include # endif #if defined(UBRR)0H #define UART0_UBRRH UBRR0H #define UART0_UBRRL UBRR0L #define UART0_UCSRA UCSR0A #define UART0_UCSRB UCSR0B #define UART0_UCSRC UCSR0C #define UART0_UDRE_BIT_VALUE (1< ENDBITS) // if high received then look at log-stop condition { // if stop condition is true, output on uart uint_fast8_t i8; uint_fast16_t i; uint_fast16_t j; uint_fast8_t v = '1'; uint_fast16_t d; for (i8 = 0; i8 < STARTCYCLES; i8++) { irmp_uart_putc ('0'); // the ignored starting zeros } for (i = 0; i < buf_idx; i++) { d = buf[i]; if (d == 0xff) { i++; d = buf[i]; i++; d |= ((uint_fast16_t) buf[i] << 8); } for (j = 0; j < d; j++) { irmp_uart_putc (v); } v = (v == '1') ? '0' : '1'; } for (i8 = 0; i8 < 20; i8++) { irmp_uart_putc ('1'); } irmp_uart_putc ('\n'); buf_idx = 0; last_val = 1; cnt = 0; } } else if (buf_idx < DATALEN - 3) { if (cnt >= 0xff) { buf[buf_idx++] = 0xff; buf[buf_idx++] = (cnt & 0xff); buf[buf_idx] = (cnt >> 8); } else { buf[buf_idx] = cnt; } buf_idx++; cnt = 1; last_val = val; } } } } #else #define irmp_log(val) #endif //IRMP_LOGGING typedef struct { uint_fast8_t protocol; // ir protocol uint_fast8_t pulse_1_len_min; // minimum length of pulse with bit value 1 uint_fast8_t pulse_1_len_max; // maximum length of pulse with bit value 1 uint_fast8_t pause_1_len_min; // minimum length of pause with bit value 1 uint_fast8_t pause_1_len_max; // maximum length of pause with bit value 1 uint_fast8_t pulse_0_len_min; // minimum length of pulse with bit value 0 uint_fast8_t pulse_0_len_max; // maximum length of pulse with bit value 0 uint_fast8_t pause_0_len_min; // minimum length of pause with bit value 0 uint_fast8_t pause_0_len_max; // maximum length of pause with bit value 0 uint_fast8_t address_offset; // address offset uint_fast8_t address_end; // end of address uint_fast8_t command_offset; // command offset uint_fast8_t command_end; // end of command uint_fast8_t complete_len; // complete length of frame uint_fast8_t stop_bit; // flag: frame has stop bit uint_fast8_t lsb_first; // flag: LSB first uint_fast8_t flags; // some flags } IRMP_PARAMETER; #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER sircs_param = { IRMP_SIRCS_PROTOCOL, // protocol: ir protocol SIRCS_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 SIRCS_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 SIRCS_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 SIRCS_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 SIRCS_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 SIRCS_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 SIRCS_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 SIRCS_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 SIRCS_ADDRESS_OFFSET, // address_offset: address offset SIRCS_ADDRESS_OFFSET + SIRCS_ADDRESS_LEN, // address_end: end of address SIRCS_COMMAND_OFFSET, // command_offset: command offset SIRCS_COMMAND_OFFSET + SIRCS_COMMAND_LEN, // command_end: end of command SIRCS_COMPLETE_DATA_LEN, // complete_len: complete length of frame SIRCS_STOP_BIT, // stop_bit: flag: frame has stop bit SIRCS_LSB, // lsb_first: flag: LSB first SIRCS_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER nec_param = { IRMP_NEC_PROTOCOL, // protocol: ir protocol NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 NEC_ADDRESS_OFFSET, // address_offset: address offset NEC_ADDRESS_OFFSET + NEC_ADDRESS_LEN, // address_end: end of address NEC_COMMAND_OFFSET, // command_offset: command offset NEC_COMMAND_OFFSET + NEC_COMMAND_LEN, // command_end: end of command NEC_COMPLETE_DATA_LEN, // complete_len: complete length of frame NEC_STOP_BIT, // stop_bit: flag: frame has stop bit NEC_LSB, // lsb_first: flag: LSB first NEC_FLAGS // flags: some flags }; static const PROGMEM IRMP_PARAMETER nec_rep_param = { IRMP_NEC_PROTOCOL, // protocol: ir protocol NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 0, // address_offset: address offset 0, // address_end: end of address 0, // command_offset: command offset 0, // command_end: end of command 0, // complete_len: complete length of frame NEC_STOP_BIT, // stop_bit: flag: frame has stop bit NEC_LSB, // lsb_first: flag: LSB first NEC_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER nec42_param = { IRMP_NEC42_PROTOCOL, // protocol: ir protocol NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 NEC42_ADDRESS_OFFSET, // address_offset: address offset NEC42_ADDRESS_OFFSET + NEC42_ADDRESS_LEN, // address_end: end of address NEC42_COMMAND_OFFSET, // command_offset: command offset NEC42_COMMAND_OFFSET + NEC42_COMMAND_LEN, // command_end: end of command NEC42_COMPLETE_DATA_LEN, // complete_len: complete length of frame NEC_STOP_BIT, // stop_bit: flag: frame has stop bit NEC_LSB, // lsb_first: flag: LSB first NEC_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 #if 0 // not needed, switching from NEC static const PROGMEM IRMP_PARAMETER lgair_param = { IRMP_LGAIR_PROTOCOL, // protocol: ir protocol NEC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NEC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NEC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NEC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NEC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NEC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NEC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NEC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 LGAIR_ADDRESS_OFFSET, // address_offset: address offset LGAIR_ADDRESS_OFFSET + LGAIR_ADDRESS_LEN, // address_end: end of address LGAIR_COMMAND_OFFSET, // command_offset: command offset LGAIR_COMMAND_OFFSET + LGAIR_COMMAND_LEN, // command_end: end of command LGAIR_COMPLETE_DATA_LEN, // complete_len: complete length of frame NEC_STOP_BIT, // stop_bit: flag: frame has stop bit NEC_LSB, // lsb_first: flag: LSB first NEC_FLAGS // flags: some flags }; #endif // 0 not needed, switching from NEC #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER samsung_param = { IRMP_SAMSUNG_PROTOCOL, // protocol: ir protocol SAMSUNG_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 SAMSUNG_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 SAMSUNG_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 SAMSUNG_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 SAMSUNG_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 SAMSUNG_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 SAMSUNG_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 SAMSUNG_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 SAMSUNG_ADDRESS_OFFSET, // address_offset: address offset SAMSUNG_ADDRESS_OFFSET + SAMSUNG_ADDRESS_LEN, // address_end: end of address SAMSUNG_COMMAND_OFFSET, // command_offset: command offset SAMSUNG_COMMAND_OFFSET + SAMSUNG_COMMAND_LEN, // command_end: end of command SAMSUNG_COMPLETE_DATA_LEN, // complete_len: complete length of frame SAMSUNG_STOP_BIT, // stop_bit: flag: frame has stop bit SAMSUNG_LSB, // lsb_first: flag: LSB first SAMSUNG_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER samsungah_param = { IRMP_SAMSUNGAH_PROTOCOL, // protocol: ir protocol SAMSUNGAH_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 SAMSUNGAH_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 SAMSUNGAH_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 SAMSUNGAH_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 SAMSUNGAH_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 SAMSUNGAH_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 SAMSUNGAH_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 SAMSUNGAH_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 SAMSUNGAH_ADDRESS_OFFSET, // address_offset: address offset SAMSUNGAH_ADDRESS_OFFSET + SAMSUNGAH_ADDRESS_LEN, // address_end: end of address SAMSUNGAH_COMMAND_OFFSET, // command_offset: command offset SAMSUNGAH_COMMAND_OFFSET + SAMSUNGAH_COMMAND_LEN, // command_end: end of command SAMSUNGAH_COMPLETE_DATA_LEN, // complete_len: complete length of frame SAMSUNGAH_STOP_BIT, // stop_bit: flag: frame has stop bit SAMSUNGAH_LSB, // lsb_first: flag: LSB first SAMSUNGAH_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER telefunken_param = { IRMP_TELEFUNKEN_PROTOCOL, // protocol: ir protocol TELEFUNKEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 TELEFUNKEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 TELEFUNKEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 TELEFUNKEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 TELEFUNKEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 TELEFUNKEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 TELEFUNKEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 TELEFUNKEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 TELEFUNKEN_ADDRESS_OFFSET, // address_offset: address offset TELEFUNKEN_ADDRESS_OFFSET + TELEFUNKEN_ADDRESS_LEN, // address_end: end of address TELEFUNKEN_COMMAND_OFFSET, // command_offset: command offset TELEFUNKEN_COMMAND_OFFSET + TELEFUNKEN_COMMAND_LEN, // command_end: end of command TELEFUNKEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame TELEFUNKEN_STOP_BIT, // stop_bit: flag: frame has stop bit TELEFUNKEN_LSB, // lsb_first: flag: LSB first TELEFUNKEN_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER matsushita_param = { IRMP_MATSUSHITA_PROTOCOL, // protocol: ir protocol MATSUSHITA_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 MATSUSHITA_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 MATSUSHITA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 MATSUSHITA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 MATSUSHITA_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 MATSUSHITA_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 MATSUSHITA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 MATSUSHITA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 MATSUSHITA_ADDRESS_OFFSET, // address_offset: address offset MATSUSHITA_ADDRESS_OFFSET + MATSUSHITA_ADDRESS_LEN, // address_end: end of address MATSUSHITA_COMMAND_OFFSET, // command_offset: command offset MATSUSHITA_COMMAND_OFFSET + MATSUSHITA_COMMAND_LEN, // command_end: end of command MATSUSHITA_COMPLETE_DATA_LEN, // complete_len: complete length of frame MATSUSHITA_STOP_BIT, // stop_bit: flag: frame has stop bit MATSUSHITA_LSB, // lsb_first: flag: LSB first MATSUSHITA_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER kaseikyo_param = { IRMP_KASEIKYO_PROTOCOL, // protocol: ir protocol KASEIKYO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 KASEIKYO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 KASEIKYO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 KASEIKYO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 KASEIKYO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 KASEIKYO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 KASEIKYO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 KASEIKYO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 KASEIKYO_ADDRESS_OFFSET, // address_offset: address offset KASEIKYO_ADDRESS_OFFSET + KASEIKYO_ADDRESS_LEN, // address_end: end of address KASEIKYO_COMMAND_OFFSET, // command_offset: command offset KASEIKYO_COMMAND_OFFSET + KASEIKYO_COMMAND_LEN, // command_end: end of command KASEIKYO_COMPLETE_DATA_LEN, // complete_len: complete length of frame KASEIKYO_STOP_BIT, // stop_bit: flag: frame has stop bit KASEIKYO_LSB, // lsb_first: flag: LSB first KASEIKYO_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER panasonic_param = { IRMP_PANASONIC_PROTOCOL, // protocol: ir protocol PANASONIC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 PANASONIC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 PANASONIC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 PANASONIC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 PANASONIC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 PANASONIC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 PANASONIC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 PANASONIC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 PANASONIC_ADDRESS_OFFSET, // address_offset: address offset PANASONIC_ADDRESS_OFFSET + PANASONIC_ADDRESS_LEN, // address_end: end of address PANASONIC_COMMAND_OFFSET, // command_offset: command offset PANASONIC_COMMAND_OFFSET + PANASONIC_COMMAND_LEN, // command_end: end of command PANASONIC_COMPLETE_DATA_LEN, // complete_len: complete length of frame PANASONIC_STOP_BIT, // stop_bit: flag: frame has stop bit PANASONIC_LSB, // lsb_first: flag: LSB first PANASONIC_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER mitsu_heavy_param = { IRMP_MITSU_HEAVY_PROTOCOL, // protocol: ir protocol MITSU_HEAVY_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 MITSU_HEAVY_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 MITSU_HEAVY_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 MITSU_HEAVY_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 MITSU_HEAVY_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 MITSU_HEAVY_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 MITSU_HEAVY_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 MITSU_HEAVY_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 MITSU_HEAVY_ADDRESS_OFFSET, // address_offset: address offset MITSU_HEAVY_ADDRESS_OFFSET + MITSU_HEAVY_ADDRESS_LEN, // address_end: end of address MITSU_HEAVY_COMMAND_OFFSET, // command_offset: command offset MITSU_HEAVY_COMMAND_OFFSET + MITSU_HEAVY_COMMAND_LEN, // command_end: end of command MITSU_HEAVY_COMPLETE_DATA_LEN, // complete_len: complete length of frame MITSU_HEAVY_STOP_BIT, // stop_bit: flag: frame has stop bit MITSU_HEAVY_LSB, // lsb_first: flag: LSB first MITSU_HEAVY_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER vincent_param = { IRMP_VINCENT_PROTOCOL, // protocol: ir protocol VINCENT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 VINCENT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 VINCENT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 VINCENT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 VINCENT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 VINCENT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 VINCENT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 VINCENT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 VINCENT_ADDRESS_OFFSET, // address_offset: address offset VINCENT_ADDRESS_OFFSET + VINCENT_ADDRESS_LEN, // address_end: end of address VINCENT_COMMAND_OFFSET, // command_offset: command offset VINCENT_COMMAND_OFFSET + VINCENT_COMMAND_LEN, // command_end: end of command VINCENT_COMPLETE_DATA_LEN, // complete_len: complete length of frame VINCENT_STOP_BIT, // stop_bit: flag: frame has stop bit VINCENT_LSB, // lsb_first: flag: LSB first VINCENT_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RECS80_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER recs80_param = { IRMP_RECS80_PROTOCOL, // protocol: ir protocol RECS80_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RECS80_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RECS80_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RECS80_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RECS80_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RECS80_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RECS80_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RECS80_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RECS80_ADDRESS_OFFSET, // address_offset: address offset RECS80_ADDRESS_OFFSET + RECS80_ADDRESS_LEN, // address_end: end of address RECS80_COMMAND_OFFSET, // command_offset: command offset RECS80_COMMAND_OFFSET + RECS80_COMMAND_LEN, // command_end: end of command RECS80_COMPLETE_DATA_LEN, // complete_len: complete length of frame RECS80_STOP_BIT, // stop_bit: flag: frame has stop bit RECS80_LSB, // lsb_first: flag: LSB first RECS80_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rc5_param = { IRMP_RC5_PROTOCOL, // protocol: ir protocol RC5_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse RC5_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse RC5_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause RC5_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used RC5_ADDRESS_OFFSET, // address_offset: address offset RC5_ADDRESS_OFFSET + RC5_ADDRESS_LEN, // address_end: end of address RC5_COMMAND_OFFSET, // command_offset: command offset RC5_COMMAND_OFFSET + RC5_COMMAND_LEN, // command_end: end of command RC5_COMPLETE_DATA_LEN, // complete_len: complete length of frame RC5_STOP_BIT, // stop_bit: flag: frame has stop bit RC5_LSB, // lsb_first: flag: LSB first RC5_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RCII_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rcii_param = { IRMP_RCII_PROTOCOL, // protocol: ir protocol RCII_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse RCII_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse RCII_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause RCII_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause RCII_BIT_LEN_MIN, // pulse_0_len_min: here: not used RCII_BIT_LEN_MAX, // pulse_0_len_max: here: not used RCII_BIT_LEN_MIN, // pause_0_len_min: here: not used RCII_BIT_LEN_MAX, // pause_0_len_max: here: not used RCII_ADDRESS_OFFSET, // address_offset: address offset RCII_ADDRESS_OFFSET + RCII_ADDRESS_LEN, // address_end: end of address RCII_COMMAND_OFFSET, // command_offset: command offset RCII_COMMAND_OFFSET + RCII_COMMAND_LEN, // command_end: end of command RCII_COMPLETE_DATA_LEN, // complete_len: complete length of frame RCII_STOP_BIT, // stop_bit: flag: frame has stop bit RCII_LSB, // lsb_first: flag: LSB first RCII_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_S100_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER s100_param = { IRMP_S100_PROTOCOL, // protocol: ir protocol S100_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse S100_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse S100_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause S100_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used S100_ADDRESS_OFFSET, // address_offset: address offset S100_ADDRESS_OFFSET + S100_ADDRESS_LEN, // address_end: end of address S100_COMMAND_OFFSET, // command_offset: command offset S100_COMMAND_OFFSET + S100_COMMAND_LEN, // command_end: end of command S100_COMPLETE_DATA_LEN, // complete_len: complete length of frame S100_STOP_BIT, // stop_bit: flag: frame has stop bit S100_LSB, // lsb_first: flag: LSB first S100_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER denon_param = { IRMP_DENON_PROTOCOL, // protocol: ir protocol DENON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 DENON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 DENON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 DENON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 DENON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 DENON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 DENON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 DENON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 DENON_ADDRESS_OFFSET, // address_offset: address offset DENON_ADDRESS_OFFSET + DENON_ADDRESS_LEN, // address_end: end of address DENON_COMMAND_OFFSET, // command_offset: command offset DENON_COMMAND_OFFSET + DENON_COMMAND_LEN, // command_end: end of command DENON_COMPLETE_DATA_LEN, // complete_len: complete length of frame DENON_STOP_BIT, // stop_bit: flag: frame has stop bit DENON_LSB, // lsb_first: flag: LSB first DENON_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rc6_param = { IRMP_RC6_PROTOCOL, // protocol: ir protocol RC6_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse RC6_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse RC6_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause RC6_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used RC6_ADDRESS_OFFSET, // address_offset: address offset RC6_ADDRESS_OFFSET + RC6_ADDRESS_LEN, // address_end: end of address RC6_COMMAND_OFFSET, // command_offset: command offset RC6_COMMAND_OFFSET + RC6_COMMAND_LEN, // command_end: end of command RC6_COMPLETE_DATA_LEN_SHORT, // complete_len: complete length of frame RC6_STOP_BIT, // stop_bit: flag: frame has stop bit RC6_LSB, // lsb_first: flag: LSB first RC6_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER recs80ext_param = { IRMP_RECS80EXT_PROTOCOL, // protocol: ir protocol RECS80EXT_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RECS80EXT_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RECS80EXT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RECS80EXT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RECS80EXT_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RECS80EXT_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RECS80EXT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RECS80EXT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RECS80EXT_ADDRESS_OFFSET, // address_offset: address offset RECS80EXT_ADDRESS_OFFSET + RECS80EXT_ADDRESS_LEN, // address_end: end of address RECS80EXT_COMMAND_OFFSET, // command_offset: command offset RECS80EXT_COMMAND_OFFSET + RECS80EXT_COMMAND_LEN, // command_end: end of command RECS80EXT_COMPLETE_DATA_LEN, // complete_len: complete length of frame RECS80EXT_STOP_BIT, // stop_bit: flag: frame has stop bit RECS80EXT_LSB, // lsb_first: flag: LSB first RECS80EXT_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER nubert_param = { IRMP_NUBERT_PROTOCOL, // protocol: ir protocol NUBERT_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NUBERT_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NUBERT_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NUBERT_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NUBERT_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NUBERT_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NUBERT_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NUBERT_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 NUBERT_ADDRESS_OFFSET, // address_offset: address offset NUBERT_ADDRESS_OFFSET + NUBERT_ADDRESS_LEN, // address_end: end of address NUBERT_COMMAND_OFFSET, // command_offset: command offset NUBERT_COMMAND_OFFSET + NUBERT_COMMAND_LEN, // command_end: end of command NUBERT_COMPLETE_DATA_LEN, // complete_len: complete length of frame NUBERT_STOP_BIT, // stop_bit: flag: frame has stop bit NUBERT_LSB, // lsb_first: flag: LSB first NUBERT_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_FAN_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER fan_param = { IRMP_FAN_PROTOCOL, // protocol: ir protocol FAN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 FAN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 FAN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 FAN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 FAN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 FAN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 FAN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 FAN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 FAN_ADDRESS_OFFSET, // address_offset: address offset FAN_ADDRESS_OFFSET + FAN_ADDRESS_LEN, // address_end: end of address FAN_COMMAND_OFFSET, // command_offset: command offset FAN_COMMAND_OFFSET + FAN_COMMAND_LEN, // command_end: end of command FAN_COMPLETE_DATA_LEN, // complete_len: complete length of frame FAN_STOP_BIT, // stop_bit: flag: frame has NO stop bit FAN_LSB, // lsb_first: flag: LSB first FAN_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER speaker_param = { IRMP_SPEAKER_PROTOCOL, // protocol: ir protocol SPEAKER_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 SPEAKER_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 SPEAKER_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 SPEAKER_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 SPEAKER_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 SPEAKER_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 SPEAKER_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 SPEAKER_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 SPEAKER_ADDRESS_OFFSET, // address_offset: address offset SPEAKER_ADDRESS_OFFSET + SPEAKER_ADDRESS_LEN, // address_end: end of address SPEAKER_COMMAND_OFFSET, // command_offset: command offset SPEAKER_COMMAND_OFFSET + SPEAKER_COMMAND_LEN, // command_end: end of command SPEAKER_COMPLETE_DATA_LEN, // complete_len: complete length of frame SPEAKER_STOP_BIT, // stop_bit: flag: frame has stop bit SPEAKER_LSB, // lsb_first: flag: LSB first SPEAKER_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER bang_olufsen_param = { IRMP_BANG_OLUFSEN_PROTOCOL, // protocol: ir protocol BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 BANG_OLUFSEN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 BANG_OLUFSEN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 BANG_OLUFSEN_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 BANG_OLUFSEN_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 BANG_OLUFSEN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 BANG_OLUFSEN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 BANG_OLUFSEN_ADDRESS_OFFSET, // address_offset: address offset BANG_OLUFSEN_ADDRESS_OFFSET + BANG_OLUFSEN_ADDRESS_LEN, // address_end: end of address BANG_OLUFSEN_COMMAND_OFFSET, // command_offset: command offset BANG_OLUFSEN_COMMAND_OFFSET + BANG_OLUFSEN_COMMAND_LEN, // command_end: end of command BANG_OLUFSEN_COMPLETE_DATA_LEN, // complete_len: complete length of frame BANG_OLUFSEN_STOP_BIT, // stop_bit: flag: frame has stop bit BANG_OLUFSEN_LSB, // lsb_first: flag: LSB first BANG_OLUFSEN_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 static uint_fast8_t first_bit; static const PROGMEM IRMP_PARAMETER grundig_param = { IRMP_GRUNDIG_PROTOCOL, // protocol: ir protocol GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse GRUNDIG_NOKIA_IR60_BIT_LEN_MIN, // pause_1_len_min: here: minimum length of short pause GRUNDIG_NOKIA_IR60_BIT_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used GRUNDIG_ADDRESS_OFFSET, // address_offset: address offset GRUNDIG_ADDRESS_OFFSET + GRUNDIG_ADDRESS_LEN, // address_end: end of address GRUNDIG_COMMAND_OFFSET, // command_offset: command offset GRUNDIG_COMMAND_OFFSET + GRUNDIG_COMMAND_LEN + 1, // command_end: end of command (USE 1 bit MORE to STORE NOKIA DATA!) NOKIA_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: NOKIA instead of GRUNDIG! GRUNDIG_NOKIA_IR60_STOP_BIT, // stop_bit: flag: frame has stop bit GRUNDIG_NOKIA_IR60_LSB, // lsb_first: flag: LSB first GRUNDIG_NOKIA_IR60_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER ruwido_param = { IRMP_RUWIDO_PROTOCOL, // protocol: ir protocol SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse SIEMENS_OR_RUWIDO_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause SIEMENS_OR_RUWIDO_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used RUWIDO_ADDRESS_OFFSET, // address_offset: address offset RUWIDO_ADDRESS_OFFSET + RUWIDO_ADDRESS_LEN, // address_end: end of address RUWIDO_COMMAND_OFFSET, // command_offset: command offset RUWIDO_COMMAND_OFFSET + RUWIDO_COMMAND_LEN, // command_end: end of command SIEMENS_COMPLETE_DATA_LEN, // complete_len: complete length of frame, here: SIEMENS instead of RUWIDO! SIEMENS_OR_RUWIDO_STOP_BIT, // stop_bit: flag: frame has stop bit SIEMENS_OR_RUWIDO_LSB, // lsb_first: flag: LSB first SIEMENS_OR_RUWIDO_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_FDC_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER fdc_param = { IRMP_FDC_PROTOCOL, // protocol: ir protocol FDC_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 FDC_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 FDC_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 FDC_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 FDC_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 FDC_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 FDC_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 FDC_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 FDC_ADDRESS_OFFSET, // address_offset: address offset FDC_ADDRESS_OFFSET + FDC_ADDRESS_LEN, // address_end: end of address FDC_COMMAND_OFFSET, // command_offset: command offset FDC_COMMAND_OFFSET + FDC_COMMAND_LEN, // command_end: end of command FDC_COMPLETE_DATA_LEN, // complete_len: complete length of frame FDC_STOP_BIT, // stop_bit: flag: frame has stop bit FDC_LSB, // lsb_first: flag: LSB first FDC_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rccar_param = { IRMP_RCCAR_PROTOCOL, // protocol: ir protocol RCCAR_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RCCAR_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RCCAR_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RCCAR_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RCCAR_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RCCAR_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RCCAR_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RCCAR_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RCCAR_ADDRESS_OFFSET, // address_offset: address offset RCCAR_ADDRESS_OFFSET + RCCAR_ADDRESS_LEN, // address_end: end of address RCCAR_COMMAND_OFFSET, // command_offset: command offset RCCAR_COMMAND_OFFSET + RCCAR_COMMAND_LEN, // command_end: end of command RCCAR_COMPLETE_DATA_LEN, // complete_len: complete length of frame RCCAR_STOP_BIT, // stop_bit: flag: frame has stop bit RCCAR_LSB, // lsb_first: flag: LSB first RCCAR_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER nikon_param = { IRMP_NIKON_PROTOCOL, // protocol: ir protocol NIKON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 NIKON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 NIKON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 NIKON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 NIKON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 NIKON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 NIKON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 NIKON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 NIKON_ADDRESS_OFFSET, // address_offset: address offset NIKON_ADDRESS_OFFSET + NIKON_ADDRESS_LEN, // address_end: end of address NIKON_COMMAND_OFFSET, // command_offset: command offset NIKON_COMMAND_OFFSET + NIKON_COMMAND_LEN, // command_end: end of command NIKON_COMPLETE_DATA_LEN, // complete_len: complete length of frame NIKON_STOP_BIT, // stop_bit: flag: frame has stop bit NIKON_LSB, // lsb_first: flag: LSB first NIKON_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER kathrein_param = { IRMP_KATHREIN_PROTOCOL, // protocol: ir protocol KATHREIN_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 KATHREIN_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 KATHREIN_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 KATHREIN_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 KATHREIN_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 KATHREIN_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 KATHREIN_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 KATHREIN_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 KATHREIN_ADDRESS_OFFSET, // address_offset: address offset KATHREIN_ADDRESS_OFFSET + KATHREIN_ADDRESS_LEN, // address_end: end of address KATHREIN_COMMAND_OFFSET, // command_offset: command offset KATHREIN_COMMAND_OFFSET + KATHREIN_COMMAND_LEN, // command_end: end of command KATHREIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame KATHREIN_STOP_BIT, // stop_bit: flag: frame has stop bit KATHREIN_LSB, // lsb_first: flag: LSB first KATHREIN_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER netbox_param = { IRMP_NETBOX_PROTOCOL, // protocol: ir protocol NETBOX_PULSE_LEN, // pulse_1_len_min: minimum length of pulse with bit value 1, here: exact value NETBOX_PULSE_REST_LEN, // pulse_1_len_max: maximum length of pulse with bit value 1, here: rest value NETBOX_PAUSE_LEN, // pause_1_len_min: minimum length of pause with bit value 1, here: exact value NETBOX_PAUSE_REST_LEN, // pause_1_len_max: maximum length of pause with bit value 1, here: rest value NETBOX_PULSE_LEN, // pulse_0_len_min: minimum length of pulse with bit value 0, here: exact value NETBOX_PULSE_REST_LEN, // pulse_0_len_max: maximum length of pulse with bit value 0, here: rest value NETBOX_PAUSE_LEN, // pause_0_len_min: minimum length of pause with bit value 0, here: exact value NETBOX_PAUSE_REST_LEN, // pause_0_len_max: maximum length of pause with bit value 0, here: rest value NETBOX_ADDRESS_OFFSET, // address_offset: address offset NETBOX_ADDRESS_OFFSET + NETBOX_ADDRESS_LEN, // address_end: end of address NETBOX_COMMAND_OFFSET, // command_offset: command offset NETBOX_COMMAND_OFFSET + NETBOX_COMMAND_LEN, // command_end: end of command NETBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame NETBOX_STOP_BIT, // stop_bit: flag: frame has stop bit NETBOX_LSB, // lsb_first: flag: LSB first NETBOX_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER lego_param = { IRMP_LEGO_PROTOCOL, // protocol: ir protocol LEGO_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 LEGO_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 LEGO_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 LEGO_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 LEGO_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 LEGO_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 LEGO_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 LEGO_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 LEGO_ADDRESS_OFFSET, // address_offset: address offset LEGO_ADDRESS_OFFSET + LEGO_ADDRESS_LEN, // address_end: end of address LEGO_COMMAND_OFFSET, // command_offset: command offset LEGO_COMMAND_OFFSET + LEGO_COMMAND_LEN, // command_end: end of command LEGO_COMPLETE_DATA_LEN, // complete_len: complete length of frame LEGO_STOP_BIT, // stop_bit: flag: frame has stop bit LEGO_LSB, // lsb_first: flag: LSB first LEGO_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER irmp16_param = { IRMP_IRMP16_PROTOCOL, // protocol: ir protocol IRMP16_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 IRMP16_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 IRMP16_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 IRMP16_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 IRMP16_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 IRMP16_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 IRMP16_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 IRMP16_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 IRMP16_ADDRESS_OFFSET, // address_offset: address offset IRMP16_ADDRESS_OFFSET + IRMP16_ADDRESS_LEN, // address_end: end of address IRMP16_COMMAND_OFFSET, // command_offset: command offset IRMP16_COMMAND_OFFSET + IRMP16_COMMAND_LEN, // command_end: end of command IRMP16_COMPLETE_DATA_LEN, // complete_len: complete length of frame IRMP16_STOP_BIT, // stop_bit: flag: frame has stop bit IRMP16_LSB, // lsb_first: flag: LSB first IRMP16_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_GREE_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER gree_param = { IRMP_GREE_PROTOCOL, // protocol: ir protocol GREE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 GREE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 GREE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 GREE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 GREE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 GREE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 GREE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 GREE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 GREE_ADDRESS_OFFSET, // address_offset: address offset GREE_ADDRESS_OFFSET + GREE_ADDRESS_LEN, // address_end: end of address GREE_COMMAND_OFFSET, // command_offset: command offset GREE_COMMAND_OFFSET + GREE_COMMAND_LEN, // command_end: end of command GREE_COMPLETE_DATA_LEN, // complete_len: complete length of frame GREE_STOP_BIT, // stop_bit: flag: frame has stop bit GREE_LSB, // lsb_first: flag: LSB first GREE_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER thomson_param = { IRMP_THOMSON_PROTOCOL, // protocol: ir protocol THOMSON_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 THOMSON_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 THOMSON_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 THOMSON_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 THOMSON_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 THOMSON_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 THOMSON_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 THOMSON_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 THOMSON_ADDRESS_OFFSET, // address_offset: address offset THOMSON_ADDRESS_OFFSET + THOMSON_ADDRESS_LEN, // address_end: end of address THOMSON_COMMAND_OFFSET, // command_offset: command offset THOMSON_COMMAND_OFFSET + THOMSON_COMMAND_LEN, // command_end: end of command THOMSON_COMPLETE_DATA_LEN, // complete_len: complete length of frame THOMSON_STOP_BIT, // stop_bit: flag: frame has stop bit THOMSON_LSB, // lsb_first: flag: LSB first THOMSON_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER bose_param = { IRMP_BOSE_PROTOCOL, // protocol: ir protocol BOSE_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 BOSE_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 BOSE_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 BOSE_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 BOSE_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 BOSE_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 BOSE_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 BOSE_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 BOSE_ADDRESS_OFFSET, // address_offset: address offset BOSE_ADDRESS_OFFSET + BOSE_ADDRESS_LEN, // address_end: end of address BOSE_COMMAND_OFFSET, // command_offset: command offset BOSE_COMMAND_OFFSET + BOSE_COMMAND_LEN, // command_end: end of command BOSE_COMPLETE_DATA_LEN, // complete_len: complete length of frame BOSE_STOP_BIT, // stop_bit: flag: frame has stop bit BOSE_LSB, // lsb_first: flag: LSB first BOSE_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER a1tvbox_param = { IRMP_A1TVBOX_PROTOCOL, // protocol: ir protocol A1TVBOX_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse A1TVBOX_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse A1TVBOX_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause A1TVBOX_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used A1TVBOX_ADDRESS_OFFSET, // address_offset: address offset A1TVBOX_ADDRESS_OFFSET + A1TVBOX_ADDRESS_LEN, // address_end: end of address A1TVBOX_COMMAND_OFFSET, // command_offset: command offset A1TVBOX_COMMAND_OFFSET + A1TVBOX_COMMAND_LEN, // command_end: end of command A1TVBOX_COMPLETE_DATA_LEN, // complete_len: complete length of frame A1TVBOX_STOP_BIT, // stop_bit: flag: frame has stop bit A1TVBOX_LSB, // lsb_first: flag: LSB first A1TVBOX_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER merlin_param = { IRMP_MERLIN_PROTOCOL, // protocol: ir protocol MERLIN_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse MERLIN_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse MERLIN_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause MERLIN_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used MERLIN_ADDRESS_OFFSET, // address_offset: address offset MERLIN_ADDRESS_OFFSET + MERLIN_ADDRESS_LEN, // address_end: end of address MERLIN_COMMAND_OFFSET, // command_offset: command offset MERLIN_COMMAND_OFFSET + MERLIN_COMMAND_LEN, // command_end: end of command MERLIN_COMPLETE_DATA_LEN, // complete_len: complete length of frame MERLIN_STOP_BIT, // stop_bit: flag: frame has stop bit MERLIN_LSB, // lsb_first: flag: LSB first MERLIN_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER ortek_param = { IRMP_ORTEK_PROTOCOL, // protocol: ir protocol ORTEK_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse ORTEK_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse ORTEK_BIT_PAUSE_LEN_MIN, // pause_1_len_min: here: minimum length of short pause ORTEK_BIT_PAUSE_LEN_MAX, // pause_1_len_max: here: maximum length of short pause 0, // pulse_0_len_min: here: not used 0, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used ORTEK_ADDRESS_OFFSET, // address_offset: address offset ORTEK_ADDRESS_OFFSET + ORTEK_ADDRESS_LEN, // address_end: end of address ORTEK_COMMAND_OFFSET, // command_offset: command offset ORTEK_COMMAND_OFFSET + ORTEK_COMMAND_LEN, // command_end: end of command ORTEK_COMPLETE_DATA_LEN, // complete_len: complete length of frame ORTEK_STOP_BIT, // stop_bit: flag: frame has stop bit ORTEK_LSB, // lsb_first: flag: LSB first ORTEK_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER roomba_param = { IRMP_ROOMBA_PROTOCOL, // protocol: ir protocol ROOMBA_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 ROOMBA_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 ROOMBA_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 ROOMBA_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 ROOMBA_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 ROOMBA_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 ROOMBA_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 ROOMBA_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 ROOMBA_ADDRESS_OFFSET, // address_offset: address offset ROOMBA_ADDRESS_OFFSET + ROOMBA_ADDRESS_LEN, // address_end: end of address ROOMBA_COMMAND_OFFSET, // command_offset: command offset ROOMBA_COMMAND_OFFSET + ROOMBA_COMMAND_LEN, // command_end: end of command ROOMBA_COMPLETE_DATA_LEN, // complete_len: complete length of frame ROOMBA_STOP_BIT, // stop_bit: flag: frame has stop bit ROOMBA_LSB, // lsb_first: flag: LSB first ROOMBA_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rcmm_param = { IRMP_RCMM32_PROTOCOL, // protocol: ir protocol RCMM32_BIT_PULSE_LEN_MIN, // pulse_1_len_min: here: minimum length of short pulse RCMM32_BIT_PULSE_LEN_MAX, // pulse_1_len_max: here: maximum length of short pulse 0, // pause_1_len_min: here: minimum length of short pause 0, // pause_1_len_max: here: maximum length of short pause RCMM32_BIT_PULSE_LEN_MIN, // pulse_0_len_min: here: not used RCMM32_BIT_PULSE_LEN_MAX, // pulse_0_len_max: here: not used 0, // pause_0_len_min: here: not used 0, // pause_0_len_max: here: not used RCMM32_ADDRESS_OFFSET, // address_offset: address offset RCMM32_ADDRESS_OFFSET + RCMM32_ADDRESS_LEN, // address_end: end of address RCMM32_COMMAND_OFFSET, // command_offset: command offset RCMM32_COMMAND_OFFSET + RCMM32_COMMAND_LEN, // command_end: end of command RCMM32_COMPLETE_DATA_LEN, // complete_len: complete length of frame RCMM32_STOP_BIT, // stop_bit: flag: frame has stop bit RCMM32_LSB, // lsb_first: flag: LSB first RCMM32_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER pentax_param = { IRMP_PENTAX_PROTOCOL, // protocol: ir protocol PENTAX_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 PENTAX_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 PENTAX_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 PENTAX_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 PENTAX_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 PENTAX_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 PENTAX_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 PENTAX_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 PENTAX_ADDRESS_OFFSET, // address_offset: address offset PENTAX_ADDRESS_OFFSET + PENTAX_ADDRESS_LEN, // address_end: end of address PENTAX_COMMAND_OFFSET, // command_offset: command offset PENTAX_COMMAND_OFFSET + PENTAX_COMMAND_LEN, // command_end: end of command PENTAX_COMPLETE_DATA_LEN, // complete_len: complete length of frame PENTAX_STOP_BIT, // stop_bit: flag: frame has stop bit PENTAX_LSB, // lsb_first: flag: LSB first PENTAX_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_ACP24_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER acp24_param = { IRMP_ACP24_PROTOCOL, // protocol: ir protocol ACP24_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 ACP24_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 ACP24_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 ACP24_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 ACP24_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 ACP24_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 ACP24_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 ACP24_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 ACP24_ADDRESS_OFFSET, // address_offset: address offset ACP24_ADDRESS_OFFSET + ACP24_ADDRESS_LEN, // address_end: end of address ACP24_COMMAND_OFFSET, // command_offset: command offset ACP24_COMMAND_OFFSET + ACP24_COMMAND_LEN, // command_end: end of command ACP24_COMPLETE_DATA_LEN, // complete_len: complete length of frame ACP24_STOP_BIT, // stop_bit: flag: frame has stop bit ACP24_LSB, // lsb_first: flag: LSB first ACP24_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_METZ_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER metz_param = { IRMP_METZ_PROTOCOL, // protocol: ir protocol METZ_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 METZ_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 METZ_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 METZ_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 METZ_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 METZ_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 METZ_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 METZ_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 METZ_ADDRESS_OFFSET, // address_offset: address offset METZ_ADDRESS_OFFSET + METZ_ADDRESS_LEN, // address_end: end of address METZ_COMMAND_OFFSET, // command_offset: command offset METZ_COMMAND_OFFSET + METZ_COMMAND_LEN, // command_end: end of command METZ_COMPLETE_DATA_LEN, // complete_len: complete length of frame METZ_STOP_BIT, // stop_bit: flag: frame has stop bit METZ_LSB, // lsb_first: flag: LSB first METZ_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rf_gen24_param = { RF_GEN24_PROTOCOL, // protocol: ir protocol RF_GEN24_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RF_GEN24_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RF_GEN24_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RF_GEN24_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RF_GEN24_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RF_GEN24_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RF_GEN24_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RF_GEN24_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RF_GEN24_ADDRESS_OFFSET, // address_offset: address offset RF_GEN24_ADDRESS_OFFSET + RF_GEN24_ADDRESS_LEN, // address_end: end of address RF_GEN24_COMMAND_OFFSET, // command_offset: command offset RF_GEN24_COMMAND_OFFSET + RF_GEN24_COMMAND_LEN, // command_end: end of command RF_GEN24_COMPLETE_DATA_LEN, // complete_len: complete length of frame RF_GEN24_STOP_BIT, // stop_bit: flag: frame has stop bit RF_GEN24_LSB, // lsb_first: flag: LSB first RF_GEN24_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rf_x10_param = { RF_X10_PROTOCOL, // protocol: ir protocol RF_X10_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RF_X10_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RF_X10_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RF_X10_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RF_X10_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RF_X10_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RF_X10_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RF_X10_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RF_X10_ADDRESS_OFFSET, // address_offset: address offset RF_X10_ADDRESS_OFFSET + RF_X10_ADDRESS_LEN, // address_end: end of address RF_X10_COMMAND_OFFSET, // command_offset: command offset RF_X10_COMMAND_OFFSET + RF_X10_COMMAND_LEN, // command_end: end of command RF_X10_COMPLETE_DATA_LEN, // complete_len: complete length of frame RF_X10_STOP_BIT, // stop_bit: flag: frame has stop bit RF_X10_LSB, // lsb_first: flag: LSB first RF_X10_FLAGS // flags: some flags }; #endif #if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 static const PROGMEM IRMP_PARAMETER rf_medion_param = { RF_MEDION_PROTOCOL, // protocol: ir protocol RF_MEDION_1_PULSE_LEN_MIN, // pulse_1_len_min: minimum length of pulse with bit value 1 RF_MEDION_1_PULSE_LEN_MAX, // pulse_1_len_max: maximum length of pulse with bit value 1 RF_MEDION_1_PAUSE_LEN_MIN, // pause_1_len_min: minimum length of pause with bit value 1 RF_MEDION_1_PAUSE_LEN_MAX, // pause_1_len_max: maximum length of pause with bit value 1 RF_MEDION_0_PULSE_LEN_MIN, // pulse_0_len_min: minimum length of pulse with bit value 0 RF_MEDION_0_PULSE_LEN_MAX, // pulse_0_len_max: maximum length of pulse with bit value 0 RF_MEDION_0_PAUSE_LEN_MIN, // pause_0_len_min: minimum length of pause with bit value 0 RF_MEDION_0_PAUSE_LEN_MAX, // pause_0_len_max: maximum length of pause with bit value 0 RF_MEDION_ADDRESS_OFFSET, // address_offset: address offset RF_MEDION_ADDRESS_OFFSET + RF_MEDION_ADDRESS_LEN, // address_end: end of address RF_MEDION_COMMAND_OFFSET, // command_offset: command offset RF_MEDION_COMMAND_OFFSET + RF_MEDION_COMMAND_LEN, // command_end: end of command RF_MEDION_COMPLETE_DATA_LEN, // complete_len: complete length of frame RF_MEDION_STOP_BIT, // stop_bit: flag: frame has stop bit RF_MEDION_LSB, // lsb_first: flag: LSB first RF_MEDION_FLAGS // flags: some flags }; #endif static uint_fast8_t irmp_bit; // current bit position static IRMP_PARAMETER irmp_param; #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) static IRMP_PARAMETER irmp_param2; #endif static volatile uint_fast8_t irmp_ir_detected = FALSE; static volatile uint_fast8_t irmp_protocol; static volatile uint_fast16_t irmp_address; #if IRMP_32_BIT == 1 static uint_fast32_t irmp_command; #else static uint_fast16_t irmp_command; // removed volatile, because it is only used in irmp_get_data and therefore volatile makes no sense #endif static volatile uint_fast16_t irmp_id; // only used for SAMSUNG protocol static uint_fast8_t irmp_flags; // removed volatile, because it is only used in irmp_get_data and therefore volatile makes no sense // static volatile uint_fast8_t irmp_busy_flag; #if IRMP_AUTODETECT_REPEATRATE volatile uint_fast16_t delta_detection = 0; // interval between two detections in ticks volatile uint32_t pass_on_delta_detection = 0xFFFF; // interval between two detections in ticks volatile uint_fast16_t tmp_delta = 0xFFFF; volatile uint_fast8_t delta = 0; // interval between two detections in ms volatile uint_fast8_t min_delta = 170; // detected repeat rate, preset to greatest known repeat rate static volatile uint_fast8_t previous_irmp_protocol = 0; volatile uint_fast8_t same_key = 0; volatile uint_fast8_t keep_same_key = 0; volatile uint_fast8_t timeout = 1; volatile uint_fast8_t upper_border = 176; // repeatrate plus jitter (threshold for timeout) #endif #if defined(__MBED__) // DigitalIn inputPin(IRMP_PIN, PullUp); // this requires mbed.h and source to be compiled as cpp gpio_t gpioIRin; // use low level c function instead #endif #if defined(ANALYZE) #define input(x) (x) static uint_fast8_t IRMP_PIN; #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Initialize IRMP decoder * @details Configures IRMP input pin *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(ANALYZE) #if ! defined(ARDUINO) void irmp_init (void) { #if defined(PIC_CCS) || defined(PIC_C18) // PIC: do nothing #elif defined(PIC_XC32) # if defined(IRMP_ANSELBIT) IRMP_ANSELBIT = 0; # endif #elif defined (ARM_STM32_HAL) // STM32 with Hal Library: do nothing #elif defined (ARM_STM32) // STM32 GPIO_InitTypeDef GPIO_InitStructure; /* GPIOx clock enable */ # if defined (ARM_STM32L1XX) RCC_AHBPeriphClockCmd(IRMP_PORT_RCC, ENABLE); # elif defined (ARM_STM32F10X) RCC_APB2PeriphClockCmd(IRMP_PORT_RCC, ENABLE); # elif defined (ARM_STM32F30X) RCC_AHBPeriphClockCmd(IRMP_PORT_RCC, ENABLE); # elif defined (ARM_STM32F4XX) RCC_AHB1PeriphClockCmd(IRMP_PORT_RCC, ENABLE); # endif /* GPIO Configuration */ GPIO_InitStructure.GPIO_Pin = IRMP_BIT; # if defined (ARM_STM32L1XX) || defined (ARM_STM32F4XX) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; # elif defined (ARM_STM32F10X) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; # elif defined (ARM_STM32F30X) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; # endif GPIO_Init(IRMP_PORT, &GPIO_InitStructure); #elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3 /* GPIOx clock enable */ # if defined (STM32L1) || defined (STM32F1) || defined (STM32F3) || defined (STM32F4) rcc_periph_clock_enable(IRMP_PORT_RCC); # endif /* GPIO Configuration */ # if defined (STM32L1) || defined (STM32F4) || defined (STM32F3) gpio_mode_setup(IRMP_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, IRMP_BIT); gpio_set_output_options(IRMP_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRMP_BIT); # elif defined (STM32F1) gpio_set_mode(IRMP_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, IRMP_BIT); # endif #elif defined(STELLARIS_ARM_CORTEX_M4) // Enable the GPIO port ROM_SysCtlPeripheralEnable(IRMP_PORT_PERIPH); // Set as an input ROM_GPIODirModeSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_DIR_MODE_IN); ROM_GPIOPadConfigSet(IRMP_PORT_BASE, IRMP_PORT_PIN, GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU); #elif defined(__SDCC_stm8) // STM8 IRMP_GPIO_STRUCT->DDR &= ~(1<CR1 |= (1<> 8) == (~irmp_command & 0x00FF)) { irmp_command &= 0xff; // irmp_command |= irmp_id << 8; // for samsung32 irmp_id looks to be the same as irmp_command tReturnCode = TRUE; } break; # if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 case IRMP_SAMSUNG48_PROTOCOL: irmp_command = (irmp_command & 0x00FF) | ((irmp_id & 0x00FF) << 8); tReturnCode = TRUE; break; # endif #endif #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 case IRMP_SIRCS_PROTOCOL: // Concatenate high byte of command and low byte of address irmp_address <<= 7; irmp_address = irmp_address | irmp_command >> 8; // Command is 7 bytes, so add the 8.th bit of command to address irmp_address <<= 1; if ((irmp_command & 0x80)) { irmp_address++; } irmp_command &= 0x7F; tReturnCode = TRUE; break; #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 case IRMP_NEC_PROTOCOL: if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) { if ((irmp_address >> 8) == (~irmp_address & 0x00FF)) { irmp_address &= 0xff; } irmp_command &= 0xff; } else if (irmp_address == 0x87EE) { ANALYZE_PRINTF1 ("APPLE protocol detected\n"); irmp_protocol = IRMP_APPLE_PROTOCOL; irmp_address = (irmp_command & 0xFF00) >> 8; // address was received in command! irmp_command &= 0x00FF; } else { ANALYZE_PRINTF1 ("ONKYO protocol detected\n"); irmp_protocol = IRMP_ONKYO_PROTOCOL; } tReturnCode = TRUE; break; #endif #if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 case IRMP_VINCENT_PROTOCOL: if ((irmp_command >> 8) == (irmp_command & 0x00FF)) { irmp_command &= 0xff; tReturnCode = TRUE; } break; #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 case IRMP_KASEIKYO_PROTOCOL: /* * Todo AJ 14.7.22 The bit before the command (not existent bit 16 of command) is skipped and I have a Panasonic remote where it is 1 for 2 buttons * and the 4 LSB command bits are always zero for this remote */ if( irmp_address == 0x2002) // PANASONIC_VENDOR_ID_CODE { ANALYZE_PRINTF1 ("Kaseikyo_Panasonic protocol detected\n"); irmp_protocol = IRMP_PANASONIC_PROTOCOL; irmp_command = irmp_command >> 4; // remove the 4 zero bits irmp_address = (irmp_command & 0xF00) >> 8; // LSB address (genre1) was received in command! irmp_address |= irmp_flags & 0xF0; // MSB of address(genre2 bits) are located in MSB of the flag byte irmp_command &= 0x00FF; } tReturnCode = TRUE; break; #endif #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 case IRMP_BOSE_PROTOCOL: if ((irmp_command >> 8) == (~irmp_command & 0x00FF)) { irmp_command &= 0xff; tReturnCode = TRUE; } break; #endif #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 case IRMP_MERLIN_PROTOCOL: if (irmp_bit == 10) { tReturnCode = TRUE; } else if (irmp_bit >= 19 && ((irmp_bit - 3) % 8 == 0)) { if (((irmp_command >> 1) & 1) != (irmp_command & 1)) { irmp_command >>= 1; irmp_command |= ((irmp_address & 1) << (irmp_bit - 12)); irmp_address >>= 1; tReturnCode = TRUE; } } break; #endif #if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 case IRMP_SIEMENS_PROTOCOL: case IRMP_RUWIDO_PROTOCOL: if (((irmp_command >> 1) & 0x0001) == (~irmp_command & 0x0001)) { irmp_command >>= 1; tReturnCode = TRUE; } break; #endif #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 case IRMP_KATHREIN_PROTOCOL: if (irmp_command != 0x0000) { tReturnCode = TRUE; } break; #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 case IRMP_RC5_PROTOCOL: irmp_address &= ~0x20; // clear toggle bit tReturnCode = TRUE; break; #endif #if IRMP_SUPPORT_S100_PROTOCOL == 1 case IRMP_S100_PROTOCOL: irmp_address &= ~0x20; // clear toggle bit tReturnCode = TRUE; break; #endif #if IRMP_SUPPORT_IR60_PROTOCOL == 1 case IRMP_IR60_PROTOCOL: if (irmp_command != 0x007d) // 0x007d (== 62<<1 + 1) is start instruction frame { tReturnCode = TRUE; } else { ANALYZE_PRINTF1("Info IR60: got start instruction frame\n"); } break; #endif #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 case IRMP_RCCAR_PROTOCOL: // frame in irmp_data: // Bit 12 11 10 9 8 7 6 5 4 3 2 1 0 // V D7 D6 D5 D4 D3 D2 D1 D0 A1 A0 C1 C0 // 10 9 8 7 6 5 4 3 2 1 0 irmp_address = (irmp_command & 0x000C) >> 2; // addr: 0 0 0 0 0 0 0 0 0 A1 A0 irmp_command = ((irmp_command & 0x1000) >> 2) | // V-Bit: V 0 0 0 0 0 0 0 0 0 0 ((irmp_command & 0x0003) << 8) | // C-Bits: 0 C1 C0 0 0 0 0 0 0 0 0 ((irmp_command & 0x0FF0) >> 4); // D-Bits: D7 D6 D5 D4 D3 D2 D1 D0 tReturnCode = TRUE; // Summe: V C1 C0 D7 D6 D5 D4 D3 D2 D1 D0 break; #endif #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 // squeeze code to 8 bit, upper bit indicates release-key case IRMP_NETBOX_PROTOCOL: if (irmp_command & 0x1000) // last bit set? { if ((irmp_command & 0x1f) == 0x15) // key pressed: 101 01 (LSB) { irmp_command >>= 5; irmp_command &= 0x7F; tReturnCode = TRUE; } else if ((irmp_command & 0x1f) == 0x10) // key released: 000 01 (LSB) { irmp_command >>= 5; irmp_command |= 0x80; tReturnCode = TRUE; } else { ANALYZE_PRINTF1("error NETBOX: bit6/7 must be 0/1\n"); } } else { ANALYZE_PRINTF1("error NETBOX: last bit not set\n"); } break; #endif #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 case IRMP_LEGO_PROTOCOL: { uint_fast8_t crc = 0x0F ^ ((irmp_command & 0xF000) >> 12) ^ ((irmp_command & 0x0F00) >> 8) ^ ((irmp_command & 0x00F0) >> 4); if ((irmp_command & 0x000F) == crc) { irmp_command >>= 4; tReturnCode = TRUE; } else { ANALYZE_PRINTF1 ("CRC error in LEGO protocol\n"); // rtc = TRUE; // don't accept codes with CRC errors } break; } #endif #if IRMP_SUPPORT_METZ_PROTOCOL == 1 case IRMP_METZ_PROTOCOL: irmp_address &= ~0x40; // clear toggle bit if (((~irmp_address) & 0x07) == (irmp_address >> 3) && ((~irmp_command) & 0x3f) == (irmp_command >> 6)) { irmp_address >>= 3; irmp_command >>= 6; tReturnCode = TRUE; } break; #endif #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 || IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 case RF_X10_PROTOCOL: case RF_MEDION_PROTOCOL: { uint8_t channel; uint8_t checksum; channel = irmp_command & 0x0F; // lower nibble: RF channel 0-15 irmp_command >>= 4; // shift out channel checksum = irmp_address; // get checksum if (((irmp_command + (0x0055 + (channel << 4))) & 0x7F) == checksum) { // checksum correct? irmp_address = channel + 1; // set address to channel + 1 tReturnCode = TRUE; } break; } #endif default: { tReturnCode = TRUE; break; } } if (tReturnCode) { irmp_data_p->protocol = irmp_protocol; irmp_data_p->address = irmp_address; irmp_data_p->command = irmp_command; #if IRMP_AUTODETECT_REPEATRATE tmp_delta = (pass_on_delta_detection * (1000000 / F_INTERRUPTS)) / 1000; // ms, this division is not precise if (tmp_delta > 0xFF ) // reduce to uint8_t delta = 0xFF; else delta = tmp_delta; if (irmp_protocol != previous_irmp_protocol) { // reset min_delta = 170; upper_border = min_delta * (100 + JITTER_COMPENSATION) / 100 + 1; timeout = 1; keep_same_key = 0; previous_irmp_protocol = irmp_protocol; } else { if (!(irmp_protocol == IRMP_NEC_PROTOCOL && delta < 75)) { // if NEC, ignore first short interval if (delta < min_delta && same_key) min_delta = delta; } upper_border = min_delta * (100 + JITTER_COMPENSATION) / 100 + 1; timeout = (delta >= upper_border); if (irmp_protocol == IRMP_RC5_PROTOCOL || irmp_protocol == IRMP_RC6_PROTOCOL || irmp_protocol == IRMP_RC6A_PROTOCOL || irmp_protocol == IRMP_RECS80_PROTOCOL \ || irmp_protocol == IRMP_RECS80EXT_PROTOCOL || irmp_protocol == IRMP_RCMM24_PROTOCOL || irmp_protocol == IRMP_RCMM32_PROTOCOL \ || irmp_protocol == IRMP_THOMSON_PROTOCOL || irmp_protocol == IRMP_S100_PROTOCOL || irmp_protocol == IRMP_METZ_PROTOCOL) { if (same_key) // same_key is false, if toggle; not using timeout helps detecting repeats after misdetection and timeout isn't needed for discerning repetition irmp_flags |= IRMP_FLAG_REPETITION; } else { if (same_key && !timeout) irmp_flags |= IRMP_FLAG_REPETITION; } keep_same_key = same_key; same_key = 0; } #endif irmp_data_p->flags = irmp_flags; } else { irmp_protocol = IRMP_UNKNOWN_PROTOCOL; } irmp_command = 0; // don't reset irmp_protocol here, needed for detection of NEC & JVC repetition frames! irmp_address = 0; irmp_flags = 0; irmp_ir_detected = FALSE; } return tReturnCode; } #if IRMP_USE_CALLBACK == 1 void irmp_set_callback_ptr (void (*cb)(uint_fast8_t)) { irmp_callback_ptr = cb; } #endif // IRMP_USE_CALLBACK == 1 // these statics must not be volatile, because they are only used by irmp_store_bit(), which is called by irmp_ISR() static uint_fast16_t irmp_tmp_address; // ir address #if IRMP_32_BIT == 1 static uint_fast32_t irmp_tmp_command; // ir command #else static uint_fast16_t irmp_tmp_command; // ir command #endif #if (IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1)) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 static uint_fast16_t irmp_tmp_address2; // ir address static uint_fast16_t irmp_tmp_command2; // ir command #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 static uint_fast16_t irmp_lgair_address; // ir address static uint_fast16_t irmp_lgair_command; // ir command #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 static uint_fast16_t irmp_melinera_command; // ir command #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 static uint_fast16_t irmp_tmp_id; // ir id (only SAMSUNG) #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 static uint8_t xor_check[6]; // check kaseikyo "parity" bits static uint_fast8_t genre2; // save genre2 bits here, later copied to MSB in flags #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 static uint_fast8_t parity; // number of '1' of the first 14 bits, check if even. #endif #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 static uint_fast8_t check; // number of '1' of the first 14 bits, check if even. static uint_fast8_t mitsu_parity; // number of '1' of the first 14 bits, check if even. #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * store bit * @details store bit in temp address or temp command * @param value to store: 0 or 1 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // verhindert, dass irmp_store_bit() inline compiliert wird: // static void irmp_store_bit (uint_fast8_t) __attribute__ ((noinline)); static void irmp_store_bit (uint_fast8_t value) { #if IRMP_SUPPORT_ACP24_PROTOCOL == 1 if (irmp_param.protocol == IRMP_ACP24_PROTOCOL) // squeeze 64 bits into 16 bits: { if (value) { // ACP24-Frame: // 1 2 3 4 5 6 // 0123456789012345678901234567890123456789012345678901234567890123456789 // N VVMMM ? ??? t vmA x y TTTT // // irmp_data_p->command: // // 5432109876543210 // NAVVvMMMmtxyTTTT switch (irmp_bit) { case 0: irmp_tmp_command |= (1<<15); break; // N case 2: irmp_tmp_command |= (1<<13); break; // V case 3: irmp_tmp_command |= (1<<12); break; // V case 4: irmp_tmp_command |= (1<<10); break; // M case 5: irmp_tmp_command |= (1<< 9); break; // M case 6: irmp_tmp_command |= (1<< 8); break; // M case 20: irmp_tmp_command |= (1<< 6); break; // t case 22: irmp_tmp_command |= (1<<11); break; // v case 23: irmp_tmp_command |= (1<< 7); break; // m case 24: irmp_tmp_command |= (1<<14); break; // A case 26: irmp_tmp_command |= (1<< 5); break; // x case 44: irmp_tmp_command |= (1<< 4); break; // y case 66: irmp_tmp_command |= (1<< 3); break; // T case 67: irmp_tmp_command |= (1<< 2); break; // T case 68: irmp_tmp_command |= (1<< 1); break; // T case 69: irmp_tmp_command |= (1<< 0); break; // T } } } else #endif // IRMP_SUPPORT_ACP24_PROTOCOL #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL) { if (irmp_bit < 14) { if (value) { parity++; } } else if (irmp_bit == 14) { if (value) // value == 1: even parity { if (parity & 0x01) { parity = PARITY_CHECK_FAILED; } else { parity = PARITY_CHECK_OK; } } else { if (parity & 0x01) // value == 0: odd parity { parity = PARITY_CHECK_OK; } else { parity = PARITY_CHECK_FAILED; } } } } else #endif { ; } #if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 if (irmp_bit == 0 && irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL) { first_bit = value; } else #endif if (irmp_bit >= irmp_param.address_offset && irmp_bit < irmp_param.address_end) { if (irmp_param.lsb_first) { irmp_tmp_address |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.address_offset)); // CV wants cast } else { irmp_tmp_address <<= 1; irmp_tmp_address |= value; } } else if (irmp_bit >= irmp_param.command_offset && irmp_bit < irmp_param.command_end) { if (irmp_param.lsb_first) { #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit >= 32) { irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - 32)); // CV wants cast } else #endif { irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - irmp_param.command_offset)); // CV wants cast } } else { irmp_tmp_command <<= 1; irmp_tmp_command |= value; } } #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL) { if (irmp_bit < 8) { irmp_lgair_address <<= 1; // LGAIR uses MSB irmp_lgair_address |= value; } else if (irmp_bit < 24) { irmp_lgair_command <<= 1; // LGAIR uses MSB irmp_lgair_command |= value; } } // NO else! #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL || irmp_param.protocol == IRMP_MELINERA_PROTOCOL) { irmp_melinera_command <<= 1; // MELINERA uses MSB irmp_melinera_command |= value; } #endif #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit >= 13 && irmp_bit < 26) { irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit - 13)); // CV wants cast } else #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit >= SAMSUNG_ID_OFFSET && irmp_bit < SAMSUNG_ID_OFFSET + SAMSUNG_ID_LEN) { irmp_tmp_id |= (((uint_fast16_t) (value)) << (irmp_bit - SAMSUNG_ID_OFFSET)); // store with LSB first } else #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) { if (irmp_bit >= 20 && irmp_bit < 24) { irmp_tmp_command |= (((uint_fast16_t) (value)) << (irmp_bit - 8)); // store 4 system bits (genre 1) in upper nibble with LSB first } else if (irmp_bit >= 24 && irmp_bit < 28) { genre2 |= (((uint_fast8_t) (value)) << (irmp_bit - 20)); // store 4 system bits (genre 2) in upper nibble with LSB first } if (irmp_bit < KASEIKYO_COMPLETE_DATA_LEN) { if (value) { xor_check[irmp_bit / 8] |= 1 << (irmp_bit % 8); } else { xor_check[irmp_bit / 8] &= ~(1 << (irmp_bit % 8)); } } } else #endif #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL) // squeeze 64 bits into 16 bits: { if (irmp_bit == 72 ) { // irmp_tmp_address, irmp_tmp_command received: check parity & compress mitsu_parity = PARITY_CHECK_OK; check = irmp_tmp_address >> 8; // inverted upper byte == lower byte? check = ~ check; if (check == (irmp_tmp_address & 0xFF)) { // ok: irmp_tmp_address <<= 8; // throw away upper byte } else { mitsu_parity = PARITY_CHECK_FAILED; } check = irmp_tmp_command >> 8; // inverted upper byte == lower byte? check = ~ check; if (check == (irmp_tmp_command & 0xFF)) { // ok: pack together irmp_tmp_address |= irmp_tmp_command & 0xFF; // byte 1, byte2 in irmp_tmp_address, irmp_tmp_command can be used for byte 3 } else { mitsu_parity = PARITY_CHECK_FAILED; } irmp_tmp_command = 0; } if (irmp_bit >= 72 ) { // receive 3. word in irmp_tmp_command irmp_tmp_command <<= 1; irmp_tmp_command |= value; } } else #endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL { ; } irmp_bit++; } /*--------------------------------------------------------------------------------------------------------------------------------------------------- * store bit * @details store bit in temp address or temp command * @param value to store: 0 or 1 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) static void irmp_store_bit2 (uint_fast8_t value) { uint_fast8_t irmp_bit2; if (irmp_param.protocol) { irmp_bit2 = irmp_bit - 2; } else { irmp_bit2 = irmp_bit - 1; } if (irmp_bit2 >= irmp_param2.address_offset && irmp_bit2 < irmp_param2.address_end) { irmp_tmp_address2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.address_offset)); // CV wants cast } else if (irmp_bit2 >= irmp_param2.command_offset && irmp_bit2 < irmp_param2.command_end) { irmp_tmp_command2 |= (((uint_fast16_t) (value)) << (irmp_bit2 - irmp_param2.command_offset)); // CV wants cast } } #endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) #if defined(ANALYZE) static uint32_t s_curSample = 0; static uint32_t s_startBitSample = 0; #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ISR routine * @details ISR routine, called 10000 to 20000 times per second *--------------------------------------------------------------------------------------------------------------------------------------------------- */ static uint_fast8_t irmp_start_bit_detected; // flag: start bit detected static uint_fast8_t wait_for_space; // flag: wait for data bit space static uint_fast8_t wait_for_start_space; // flag: wait for start bit space #if __SIZEOF_INT__ == 4 static uint_fast16_t irmp_pulse_time; // count bit time for pulse #else static uint_fast8_t irmp_pulse_time; // count bit time for pulse #endif static PAUSE_LEN irmp_pause_time; // count bit time for pause static uint_fast16_t key_repetition_len; // SIRCS repeats frame 2-5 times with 45 ms pause static uint_fast8_t repetition_frame_number; #if defined(ARDUINO) #include "irmpArduinoExt.hpp" // Must be included after declaration of irmp_start_bit_detected etc. #endif /* * 4 us idle, 45 us at start of each pulse @16 MHz ATmega 328p */ #if defined(ESP8266) || defined(ESP32) bool IRAM_ATTR irmp_ISR(void) #else # ifdef __cplusplus bool irmp_ISR(void) # else uint_fast8_t irmp_ISR(void) # endif #endif { static uint_fast16_t last_irmp_address = 0xFFFF; // save last irmp address to recognize key repetition #if IRMP_ENABLE_RELEASE_DETECTION == 1 static uint_fast8_t key_released = TRUE; #endif #if IRMP_32_BIT == 1 static uint_fast32_t last_irmp_command = 0xFFFFFFFF; // save last irmp command to recognize key repetition #else static uint_fast16_t last_irmp_command = 0xFFFF; // save last irmp command to recognize key repetition #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 static uint_fast16_t last_irmp_denon_command; // save last irmp command to recognize DENON frame repetition static uint_fast16_t denon_repetition_len = 0xFFFF; // denon repetition len of 2nd auto generated frame #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1 static uint_fast8_t rc5_cmd_bit6; // bit 6 of RC5 command is the inverted 2nd start bit #endif #if IRMP_SUPPORT_MANCHESTER == 1 static PAUSE_LEN last_pause; // last pause value #endif #if IRMP_SUPPORT_MANCHESTER == 1 || IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 static uint_fast8_t last_value; // last bit value #endif #if IRMP_SUPPORT_RCII_PROTOCOL == 1 static uint_fast8_t waiting_for_2nd_pulse = 0; #endif #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 uint_fast8_t bit_0 = 0; #endif uint_fast8_t irmp_input; // input value #if defined(ANALYZE) time_counter++; #endif // ANALYZE #if IRMP_HIGH_ACTIVE == 1 irmp_input = ! input(IRMP_PIN); #else irmp_input = input(IRMP_PIN); #endif #if IRMP_USE_CALLBACK == 1 if (irmp_callback_ptr) { static uint_fast8_t last_inverted_input; if (last_inverted_input != !irmp_input) { (*irmp_callback_ptr) (! irmp_input); last_inverted_input = !irmp_input; } } #endif // IRMP_USE_CALLBACK == 1 #if defined(ARDUINO) # if !defined(NO_LED_FEEDBACK_CODE) irmp_DoLEDFeedback(irmp_input); # endif #endif irmp_log(irmp_input); // log ir signal, if IRMP_LOGGING defined #if IRMP_AUTODETECT_REPEATRATE if (delta_detection < 0xFFFF) delta_detection++; #if IRMP_ENABLE_RELEASE_DETECTION == 1 if (! key_released && delta_detection * (1000000 / F_INTERRUPTS) / 1000 >= upper_border) { irmp_address = last_irmp_address; irmp_command = last_irmp_command; irmp_flags = IRMP_FLAG_RELEASE; irmp_ir_detected = TRUE; key_released = TRUE; } #endif #endif if (! irmp_ir_detected) // ir code already detected? { // no... if (! irmp_start_bit_detected) // start bit detected? { // no... if (! irmp_input) // receiving burst? { // yes... // irmp_busy_flag = TRUE; #if defined(ANALYZE) if (! irmp_pulse_time) { s_startBitSample = s_curSample; ANALYZE_PRINTF2("%8.3fms [starting pulse]\n", (double) (time_counter * 1000) / F_INTERRUPTS); } #endif // ANALYZE irmp_pulse_time++; // increment counter } else { // no... if (irmp_pulse_time) // it's dark.... { // set flags for counting the time of darkness... irmp_start_bit_detected = 1; wait_for_start_space = 1; wait_for_space = 0; irmp_tmp_command = 0; irmp_tmp_address = 0; #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 genre2 = 0; #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 irmp_tmp_id = 0; #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) || IRMP_SUPPORT_NEC42_PROTOCOL == 1 irmp_tmp_command2 = 0; irmp_tmp_address2 = 0; #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 irmp_lgair_command = 0; irmp_lgair_address = 0; #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 irmp_melinera_command = 0; #endif irmp_bit = 0xff; irmp_pause_time = 1; // 1st pause: set to 1, not to 0! #if IRMP_SUPPORT_RC5_PROTOCOL == 1 || IRMP_SUPPORT_S100_PROTOCOL == 1 rc5_cmd_bit6 = 0; // fm 2010-03-07: bugfix: reset it after incomplete RC5 frame! #endif } else { if (key_repetition_len < 0xFFFF) // avoid overflow of counter { key_repetition_len++; #if IRMP_ENABLE_RELEASE_DETECTION == 1 #if !IRMP_AUTODETECT_REPEATRATE if (! key_released && key_repetition_len > IRMP_KEY_RELEASE_LEN) { irmp_address = last_irmp_address; irmp_command = last_irmp_command; irmp_flags = IRMP_FLAG_RELEASE; irmp_ir_detected = TRUE; key_released = TRUE; } #endif #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 if (denon_repetition_len < 0xFFFF) // avoid overflow of counter { denon_repetition_len++; if (denon_repetition_len >= DENON_AUTO_REPETITION_PAUSE_LEN && last_irmp_denon_command != 0) { ANALYZE_PRINTF2 ("%8.3fms warning: did not receive inverted command repetition\n", (double) (time_counter * 1000) / F_INTERRUPTS); last_irmp_denon_command = 0; denon_repetition_len = 0xFFFF; } } #endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 } } } } else { if (wait_for_start_space) // we have received start bit... { // ...and are counting the time of darkness if (irmp_input) // still dark? { // yes irmp_pause_time++; // increment counter #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 if (((irmp_pulse_time < NIKON_START_BIT_PULSE_LEN_MIN || irmp_pulse_time > NIKON_START_BIT_PULSE_LEN_MAX) && irmp_pause_time > IRMP_TIMEOUT_LEN) || irmp_pause_time > IRMP_TIMEOUT_NIKON_LEN) #else if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? #endif { // yes... #if IRMP_SUPPORT_JVC_PROTOCOL == 1 if (irmp_protocol == IRMP_JVC_PROTOCOL) // don't show eror if JVC protocol, irmp_pulse_time has been set below! { ; } else #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 { ANALYZE_PRINTF4 ("%8.3fms error 1: pause after start bit pulse %d too long: %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); } irmp_start_bit_detected = 0; // reset flags, let's wait for another start bit irmp_pulse_time = 0; irmp_pause_time = 0; } } else { // receiving first data pulse! IRMP_PARAMETER * irmp_param_p; irmp_param_p = (IRMP_PARAMETER *) 0; irmp_bit = 0; #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) irmp_param2.protocol = 0; #endif ANALYZE_PRINTF4 ("%8.3fms [start-bit: pulse = %2d, pause = %2d]\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_pulse_time, irmp_pause_time); #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 if (irmp_pulse_time >= SIRCS_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIRCS_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= SIRCS_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIRCS_START_BIT_PAUSE_LEN_MAX) { // it's SIRCS ANALYZE_PRINTF5 ("protocol = SIRCS, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", SIRCS_START_BIT_PULSE_LEN_MIN, SIRCS_START_BIT_PULSE_LEN_MAX, SIRCS_START_BIT_PAUSE_LEN_MIN, SIRCS_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &sircs_param; } else #endif // IRMP_SUPPORT_SIRCS_PROTOCOL == 1 #if IRMP_SUPPORT_JVC_PROTOCOL == 1 if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame irmp_pulse_time >= JVC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= JVC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= JVC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= JVC_REPEAT_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = NEC or JVC (type 1) repeat frame, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", JVC_START_BIT_PULSE_LEN_MIN, JVC_START_BIT_PULSE_LEN_MAX, JVC_REPEAT_START_BIT_PAUSE_LEN_MIN, JVC_REPEAT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec_param; } else #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 #if IRMP_SUPPORT_NEC_PROTOCOL == 1 if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) { #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 ANALYZE_PRINTF5 ("protocol = NEC42, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec42_param; #else ANALYZE_PRINTF5 ("protocol = NEC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_START_BIT_PAUSE_LEN_MIN, NEC_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec_param; #endif } else if (irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NEC_REPEAT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_REPEAT_START_BIT_PAUSE_LEN_MAX) { // it's NEC #if IRMP_SUPPORT_JVC_PROTOCOL == 1 if (irmp_protocol == IRMP_JVC_PROTOCOL) // last protocol was JVC, awaiting repeat frame { // some jvc remote controls use nec repetition frame for jvc repetition frame ANALYZE_PRINTF5 ("protocol = JVC repeat frame type 2, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec_param; } else #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 { ANALYZE_PRINTF5 ("protocol = NEC (repetition frame), start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_REPEAT_START_BIT_PAUSE_LEN_MIN, NEC_REPEAT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec_rep_param; } } else #if IRMP_SUPPORT_JVC_PROTOCOL == 1 if (irmp_protocol == IRMP_JVC_PROTOCOL && // last protocol was JVC, awaiting repeat frame irmp_pulse_time >= NEC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NEC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NEC_0_PAUSE_LEN_MIN && irmp_pause_time <= NEC_0_PAUSE_LEN_MAX) { // it's JVC repetition type 3 ANALYZE_PRINTF5 ("protocol = JVC repeat frame type 3, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NEC_START_BIT_PULSE_LEN_MIN, NEC_START_BIT_PULSE_LEN_MAX, NEC_0_PAUSE_LEN_MIN, NEC_0_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nec_param; } else #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 #endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 if (irmp_pulse_time >= TELEFUNKEN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= TELEFUNKEN_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= TELEFUNKEN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= TELEFUNKEN_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = TELEFUNKEN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", TELEFUNKEN_START_BIT_PULSE_LEN_MIN, TELEFUNKEN_START_BIT_PULSE_LEN_MAX, TELEFUNKEN_START_BIT_PAUSE_LEN_MIN, TELEFUNKEN_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &telefunken_param; } else #endif // IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 #if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 if (irmp_pulse_time >= ROOMBA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= ROOMBA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ROOMBA_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = ROOMBA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", ROOMBA_START_BIT_PULSE_LEN_MIN, ROOMBA_START_BIT_PULSE_LEN_MAX, ROOMBA_START_BIT_PAUSE_LEN_MIN, ROOMBA_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &roomba_param; } else #endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 #if IRMP_SUPPORT_ACP24_PROTOCOL == 1 if (irmp_pulse_time >= ACP24_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ACP24_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= ACP24_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ACP24_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = ACP24, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", ACP24_START_BIT_PULSE_LEN_MIN, ACP24_START_BIT_PULSE_LEN_MAX, ACP24_START_BIT_PAUSE_LEN_MIN, ACP24_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &acp24_param; } else #endif // IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 #if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 if (irmp_pulse_time >= PENTAX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PENTAX_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= PENTAX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PENTAX_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = PENTAX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", PENTAX_START_BIT_PULSE_LEN_MIN, PENTAX_START_BIT_PULSE_LEN_MAX, PENTAX_START_BIT_PAUSE_LEN_MIN, PENTAX_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &pentax_param; } else #endif // IRMP_SUPPORT_PENTAX_PROTOCOL == 1 #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 if (irmp_pulse_time >= NIKON_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NIKON_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NIKON_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NIKON_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = NIKON, start bit timings: pulse: %3d - %3d, pause: %3u - %3u\n", NIKON_START_BIT_PULSE_LEN_MIN, NIKON_START_BIT_PULSE_LEN_MAX, (unsigned int) NIKON_START_BIT_PAUSE_LEN_MIN, (unsigned int) NIKON_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nikon_param; } else #endif // IRMP_SUPPORT_NIKON_PROTOCOL == 1 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 if (irmp_pulse_time >= SAMSUNG_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) { // it's SAMSUNG ANALYZE_PRINTF5 ("protocol = SAMSUNG, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", SAMSUNG_START_BIT_PULSE_LEN_MIN, SAMSUNG_START_BIT_PULSE_LEN_MAX, SAMSUNG_START_BIT_PAUSE_LEN_MIN, SAMSUNG_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &samsung_param; } else #endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 if (irmp_pulse_time >= SAMSUNGAH_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNGAH_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= SAMSUNGAH_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNGAH_START_BIT_PAUSE_LEN_MAX) { // it's SAMSUNGAH ANALYZE_PRINTF5 ("protocol = SAMSUNGAH, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", SAMSUNGAH_START_BIT_PULSE_LEN_MIN, SAMSUNGAH_START_BIT_PULSE_LEN_MAX, SAMSUNGAH_START_BIT_PAUSE_LEN_MIN, SAMSUNGAH_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &samsungah_param; } else #endif // IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 if (irmp_pulse_time >= MATSUSHITA_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MATSUSHITA_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= MATSUSHITA_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MATSUSHITA_START_BIT_PAUSE_LEN_MAX) { // it's MATSUSHITA ANALYZE_PRINTF5 ("protocol = MATSUSHITA, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", MATSUSHITA_START_BIT_PULSE_LEN_MIN, MATSUSHITA_START_BIT_PULSE_LEN_MAX, MATSUSHITA_START_BIT_PAUSE_LEN_MIN, MATSUSHITA_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &matsushita_param; } else #endif // IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 if (irmp_pulse_time >= KASEIKYO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KASEIKYO_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= KASEIKYO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KASEIKYO_START_BIT_PAUSE_LEN_MAX) { // it's KASEIKYO ANALYZE_PRINTF5 ("protocol = KASEIKYO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", KASEIKYO_START_BIT_PULSE_LEN_MIN, KASEIKYO_START_BIT_PULSE_LEN_MAX, KASEIKYO_START_BIT_PAUSE_LEN_MIN, KASEIKYO_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &kaseikyo_param; } else #endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 #if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 if (irmp_pulse_time >= PANASONIC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= PANASONIC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= PANASONIC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= PANASONIC_START_BIT_PAUSE_LEN_MAX) { // it's PANASONIC ANALYZE_PRINTF5 ("protocol = PANASONIC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", PANASONIC_START_BIT_PULSE_LEN_MIN, PANASONIC_START_BIT_PULSE_LEN_MAX, PANASONIC_START_BIT_PAUSE_LEN_MIN, PANASONIC_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &panasonic_param; } else #endif // IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 if (irmp_pulse_time >= MITSU_HEAVY_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MITSU_HEAVY_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX) { // it's MITSU_HEAVY ANALYZE_PRINTF5 ("protocol = MITSU_HEAVY, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", MITSU_HEAVY_START_BIT_PULSE_LEN_MIN, MITSU_HEAVY_START_BIT_PULSE_LEN_MAX, MITSU_HEAVY_START_BIT_PAUSE_LEN_MIN, MITSU_HEAVY_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &mitsu_heavy_param; } else #endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 #if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 if (irmp_pulse_time >= VINCENT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= VINCENT_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= VINCENT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= VINCENT_START_BIT_PAUSE_LEN_MAX) { // it's VINCENT ANALYZE_PRINTF5 ("protocol = VINCENT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", VINCENT_START_BIT_PULSE_LEN_MIN, VINCENT_START_BIT_PULSE_LEN_MAX, VINCENT_START_BIT_PAUSE_LEN_MIN, VINCENT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &vincent_param; } else #endif // IRMP_SUPPORT_VINCENT_PROTOCOL == 1 #if IRMP_SUPPORT_METZ_PROTOCOL == 1 if (irmp_pulse_time >= METZ_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= METZ_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= METZ_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= METZ_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = METZ, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", METZ_START_BIT_PULSE_LEN_MIN, METZ_START_BIT_PULSE_LEN_MAX, METZ_START_BIT_PAUSE_LEN_MIN, METZ_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &metz_param; } else #endif // IRMP_SUPPORT_METZ_PROTOCOL == 1 #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 // RF_GEN24 has no start bit if (irmp_pulse_time >= RF_GEN24_0_PULSE_LEN_MIN && irmp_pulse_time <= RF_GEN24_0_PULSE_LEN_MAX && irmp_pause_time >= RF_GEN24_0_PAUSE_LEN_MIN && irmp_pause_time <= RF_GEN24_0_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("protocol = RF_GEN24\n"); irmp_param_p = (IRMP_PARAMETER *) &rf_gen24_param; bit_0 = 0; } else if (irmp_pulse_time >= RF_GEN24_1_PULSE_LEN_MIN && irmp_pulse_time <= RF_GEN24_1_PULSE_LEN_MAX && irmp_pause_time >= RF_GEN24_1_PAUSE_LEN_MIN && irmp_pause_time <= RF_GEN24_1_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("protocol = RF_GEN24\n"); irmp_param_p = (IRMP_PARAMETER *) &rf_gen24_param; bit_0 = 1; } else #endif // IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 if (irmp_pulse_time >= RF_X10_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RF_X10_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RF_X10_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RF_X10_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = RF_X10, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RF_X10_START_BIT_PULSE_LEN_MIN, RF_X10_START_BIT_PULSE_LEN_MAX, RF_X10_START_BIT_PAUSE_LEN_MIN, RF_X10_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &rf_x10_param; } else #endif // IRMP_SUPPORT_RF_X10_PROTOCOL == 1 #if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 if (irmp_pulse_time >= RF_MEDION_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RF_MEDION_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RF_MEDION_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RF_MEDION_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = RF_MEDION, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RF_MEDION_START_BIT_PULSE_LEN_MIN, RF_MEDION_START_BIT_PULSE_LEN_MAX, RF_MEDION_START_BIT_PAUSE_LEN_MIN, RF_MEDION_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &rf_medion_param; } else #endif // IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 #if IRMP_SUPPORT_RECS80_PROTOCOL == 1 if (irmp_pulse_time >= RECS80_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RECS80_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80_START_BIT_PAUSE_LEN_MAX) { // it's RECS80 ANALYZE_PRINTF5 ("protocol = RECS80, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RECS80_START_BIT_PULSE_LEN_MIN, RECS80_START_BIT_PULSE_LEN_MAX, RECS80_START_BIT_PAUSE_LEN_MIN, RECS80_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &recs80_param; } else #endif // IRMP_SUPPORT_RECS80_PROTOCOL == 1 #if IRMP_SUPPORT_S100_PROTOCOL == 1 if (((irmp_pulse_time >= S100_START_BIT_LEN_MIN && irmp_pulse_time <= S100_START_BIT_LEN_MAX) || (irmp_pulse_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX)) && ((irmp_pause_time >= S100_START_BIT_LEN_MIN && irmp_pause_time <= S100_START_BIT_LEN_MAX) || (irmp_pause_time >= 2 * S100_START_BIT_LEN_MIN && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX))) { // it's S100 ANALYZE_PRINTF9 ("protocol = S100, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX, 2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX, S100_START_BIT_LEN_MIN, S100_START_BIT_LEN_MAX, 2 * S100_START_BIT_LEN_MIN, 2 * S100_START_BIT_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &s100_param; last_pause = irmp_pause_time; if ((irmp_pulse_time > S100_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * S100_START_BIT_LEN_MAX) || (irmp_pause_time > S100_START_BIT_LEN_MAX && irmp_pause_time <= 2 * S100_START_BIT_LEN_MAX)) { last_value = 0; rc5_cmd_bit6 = 1<<6; } else { last_value = 1; } } else #endif // IRMP_SUPPORT_S100_PROTOCOL == 1 #if IRMP_SUPPORT_RC5_PROTOCOL == 1 if (((irmp_pulse_time >= RC5_START_BIT_LEN_MIN && irmp_pulse_time <= RC5_START_BIT_LEN_MAX) || (irmp_pulse_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX)) && ((irmp_pause_time >= RC5_START_BIT_LEN_MIN && irmp_pause_time <= RC5_START_BIT_LEN_MAX) || (irmp_pause_time >= 2 * RC5_START_BIT_LEN_MIN && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX))) { // it's RC5 #if IRMP_SUPPORT_FDC_PROTOCOL == 1 if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("protocol = RC5 or FDC\n"); ANALYZE_PRINTF5 ("FDC start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); ANALYZE_PRINTF5 ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); memcpy_P (&irmp_param2, &fdc_param, sizeof (IRMP_PARAMETER)); } else #endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("protocol = RC5 or RCCAR\n"); ANALYZE_PRINTF5 ("RCCAR start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); ANALYZE_PRINTF5 ("RC5 start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX); memcpy_P (&irmp_param2, &rccar_param, sizeof (IRMP_PARAMETER)); } else #endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 { ANALYZE_PRINTF9 ("protocol = RC5, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or pulse: %3d - %3d, pause: %3d - %3d\n", RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX, RC5_START_BIT_LEN_MIN, RC5_START_BIT_LEN_MAX, 2 * RC5_START_BIT_LEN_MIN, 2 * RC5_START_BIT_LEN_MAX); } irmp_param_p = (IRMP_PARAMETER *) &rc5_param; last_pause = irmp_pause_time; if ((irmp_pulse_time > RC5_START_BIT_LEN_MAX && irmp_pulse_time <= 2 * RC5_START_BIT_LEN_MAX) || (irmp_pause_time > RC5_START_BIT_LEN_MAX && irmp_pause_time <= 2 * RC5_START_BIT_LEN_MAX)) { last_value = 0; rc5_cmd_bit6 = 1<<6; } else { last_value = 1; } } else #endif // IRMP_SUPPORT_RC5_PROTOCOL == 1 #if IRMP_SUPPORT_RCII_PROTOCOL == 1 if ((irmp_pulse_time >= RCII_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCII_START_BIT_PULSE_LEN_MAX) && (irmp_pause_time >= RCII_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCII_START_BIT_PAUSE_LEN_MAX)) { // it's RCII ANALYZE_PRINTF5 ("protocol = RCII, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RCII_START_BIT_PULSE_LEN_MIN, RCII_START_BIT_PULSE_LEN_MAX, RCII_START_BIT_PAUSE_LEN_MIN, RCII_START_BIT_PAUSE_LEN_MAX) irmp_param_p = (IRMP_PARAMETER *) &rcii_param; last_pause = irmp_pause_time; waiting_for_2nd_pulse = 1; last_value = 1; } else #endif // IRMP_SUPPORT_RCII_PROTOCOL == 1 #if IRMP_SUPPORT_DENON_PROTOCOL == 1 if ( (irmp_pulse_time >= DENON_PULSE_LEN_MIN && irmp_pulse_time <= DENON_PULSE_LEN_MAX) && ((irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) || (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX))) { // it's DENON ANALYZE_PRINTF7 ("protocol = DENON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", DENON_PULSE_LEN_MIN, DENON_PULSE_LEN_MAX, DENON_1_PAUSE_LEN_MIN, DENON_1_PAUSE_LEN_MAX, DENON_0_PAUSE_LEN_MIN, DENON_0_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &denon_param; } else #endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 #if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 if ( (irmp_pulse_time >= THOMSON_PULSE_LEN_MIN && irmp_pulse_time <= THOMSON_PULSE_LEN_MAX) && ((irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) || (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX))) { // it's THOMSON ANALYZE_PRINTF7 ("protocol = THOMSON, start bit timings: pulse: %3d - %3d, pause: %3d - %3d or %3d - %3d\n", THOMSON_PULSE_LEN_MIN, THOMSON_PULSE_LEN_MAX, THOMSON_1_PAUSE_LEN_MIN, THOMSON_1_PAUSE_LEN_MAX, THOMSON_0_PAUSE_LEN_MIN, THOMSON_0_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &thomson_param; } else #endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 if (irmp_pulse_time >= BOSE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= BOSE_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= BOSE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BOSE_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = BOSE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", BOSE_START_BIT_PULSE_LEN_MIN, BOSE_START_BIT_PULSE_LEN_MAX, BOSE_START_BIT_PAUSE_LEN_MIN, BOSE_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &bose_param; } else #endif // IRMP_SUPPORT_BOSE_PROTOCOL == 1 #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_pulse_time >= RC6_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RC6_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RC6_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RC6_START_BIT_PAUSE_LEN_MAX) { // it's RC6 ANALYZE_PRINTF5 ("protocol = RC6, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RC6_START_BIT_PULSE_LEN_MIN, RC6_START_BIT_PULSE_LEN_MAX, RC6_START_BIT_PAUSE_LEN_MIN, RC6_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &rc6_param; last_pause = 0; last_value = 1; } else #endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 #if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 if (irmp_pulse_time >= RECS80EXT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RECS80EXT_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RECS80EXT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RECS80EXT_START_BIT_PAUSE_LEN_MAX) { // it's RECS80EXT ANALYZE_PRINTF5 ("protocol = RECS80EXT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RECS80EXT_START_BIT_PULSE_LEN_MIN, RECS80EXT_START_BIT_PULSE_LEN_MAX, RECS80EXT_START_BIT_PAUSE_LEN_MIN, RECS80EXT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &recs80ext_param; } else #endif // IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 if (irmp_pulse_time >= NUBERT_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NUBERT_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NUBERT_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NUBERT_START_BIT_PAUSE_LEN_MAX) { // it's NUBERT ANALYZE_PRINTF5 ("protocol = NUBERT, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NUBERT_START_BIT_PULSE_LEN_MIN, NUBERT_START_BIT_PULSE_LEN_MAX, NUBERT_START_BIT_PAUSE_LEN_MIN, NUBERT_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &nubert_param; } else #endif // IRMP_SUPPORT_NUBERT_PROTOCOL == 1 #if IRMP_SUPPORT_FAN_PROTOCOL == 1 if (irmp_pulse_time >= FAN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FAN_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= FAN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FAN_START_BIT_PAUSE_LEN_MAX) { // it's FAN ANALYZE_PRINTF5 ("protocol = FAN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", FAN_START_BIT_PULSE_LEN_MIN, FAN_START_BIT_PULSE_LEN_MAX, FAN_START_BIT_PAUSE_LEN_MIN, FAN_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &fan_param; } else #endif // IRMP_SUPPORT_FAN_PROTOCOL == 1 #if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 if (irmp_pulse_time >= SPEAKER_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SPEAKER_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= SPEAKER_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SPEAKER_START_BIT_PAUSE_LEN_MAX) { // it's SPEAKER ANALYZE_PRINTF5 ("protocol = SPEAKER, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", SPEAKER_START_BIT_PULSE_LEN_MIN, SPEAKER_START_BIT_PULSE_LEN_MAX, SPEAKER_START_BIT_PAUSE_LEN_MIN, SPEAKER_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &speaker_param; } else #endif // IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 if (irmp_pulse_time >= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX && irmp_pause_time >= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX) { // it's BANG_OLUFSEN ANALYZE_PRINTF1 ("protocol = BANG_OLUFSEN\n"); ANALYZE_PRINTF5 ("start bit 1 timings: pulse: %3d - %3d, pause: %3d - %3d\n", BANG_OLUFSEN_START_BIT1_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT1_PAUSE_LEN_MAX); ANALYZE_PRINTF5 ("start bit 2 timings: pulse: %3d - %3d, pause: %3d - %3d\n", BANG_OLUFSEN_START_BIT2_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT2_PAUSE_LEN_MAX); ANALYZE_PRINTF5 ("start bit 3 timings: pulse: %3d - %3d, pause: %3d - %3d\n", BANG_OLUFSEN_START_BIT3_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX); ANALYZE_PRINTF5 ("start bit 4 timings: pulse: %3d - %3d, pause: %3d - %3d\n", BANG_OLUFSEN_START_BIT4_PULSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PULSE_LEN_MAX, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MIN, BANG_OLUFSEN_START_BIT4_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &bang_olufsen_param; last_value = 0; } else #endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 #if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 if (irmp_pulse_time >= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN && irmp_pulse_time <= GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX && irmp_pause_time >= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN && irmp_pause_time <= GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX) { // it's GRUNDIG ANALYZE_PRINTF5 ("protocol = GRUNDIG, pre bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", GRUNDIG_NOKIA_IR60_START_BIT_LEN_MIN, GRUNDIG_NOKIA_IR60_START_BIT_LEN_MAX, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MIN, GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &grundig_param; last_pause = irmp_pause_time; last_value = 1; } else #endif // IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 // check MERLIN before RUWIDO! if (irmp_pulse_time >= MERLIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= MERLIN_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= MERLIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= MERLIN_START_BIT_PAUSE_LEN_MAX) { // it's MERLIN ANALYZE_PRINTF5 ("protocol = MERLIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", MERLIN_START_BIT_PULSE_LEN_MIN, MERLIN_START_BIT_PULSE_LEN_MAX, MERLIN_START_BIT_PAUSE_LEN_MIN, MERLIN_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &merlin_param; last_pause = irmp_pause_time; last_value = 1; } else #endif // IRMP_SUPPORT_MERLIN_PROTOCOL == 1 #if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 if (((irmp_pulse_time >= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX) || (irmp_pulse_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX)) && ((irmp_pause_time >= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX) || (irmp_pause_time >= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX))) { // it's RUWIDO or SIEMENS ANALYZE_PRINTF9 ("protocol = RUWIDO, start bit timings: pulse: %3d - %3d or %3d - %3d, pause: %3d - %3d or %3d - %3d\n", SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PULSE_LEN_MAX, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MIN, 2 * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &ruwido_param; last_pause = irmp_pause_time; last_value = 1; } else #endif // IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 #if IRMP_SUPPORT_FDC_PROTOCOL == 1 if (irmp_pulse_time >= FDC_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= FDC_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= FDC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= FDC_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = FDC, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", FDC_START_BIT_PULSE_LEN_MIN, FDC_START_BIT_PULSE_LEN_MAX, FDC_START_BIT_PAUSE_LEN_MIN, FDC_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &fdc_param; } else #endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 if (irmp_pulse_time >= RCCAR_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RCCAR_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = RCCAR, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RCCAR_START_BIT_PULSE_LEN_MIN, RCCAR_START_BIT_PULSE_LEN_MAX, RCCAR_START_BIT_PAUSE_LEN_MIN, RCCAR_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &rccar_param; } else #endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 if (irmp_pulse_time >= KATHREIN_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX) { // it's KATHREIN ANALYZE_PRINTF5 ("protocol = KATHREIN, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", KATHREIN_START_BIT_PULSE_LEN_MIN, KATHREIN_START_BIT_PULSE_LEN_MAX, KATHREIN_START_BIT_PAUSE_LEN_MIN, KATHREIN_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &kathrein_param; } else #endif // IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 if (irmp_pulse_time >= NETBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= NETBOX_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= NETBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NETBOX_START_BIT_PAUSE_LEN_MAX) { // it's NETBOX ANALYZE_PRINTF5 ("protocol = NETBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", NETBOX_START_BIT_PULSE_LEN_MIN, NETBOX_START_BIT_PULSE_LEN_MAX, NETBOX_START_BIT_PAUSE_LEN_MIN, NETBOX_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &netbox_param; } else #endif // IRMP_SUPPORT_NETBOX_PROTOCOL == 1 #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 if (irmp_pulse_time >= LEGO_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= LEGO_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= LEGO_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= LEGO_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = LEGO, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", LEGO_START_BIT_PULSE_LEN_MIN, LEGO_START_BIT_PULSE_LEN_MAX, LEGO_START_BIT_PAUSE_LEN_MIN, LEGO_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &lego_param; } else #endif // IRMP_SUPPORT_LEGO_PROTOCOL == 1 #if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 if (irmp_pulse_time >= IRMP16_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= IRMP16_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= IRMP16_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= IRMP16_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = IRMP16, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", IRMP16_START_BIT_PULSE_LEN_MIN, IRMP16_START_BIT_PULSE_LEN_MAX, IRMP16_START_BIT_PAUSE_LEN_MIN, IRMP16_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &irmp16_param; } else #endif // IRMP_SUPPORT_IRMP16_PROTOCOL == 1 #if IRMP_SUPPORT_GREE_PROTOCOL == 1 if (irmp_pulse_time >= GREE_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= GREE_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= GREE_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= GREE_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF5 ("protocol = GREE, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", GREE_START_BIT_PULSE_LEN_MIN, GREE_START_BIT_PULSE_LEN_MAX, GREE_START_BIT_PAUSE_LEN_MIN, GREE_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &gree_param; } else #endif // IRMP_SUPPORT_GREE_PROTOCOL == 1 #if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 if (irmp_pulse_time >= A1TVBOX_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= A1TVBOX_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= A1TVBOX_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= A1TVBOX_START_BIT_PAUSE_LEN_MAX) { // it's A1TVBOX ANALYZE_PRINTF5 ("protocol = A1TVBOX, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", A1TVBOX_START_BIT_PULSE_LEN_MIN, A1TVBOX_START_BIT_PULSE_LEN_MAX, A1TVBOX_START_BIT_PAUSE_LEN_MIN, A1TVBOX_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &a1tvbox_param; last_pause = 0; last_value = 1; } else #endif // IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 if (irmp_pulse_time >= ORTEK_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= ORTEK_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= ORTEK_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= ORTEK_START_BIT_PAUSE_LEN_MAX) { // it's ORTEK (Hama) ANALYZE_PRINTF5 ("protocol = ORTEK, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", ORTEK_START_BIT_PULSE_LEN_MIN, ORTEK_START_BIT_PULSE_LEN_MAX, ORTEK_START_BIT_PAUSE_LEN_MIN, ORTEK_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &ortek_param; last_pause = 0; last_value = 1; parity = 0; } else #endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1 #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 if (irmp_pulse_time >= RCMM32_START_BIT_PULSE_LEN_MIN && irmp_pulse_time <= RCMM32_START_BIT_PULSE_LEN_MAX && irmp_pause_time >= RCMM32_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_START_BIT_PAUSE_LEN_MAX) { // it's RCMM ANALYZE_PRINTF5 ("protocol = RCMM, start bit timings: pulse: %3d - %3d, pause: %3d - %3d\n", RCMM32_START_BIT_PULSE_LEN_MIN, RCMM32_START_BIT_PULSE_LEN_MAX, RCMM32_START_BIT_PAUSE_LEN_MIN, RCMM32_START_BIT_PAUSE_LEN_MAX); irmp_param_p = (IRMP_PARAMETER *) &rcmm_param; } else #endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1 { ANALYZE_PRINTF1 ("protocol = UNKNOWN\n"); irmp_start_bit_detected = 0; // wait for another start bit... irmp_param.protocol = 0; // reset protocol } if (irmp_start_bit_detected) { memcpy_P (&irmp_param, irmp_param_p, sizeof (IRMP_PARAMETER)); if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) { ANALYZE_PRINTF3 ("pulse_1: %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max); ANALYZE_PRINTF3 ("pause_1: %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max); } else { ANALYZE_PRINTF5 ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_1_len_min, irmp_param.pulse_1_len_max, 2 * irmp_param.pulse_1_len_min, 2 * irmp_param.pulse_1_len_max); ANALYZE_PRINTF5 ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_1_len_min, irmp_param.pause_1_len_max, 2 * irmp_param.pause_1_len_min, 2 * irmp_param.pause_1_len_max); } #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) if (irmp_param2.protocol) { ANALYZE_PRINTF3 ("pulse_0: %3d - %3d\n", irmp_param2.pulse_0_len_min, irmp_param2.pulse_0_len_max); ANALYZE_PRINTF3 ("pause_0: %3d - %3d\n", irmp_param2.pause_0_len_min, irmp_param2.pause_0_len_max); ANALYZE_PRINTF3 ("pulse_1: %3d - %3d\n", irmp_param2.pulse_1_len_min, irmp_param2.pulse_1_len_max); ANALYZE_PRINTF3 ("pause_1: %3d - %3d\n", irmp_param2.pause_1_len_min, irmp_param2.pause_1_len_max); } #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC6_PROTOCOL) { ANALYZE_PRINTF3 ("pulse_toggle: %3d - %3d\n", RC6_TOGGLE_BIT_LEN_MIN, RC6_TOGGLE_BIT_LEN_MAX); } #endif if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) { ANALYZE_PRINTF3 ("pulse_0: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); ANALYZE_PRINTF3 ("pause_0: %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max); } else { ANALYZE_PRINTF5 ("pulse: %3d - %3d or %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max, 2 * irmp_param.pulse_0_len_min, 2 * irmp_param.pulse_0_len_max); ANALYZE_PRINTF5 ("pause: %3d - %3d or %3d - %3d\n", irmp_param.pause_0_len_min, irmp_param.pause_0_len_max, 2 * irmp_param.pause_0_len_min, 2 * irmp_param.pause_0_len_max); } #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) { ANALYZE_PRINTF3 ("pulse_r: %3d - %3d\n", irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); ANALYZE_PRINTF3 ("pause_r: %3d - %3d\n", BANG_OLUFSEN_R_PAUSE_LEN_MIN, BANG_OLUFSEN_R_PAUSE_LEN_MAX); } #endif ANALYZE_PRINTF2 ("command_offset: %2d\n", irmp_param.command_offset); ANALYZE_PRINTF2 ("command_len: %3d\n", irmp_param.command_end - irmp_param.command_offset); ANALYZE_PRINTF2 ("complete_len: %3d\n", irmp_param.complete_len); ANALYZE_PRINTF2 ("stop_bit: %3d\n", irmp_param.stop_bit); } #if IRMP_SUPPORT_MANCHESTER == 1 if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && irmp_param.protocol != IRMP_RUWIDO_PROTOCOL && // Manchester, but not RUWIDO irmp_param.protocol != IRMP_RC6_PROTOCOL /*** && // Manchester, but not RC6 irmp_param.protocol != IRMP_RCII_PROTOCOL ****/) // Manchester, but not RCII { if (irmp_pause_time > irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pulse_1_len_max) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); ANALYZE_NEWLINE (); irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1); } else if (! last_value) // && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); ANALYZE_NEWLINE (); irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0); } } else #endif // IRMP_SUPPORT_MANCHESTER == 1 #if IRMP_SUPPORT_SERIAL == 1 if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) { ; // do nothing } else #endif // IRMP_SUPPORT_SERIAL == 1 #if IRMP_SUPPORT_DENON_PROTOCOL == 1 if (irmp_param.protocol == IRMP_DENON_PROTOCOL) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); if (irmp_pause_time >= DENON_1_PAUSE_LEN_MIN && irmp_pause_time <= DENON_1_PAUSE_LEN_MAX) { // pause timings correct for "1"? ANALYZE_PUTCHAR ('1'); // yes, store 1 ANALYZE_NEWLINE (); irmp_store_bit (1); } else // if (irmp_pause_time >= DENON_0_PAUSE_LEN_MIN && irmp_pause_time <= DENON_0_PAUSE_LEN_MAX) { // pause timings correct for "0"? ANALYZE_PUTCHAR ('0'); // yes, store 0 ANALYZE_NEWLINE (); irmp_store_bit (0); } } else #endif // IRMP_SUPPORT_DENON_PROTOCOL == 1 #if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 if (irmp_param.protocol == IRMP_THOMSON_PROTOCOL) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); if (irmp_pause_time >= THOMSON_1_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_1_PAUSE_LEN_MAX) { // pause timings correct for "1"? ANALYZE_PUTCHAR ('1'); // yes, store 1 ANALYZE_NEWLINE (); irmp_store_bit (1); } else // if (irmp_pause_time >= THOMSON_0_PAUSE_LEN_MIN && irmp_pause_time <= THOMSON_0_PAUSE_LEN_MAX) { // pause timings correct for "0"? ANALYZE_PUTCHAR ('0'); // yes, store 0 ANALYZE_NEWLINE (); irmp_store_bit (0); } } else #endif // IRMP_SUPPORT_THOMSON_PROTOCOL == 1 #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 if (irmp_param.protocol == RF_GEN24_PROTOCOL) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_PUTCHAR (bit_0 + '0'); ANALYZE_NEWLINE (); irmp_store_bit (bit_0); // start bit is data bit } else #endif // IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 { ; // else do nothing } irmp_pulse_time = 1; // set counter to 1, not 0 irmp_pause_time = 0; wait_for_start_space = 0; } } else if (wait_for_space) // the data section.... { // counting the time of darkness.... uint_fast8_t got_light = FALSE; if (irmp_input) // still dark? { // yes... irmp_pause_time++; // increment counter if (irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 1 && irmp_pause_time > ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) ? 0 : STOP_BIT_PAUSE_LEN_MIN)) { if ( #if IRMP_SUPPORT_MANCHESTER == 1 (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) || #endif #if IRMP_SUPPORT_SERIAL == 1 (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) || #endif (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max)) { if (! (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) { ANALYZE_PRINTF1 ("stop bit detected\n"); #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 if (irmp_param.protocol == IRMP_MELINERA_PROTOCOL) { irmp_tmp_command = irmp_melinera_command; // set command irmp_tmp_address = 0; // no address } #endif } irmp_param.stop_bit = 0; } else { ANALYZE_PRINTF5 ("error: stop bit timing wrong, irmp_bit = %d, irmp_pulse_time = %d, pulse_0_len_min = %d, pulse_0_len_max = %d\n", irmp_bit, irmp_pulse_time, irmp_param.pulse_0_len_min, irmp_param.pulse_0_len_max); irmp_start_bit_detected = 0; // wait for another start bit... irmp_pulse_time = 0; irmp_pause_time = 0; } } else #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && // Sony has a variable number of bits: irmp_pause_time > SIRCS_PAUSE_LEN_MAX && // minimum is 12 irmp_bit >= 12 - 1) // pause too long? { // yes, break and close this frame irmp_param.complete_len = irmp_bit + 1; // set new complete length got_light = TRUE; // this is a lie, but helps (generates stop bit) irmp_tmp_address |= (irmp_bit - SIRCS_MINIMUM_DATA_LEN + 1) << 8; // new: store number of additional bits in upper byte of address! irmp_param.command_end = irmp_param.command_offset + irmp_bit + 1; // correct command length irmp_pause_time = SIRCS_PAUSE_LEN_MAX - 1; // correct pause length } else #endif #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 if (irmp_param.protocol == IRMP_MERLIN_PROTOCOL && // Merlin has a variable number of bits: irmp_pause_time > MERLIN_START_BIT_PAUSE_LEN_MAX && // minimum is 8 irmp_bit >= 8 - 1) // pause too long? { // yes, break and close this frame irmp_param.complete_len = irmp_bit; // set new complete length got_light = TRUE; // this is a lie, but helps (generates stop bit) irmp_pause_time = MERLIN_BIT_PAUSE_LEN_MAX - 1; // correct pause length } else #endif #if IRMP_SUPPORT_FAN_PROTOCOL == 1 if (irmp_param.protocol == IRMP_FAN_PROTOCOL && // FAN has no stop bit. irmp_bit >= FAN_COMPLETE_DATA_LEN - 1) // last bit in frame { // yes, break and close this frame if (irmp_pulse_time <= FAN_0_PULSE_LEN_MAX && irmp_pause_time >= FAN_0_PAUSE_LEN_MIN) { ANALYZE_PRINTF1 ("Generating virtual stop bit\n"); got_light = TRUE; // this is a lie, but helps (generates stop bit) } else if (irmp_pulse_time >= FAN_1_PULSE_LEN_MIN && irmp_pause_time >= FAN_1_PAUSE_LEN_MIN) { ANALYZE_PRINTF1 ("Generating virtual stop bit\n"); got_light = TRUE; // this is a lie, but helps (generates stop bit) } } else #endif #if IRMP_SUPPORT_SERIAL == 1 // NETBOX generates no stop bit, here is the timeout condition: if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) && irmp_param.protocol == IRMP_NETBOX_PROTOCOL && irmp_pause_time >= NETBOX_PULSE_LEN * (NETBOX_COMPLETE_DATA_LEN - irmp_bit)) { got_light = TRUE; // this is a lie, but helps (generates stop bit) } else #endif #if IRMP_SUPPORT_GRUNDIG_NOKIA_IR60_PROTOCOL == 1 if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && !irmp_param.stop_bit) { if (irmp_pause_time > IR60_TIMEOUT_LEN && (irmp_bit == 5 || irmp_bit == 6)) { ANALYZE_PRINTF1 ("Switching to IR60 protocol\n"); got_light = TRUE; // this is a lie, but generates a stop bit ;-) irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_IR60_PROTOCOL; // change protocol irmp_param.complete_len = IR60_COMPLETE_DATA_LEN; // correct complete len irmp_param.address_offset = IR60_ADDRESS_OFFSET; irmp_param.address_end = IR60_ADDRESS_OFFSET + IR60_ADDRESS_LEN; irmp_param.command_offset = IR60_COMMAND_OFFSET; irmp_param.command_end = IR60_COMMAND_OFFSET + IR60_COMMAND_LEN; irmp_tmp_command <<= 1; irmp_tmp_command |= first_bit; } else if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN - 2) { // special manchester decoder irmp_param.complete_len = GRUNDIG_COMPLETE_DATA_LEN; // correct complete len got_light = TRUE; // this is a lie, but generates a stop bit ;-) irmp_param.stop_bit = TRUE; // set flag } else if (irmp_bit >= GRUNDIG_COMPLETE_DATA_LEN) { ANALYZE_PRINTF2 ("Switching to NOKIA protocol, irmp_bit = %d\n", irmp_bit); irmp_param.protocol = IRMP_NOKIA_PROTOCOL; // change protocol irmp_param.address_offset = NOKIA_ADDRESS_OFFSET; irmp_param.address_end = NOKIA_ADDRESS_OFFSET + NOKIA_ADDRESS_LEN; irmp_param.command_offset = NOKIA_COMMAND_OFFSET; irmp_param.command_end = NOKIA_COMMAND_OFFSET + NOKIA_COMMAND_LEN; if (irmp_tmp_command & 0x300) { irmp_tmp_address = (irmp_tmp_command >> 8); irmp_tmp_command &= 0xFF; } } } else #endif #if IRMP_SUPPORT_SIEMENS_OR_RUWIDO_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RUWIDO_PROTOCOL && !irmp_param.stop_bit) { if (irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= RUWIDO_COMPLETE_DATA_LEN - 2) { // special manchester decoder irmp_param.complete_len = RUWIDO_COMPLETE_DATA_LEN; // correct complete len got_light = TRUE; // this is a lie, but generates a stop bit ;-) irmp_param.stop_bit = TRUE; // set flag } else if (irmp_bit >= RUWIDO_COMPLETE_DATA_LEN) { ANALYZE_PRINTF1 ("Switching to SIEMENS protocol\n"); irmp_param.protocol = IRMP_SIEMENS_PROTOCOL; // change protocol irmp_param.address_offset = SIEMENS_ADDRESS_OFFSET; irmp_param.address_end = SIEMENS_ADDRESS_OFFSET + SIEMENS_ADDRESS_LEN; irmp_param.command_offset = SIEMENS_COMMAND_OFFSET; irmp_param.command_end = SIEMENS_COMMAND_OFFSET + SIEMENS_COMMAND_LEN; // 76543210 // RUWIDO: AAAAAAAAACCCCCCCp // SIEMENS: AAAAAAAAAAACCCCCCCCCCp irmp_tmp_address <<= 2; irmp_tmp_address |= (irmp_tmp_command >> 6); irmp_tmp_command &= 0x003F; irmp_tmp_command |= last_value; } } else #endif #if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 if (irmp_param.protocol == IRMP_ROOMBA_PROTOCOL && // Roomba has no stop bit irmp_bit >= ROOMBA_COMPLETE_DATA_LEN - 1) // it's the last data bit... { // break and close this frame if (irmp_pulse_time >= ROOMBA_1_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_1_PULSE_LEN_MAX) { irmp_pause_time = ROOMBA_1_PAUSE_LEN_EXACT; } else if (irmp_pulse_time >= ROOMBA_0_PULSE_LEN_MIN && irmp_pulse_time <= ROOMBA_0_PULSE_LEN_MAX) { irmp_pause_time = ROOMBA_0_PAUSE_LEN; } got_light = TRUE; // this is a lie, but helps (generates stop bit) } else #endif #if IRMP_SUPPORT_MANCHESTER == 1 if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && (irmp_param.protocol != IRMP_RC6_PROTOCOL || irmp_param.complete_len != RC6_COMPLETE_DATA_LEN_LONG) && // not RC6A irmp_pause_time >= 2 * irmp_param.pause_1_len_max && irmp_bit >= irmp_param.complete_len - 2 && !irmp_param.stop_bit) { // special manchester decoder got_light = TRUE; // this is a lie, but generates a stop bit ;-) irmp_param.stop_bit = TRUE; // set flag } else if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG && // RC6A irmp_pause_time >= 2 * irmp_param.pause_1_len_max) // this pause indicates the end { // special manchester decoder got_light = TRUE; // this is a lie, but generates a stop bit ;-) irmp_param.stop_bit = TRUE; // set flag irmp_param.complete_len = irmp_bit + 1; // at least 1 more bit will be added at last position } else #endif // IRMP_SUPPORT_MANCHESTER == 1 if (irmp_pause_time > IRMP_TIMEOUT_LEN) // timeout? { // yes... if (irmp_bit == irmp_param.complete_len - 1 && irmp_param.stop_bit == 0) { irmp_bit++; } #if IRMP_SUPPORT_NEC_PROTOCOL == 1 else if ((irmp_param.protocol == IRMP_NEC_PROTOCOL || irmp_param.protocol == IRMP_NEC42_PROTOCOL) && irmp_bit == 0) { // it was a non-standard repetition frame ANALYZE_PRINTF1 ("Detected non-standard repetition frame, switching to NEC repetition\n"); if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) { irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 irmp_tmp_address = last_irmp_address; // address is last address irmp_tmp_command = last_irmp_command; // command is last command irmp_flags |= IRMP_FLAG_REPETITION; key_repetition_len = 0; } else { ANALYZE_PRINTF3 ("ignoring NEC repetition frame: timeout occured, key_repetition_len = %u > %u\n", (unsigned int) key_repetition_len, (unsigned int) NEC_FRAME_REPEAT_PAUSE_LEN_MAX); irmp_ir_detected = FALSE; } } #endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 #if IRMP_SUPPORT_JVC_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit { ANALYZE_PRINTF2 ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 irmp_tmp_command = (irmp_tmp_address >> 4); // set command: upper 12 bits are command bits irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... } #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_NEC_PROTOCOL && (irmp_bit == 28 || irmp_bit == 29)) // it was a LGAIR stop bit { ANALYZE_PRINTF2 ("Switching to LGAIR protocol, irmp_bit = %d\n", irmp_bit); irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 irmp_tmp_command = irmp_lgair_command; // set command: upper 8 bits are command bits irmp_tmp_address = irmp_lgair_address; // lower 4 bits are address bits irmp_start_bit_detected = 1; // tricky: don't wait for another start bit... } #endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1 #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 #if IRMP_SUPPORT_NEC_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 32) // it was a NEC stop bit { ANALYZE_PRINTF1 ("Switching to NEC protocol\n"); irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_NEC_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 // 0123456789ABC0123456789ABC0123456701234567 // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc // NEC: AAAAAAAAaaaaaaaaCCCCCCCCcccccccc irmp_tmp_address |= (irmp_tmp_address2 & 0x0007) << 13; // fm 2012-02-13: 12 -> 13 irmp_tmp_command = (irmp_tmp_address2 >> 3) | (irmp_tmp_command << 10); } #endif // IRMP_SUPPORT_NEC_PROTOCOL == 1 #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && irmp_bit == 28) // it was a NEC stop bit { ANALYZE_PRINTF1 ("Switching to LGAIR protocol\n"); irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_LGAIR_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 irmp_tmp_address = irmp_lgair_address; irmp_tmp_command = irmp_lgair_command; } #endif // IRMP_SUPPORT_LGAIR_PROTOCOL == 1 #if IRMP_SUPPORT_JVC_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && (irmp_bit == 16 || irmp_bit == 17)) // it was a JVC stop bit { ANALYZE_PRINTF2 ("Switching to JVC protocol, irmp_bit = %d\n", irmp_bit); irmp_param.stop_bit = TRUE; // set flag irmp_param.protocol = IRMP_JVC_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length: 16 or 17 // 0123456789ABC0123456789ABC0123456701234567 // NEC42: AAAAAAAAAAAAAaaaaaaaaaaaaaCCCCCCCCcccccccc // JVC: AAAACCCCCCCCCCCC irmp_tmp_command = (irmp_tmp_address >> 4) | (irmp_tmp_address2 << 9); // set command: upper 12 bits are command bits irmp_tmp_address = irmp_tmp_address & 0x000F; // lower 4 bits are address bits } #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 #endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL && irmp_bit == 32) // it was a SAMSUNG32 stop bit { ANALYZE_PRINTF1 ("Switching to SAMSUNG32 protocol\n"); irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; } #endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL && (irmp_bit == 12 || irmp_bit == 24)) // it was a RCMM stop bit { if (irmp_bit == 12) { irmp_tmp_command = (irmp_tmp_address & 0xFF); // set command: lower 8 bits are command bits irmp_tmp_address >>= 8; // upper 4 bits are address bits ANALYZE_PRINTF2 ("Switching to RCMM12 protocol, irmp_bit = %d\n", irmp_bit); irmp_param.protocol = IRMP_RCMM12_PROTOCOL; // switch protocol } else // if ((irmp_bit == 24) { ANALYZE_PRINTF2 ("Switching to RCMM24 protocol, irmp_bit = %d\n", irmp_bit); irmp_param.protocol = IRMP_RCMM24_PROTOCOL; // switch protocol } irmp_param.stop_bit = TRUE; // set flag irmp_param.complete_len = irmp_bit; // patch length } #endif // IRMP_SUPPORT_RCMM_PROTOCOL == 1 #if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 else if (irmp_param.protocol == IRMP_MATSUSHITA_PROTOCOL && irmp_bit == 22) // it was a TECHNICS stop bit { ANALYZE_PRINTF2 ("Switching to TECHNICS protocol, irmp_bit = %d\n", irmp_bit); // Situation: // The first 12 bits have been stored in irmp_tmp_command (LSB first) // The following 10 bits have been stored in irmp_tmp_address (LSB first) // The code of TECHNICS is: // cccccccccccCCCCCCCCCCC (11 times c and 11 times C) // ccccccccccccaaaaaaaaaa // where C is inverted value of c irmp_tmp_address <<= 1; if (irmp_tmp_command & (1<<11)) { irmp_tmp_address |= 1; irmp_tmp_command &= ~(1<<11); } if (irmp_tmp_command == ((~irmp_tmp_address) & 0x07FF)) { irmp_tmp_address = 0; irmp_param.protocol = IRMP_TECHNICS_PROTOCOL; // switch protocol irmp_param.complete_len = irmp_bit; // patch length } else { ANALYZE_PRINTF1 ("error 8: TECHNICS frame error\n"); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // wait for another start bit... irmp_pulse_time = 0; irmp_pause_time = 0; } } #endif // IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 else { ANALYZE_PRINTF3 ("error 2: pause %d after data bit %d too long\n", irmp_pause_time, irmp_bit); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // wait for another start bit... irmp_pulse_time = 0; irmp_pause_time = 0; } } } else { // got light now! got_light = TRUE; } if (got_light) { ANALYZE_PRINTF5 ("%8.3fms [bit %2d: pulse = %3d, pause = %3d] ", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit, irmp_pulse_time, irmp_pause_time); #if IRMP_SUPPORT_MANCHESTER == 1 if ((irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER)) // Manchester { #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 if (irmp_param.complete_len == irmp_bit && irmp_param.protocol == IRMP_MERLIN_PROTOCOL) { if (last_value == 0) { if (irmp_pulse_time >= 2 * irmp_param.pulse_1_len_min && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max && last_pause >= irmp_param.pause_1_len_min && last_pause <= irmp_param.pulse_1_len_max) { irmp_param.complete_len += 2; irmp_store_bit(0); irmp_store_bit(1); ANALYZE_PUTCHAR ('0'); ANALYZE_PUTCHAR ('1'); ANALYZE_NEWLINE (); } } else { if (last_pause >= 2 * irmp_param.pause_1_len_min && last_pause <= 2 * irmp_param.pulse_1_len_max) { if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max) { irmp_param.complete_len++; irmp_store_bit(0); ANALYZE_PUTCHAR ('0'); ANALYZE_NEWLINE (); } else if (irmp_pulse_time >= 2 * irmp_param.pulse_1_len_min && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max) { irmp_param.complete_len += 2; irmp_store_bit(0); irmp_store_bit(1); ANALYZE_PUTCHAR ('0'); ANALYZE_PUTCHAR ('1'); ANALYZE_NEWLINE (); } } } } else #endif #if 1 if (irmp_pulse_time > irmp_param.pulse_1_len_max /* && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max */) #else // better, but some IR-RCs use asymmetric timings :-/ if (irmp_pulse_time > irmp_param.pulse_1_len_max && irmp_pulse_time <= 2 * irmp_param.pulse_1_len_max && irmp_pause_time <= 2 * irmp_param.pause_1_len_max) #endif { #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == irmp_bit + 1) // RC6A { irmp_param.complete_len++; // this is the last position and 2 bits (instead of only 1) will be added } if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit { ANALYZE_PUTCHAR ('T'); if (irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode 6A { irmp_store_bit (1); last_value = 1; } else // RC6 mode 0 { irmp_store_bit (0); last_value = 0; } ANALYZE_NEWLINE (); } else #endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 { ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '0' : '1'); irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 0 : 1 ); #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 4 && irmp_pulse_time > RC6_TOGGLE_BIT_LEN_MIN) // RC6 toggle bit { ANALYZE_PUTCHAR ('T'); irmp_store_bit (1); if (irmp_pause_time > 2 * irmp_param.pause_1_len_max) { last_value = 0; } else { last_value = 1; } ANALYZE_NEWLINE (); } else #endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 { ANALYZE_PUTCHAR ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? '1' : '0'); irmp_store_bit ((irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0 ); #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCII_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) if (! irmp_param2.protocol) #endif { ANALYZE_NEWLINE (); } last_value = (irmp_param.flags & IRMP_PARAM_FLAG_1ST_PULSE_IS_1) ? 1 : 0; } } } else if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max /* && irmp_pause_time <= 2 * irmp_param.pause_1_len_max */) { uint_fast8_t manchester_value; if (last_pause > irmp_param.pause_1_len_max && last_pause <= 2 * irmp_param.pause_1_len_max) { manchester_value = last_value ? 0 : 1; last_value = manchester_value; } else { manchester_value = last_value; } ANALYZE_PUTCHAR (manchester_value + '0'); #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && (IRMP_SUPPORT_FDC_PROTOCOL == 1 || IRMP_SUPPORT_RCCAR_PROTOCOL == 1) if (! irmp_param2.protocol) #endif { ANALYZE_NEWLINE (); } #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_bit == 1 && manchester_value == 1) // RC6 mode != 0 ??? { ANALYZE_PRINTF1 ("Switching to RC6A protocol\n"); irmp_param.complete_len = RC6_COMPLETE_DATA_LEN_LONG; irmp_param.address_offset = 5; irmp_param.address_end = irmp_param.address_offset + 15; irmp_param.command_offset = irmp_param.address_end + 1; // skip 1 system bit, changes like a toggle bit irmp_param.command_end = irmp_param.command_offset + 16 - 1; irmp_tmp_address = 0; } #endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 irmp_store_bit (manchester_value); } else { #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX && ((irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) || (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX))) { ANALYZE_PUTCHAR ('?'); irmp_param.protocol = 0; // switch to FDC, see below } else #endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX && ((irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) || (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX))) { ANALYZE_PUTCHAR ('?'); irmp_param.protocol = 0; // switch to RCCAR, see below } else #endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 { ANALYZE_PUTCHAR ('?'); ANALYZE_NEWLINE (); ANALYZE_PRINTF4 ("error 3 manchester: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_FDC_PROTOCOL == 1 if (irmp_param2.protocol == IRMP_FDC_PROTOCOL && irmp_pulse_time >= FDC_PULSE_LEN_MIN && irmp_pulse_time <= FDC_PULSE_LEN_MAX) { if (irmp_pause_time >= FDC_1_PAUSE_LEN_MIN && irmp_pause_time <= FDC_1_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 (" 1 (FDC)\n"); irmp_store_bit2 (1); } else if (irmp_pause_time >= FDC_0_PAUSE_LEN_MIN && irmp_pause_time <= FDC_0_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 (" 0 (FDC)\n"); irmp_store_bit2 (0); } if (! irmp_param.protocol) { ANALYZE_PRINTF1 ("Switching to FDC protocol\n"); memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); irmp_param2.protocol = 0; irmp_tmp_address = irmp_tmp_address2; irmp_tmp_command = irmp_tmp_command2; } } #endif // IRMP_SUPPORT_FDC_PROTOCOL == 1 #if IRMP_SUPPORT_RC5_PROTOCOL == 1 && IRMP_SUPPORT_RCCAR_PROTOCOL == 1 if (irmp_param2.protocol == IRMP_RCCAR_PROTOCOL && irmp_pulse_time >= RCCAR_PULSE_LEN_MIN && irmp_pulse_time <= RCCAR_PULSE_LEN_MAX) { if (irmp_pause_time >= RCCAR_1_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_1_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 (" 1 (RCCAR)\n"); irmp_store_bit2 (1); } else if (irmp_pause_time >= RCCAR_0_PAUSE_LEN_MIN && irmp_pause_time <= RCCAR_0_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 (" 0 (RCCAR)\n"); irmp_store_bit2 (0); } if (! irmp_param.protocol) { ANALYZE_PRINTF1 ("Switching to RCCAR protocol\n"); memcpy (&irmp_param, &irmp_param2, sizeof (IRMP_PARAMETER)); irmp_param2.protocol = 0; irmp_tmp_address = irmp_tmp_address2; irmp_tmp_command = irmp_tmp_command2; } } #endif // IRMP_SUPPORT_RCCAR_PROTOCOL == 1 last_pause = irmp_pause_time; wait_for_space = 0; } else #endif // IRMP_SUPPORT_MANCHESTER == 1 #if IRMP_SUPPORT_SERIAL == 1 if (irmp_param.flags & IRMP_PARAM_FLAG_IS_SERIAL) { while (irmp_bit < irmp_param.complete_len && irmp_pulse_time > irmp_param.pulse_1_len_max) { ANALYZE_PUTCHAR ('1'); irmp_store_bit (1); if (irmp_pulse_time >= irmp_param.pulse_1_len_min) { irmp_pulse_time -= irmp_param.pulse_1_len_min; } else { irmp_pulse_time = 0; } } while (irmp_bit < irmp_param.complete_len && irmp_pause_time > irmp_param.pause_1_len_max) { ANALYZE_PUTCHAR ('0'); irmp_store_bit (0); if (irmp_pause_time >= irmp_param.pause_1_len_min) { irmp_pause_time -= irmp_param.pause_1_len_min; } else { irmp_pause_time = 0; } } ANALYZE_NEWLINE (); wait_for_space = 0; } else #endif // IRMP_SUPPORT_SERIAL == 1 #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 if (irmp_param.protocol == IRMP_SAMSUNG_PROTOCOL && irmp_bit == 16) // Samsung: 16th bit { if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX && irmp_pause_time >= SAMSUNG_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("SYNC\n"); wait_for_space = 0; irmp_bit++; } else if (irmp_pulse_time >= SAMSUNG_PULSE_LEN_MIN && irmp_pulse_time <= SAMSUNG_PULSE_LEN_MAX) { #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 ANALYZE_PRINTF1 ("Switching to SAMSUNG48 protocol "); irmp_param.protocol = IRMP_SAMSUNG48_PROTOCOL; irmp_param.command_offset = SAMSUNG48_COMMAND_OFFSET; irmp_param.command_end = SAMSUNG48_COMMAND_OFFSET + SAMSUNG48_COMMAND_LEN; irmp_param.complete_len = SAMSUNG48_COMPLETE_DATA_LEN; #else ANALYZE_PRINTF1 ("Switching to SAMSUNG32 protocol "); irmp_param.protocol = IRMP_SAMSUNG32_PROTOCOL; irmp_param.command_offset = SAMSUNG32_COMMAND_OFFSET; irmp_param.command_end = SAMSUNG32_COMMAND_OFFSET + SAMSUNG32_COMMAND_LEN; irmp_param.complete_len = SAMSUNG32_COMPLETE_DATA_LEN; #endif if (irmp_pause_time >= SAMSUNG_1_PAUSE_LEN_MIN && irmp_pause_time <= SAMSUNG_1_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('1'); ANALYZE_NEWLINE (); irmp_store_bit (1); wait_for_space = 0; } else { ANALYZE_PUTCHAR ('0'); ANALYZE_NEWLINE (); irmp_store_bit (0); wait_for_space = 0; } } else { // timing incorrect! ANALYZE_PRINTF4 ("error 3 Samsung: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } else #endif // IRMP_SUPPORT_SAMSUNG_PROTOCOL #if IRMP_SUPPORT_NEC16_PROTOCOL #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && #else // IRMP_SUPPORT_NEC_PROTOCOL instead if (irmp_param.protocol == IRMP_NEC_PROTOCOL && #endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 irmp_bit == 8 && irmp_pause_time >= NEC_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= NEC_START_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("Switching to NEC16 protocol\n"); irmp_param.protocol = IRMP_NEC16_PROTOCOL; irmp_param.address_offset = NEC16_ADDRESS_OFFSET; irmp_param.address_end = NEC16_ADDRESS_OFFSET + NEC16_ADDRESS_LEN; irmp_param.command_offset = NEC16_COMMAND_OFFSET; irmp_param.command_end = NEC16_COMMAND_OFFSET + NEC16_COMMAND_LEN; irmp_param.complete_len = NEC16_COMPLETE_DATA_LEN; wait_for_space = 0; } else #endif // IRMP_SUPPORT_NEC16_PROTOCOL #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 if (irmp_param.protocol == IRMP_BANG_OLUFSEN_PROTOCOL) { if (irmp_pulse_time >= BANG_OLUFSEN_PULSE_LEN_MIN && irmp_pulse_time <= BANG_OLUFSEN_PULSE_LEN_MAX) { if (irmp_bit == 1) // Bang & Olufsen: 3rd bit { if (irmp_pause_time >= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_START_BIT3_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("3rd start bit\n"); wait_for_space = 0; irmp_bit++; } else { // timing incorrect! ANALYZE_PRINTF4 ("error 3a B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } else if (irmp_bit == 19) // Bang & Olufsen: trailer bit { if (irmp_pause_time >= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN_MAX) { ANALYZE_PRINTF1 ("trailer bit\n"); wait_for_space = 0; irmp_bit++; } else { // timing incorrect! ANALYZE_PRINTF4 ("error 3b B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } else { if (irmp_pause_time >= BANG_OLUFSEN_1_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_1_PAUSE_LEN_MAX) { // pulse & pause timings correct for "1"? ANALYZE_PUTCHAR ('1'); ANALYZE_NEWLINE (); irmp_store_bit (1); last_value = 1; wait_for_space = 0; } else if (irmp_pause_time >= BANG_OLUFSEN_0_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_0_PAUSE_LEN_MAX) { // pulse & pause timings correct for "0"? ANALYZE_PUTCHAR ('0'); ANALYZE_NEWLINE (); irmp_store_bit (0); last_value = 0; wait_for_space = 0; } else if (irmp_pause_time >= BANG_OLUFSEN_R_PAUSE_LEN_MIN && irmp_pause_time <= BANG_OLUFSEN_R_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR (last_value + '0'); ANALYZE_NEWLINE (); irmp_store_bit (last_value); wait_for_space = 0; } else { // timing incorrect! ANALYZE_PRINTF4 ("error 3c B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } } else { // timing incorrect! ANALYZE_PRINTF4 ("error 3d B&O: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } } else #endif // IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RCMM32_PROTOCOL) { if (irmp_pause_time >= RCMM32_BIT_00_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_00_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('0'); ANALYZE_PUTCHAR ('0'); irmp_store_bit (0); irmp_store_bit (0); } else if (irmp_pause_time >= RCMM32_BIT_01_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_01_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('0'); ANALYZE_PUTCHAR ('1'); irmp_store_bit (0); irmp_store_bit (1); } else if (irmp_pause_time >= RCMM32_BIT_10_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_10_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('1'); ANALYZE_PUTCHAR ('0'); irmp_store_bit (1); irmp_store_bit (0); } else if (irmp_pause_time >= RCMM32_BIT_11_PAUSE_LEN_MIN && irmp_pause_time <= RCMM32_BIT_11_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('1'); ANALYZE_PUTCHAR ('1'); irmp_store_bit (1); irmp_store_bit (1); } ANALYZE_PRINTF1 ("\n"); wait_for_space = 0; } else #endif if (irmp_pulse_time >= irmp_param.pulse_1_len_min && irmp_pulse_time <= irmp_param.pulse_1_len_max && irmp_pause_time >= irmp_param.pause_1_len_min && irmp_pause_time <= irmp_param.pause_1_len_max) { // pulse & pause timings correct for "1"? ANALYZE_PUTCHAR ('1'); ANALYZE_NEWLINE (); irmp_store_bit (1); wait_for_space = 0; } else if (irmp_pulse_time >= irmp_param.pulse_0_len_min && irmp_pulse_time <= irmp_param.pulse_0_len_max && irmp_pause_time >= irmp_param.pause_0_len_min && irmp_pause_time <= irmp_param.pause_0_len_max) { // pulse & pause timings correct for "0"? ANALYZE_PUTCHAR ('0'); ANALYZE_NEWLINE (); irmp_store_bit (0); wait_for_space = 0; } else #if IRMP_SUPPORT_KATHREIN_PROTOCOL if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && irmp_pulse_time >= KATHREIN_1_PULSE_LEN_MIN && irmp_pulse_time <= KATHREIN_1_PULSE_LEN_MAX && (((irmp_bit == 8 || irmp_bit == 6) && irmp_pause_time >= KATHREIN_SYNC_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_SYNC_BIT_PAUSE_LEN_MAX) || (irmp_bit == 12 && irmp_pause_time >= KATHREIN_START_BIT_PAUSE_LEN_MIN && irmp_pause_time <= KATHREIN_START_BIT_PAUSE_LEN_MAX))) { if (irmp_bit == 8) { irmp_bit++; ANALYZE_PUTCHAR ('S'); ANALYZE_NEWLINE (); irmp_tmp_command <<= 1; } else { ANALYZE_PUTCHAR ('S'); ANALYZE_NEWLINE (); irmp_store_bit (1); } wait_for_space = 0; } else #endif // IRMP_SUPPORT_KATHREIN_PROTOCOL #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC42_PROTOCOL && #else // IRMP_SUPPORT_NEC_PROTOCOL instead if (irmp_param.protocol == IRMP_NEC_PROTOCOL && #endif // IRMP_SUPPORT_NEC42_PROTOCOL == 1 ( (irmp_pulse_time >= MELINERA_0_PULSE_LEN_MIN && irmp_pulse_time <= MELINERA_0_PULSE_LEN_MAX && irmp_pause_time >= MELINERA_0_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_0_PAUSE_LEN_MAX) || (irmp_pulse_time >= MELINERA_1_PULSE_LEN_MIN && irmp_pulse_time <= MELINERA_1_PULSE_LEN_MAX && irmp_pause_time >= MELINERA_1_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_1_PAUSE_LEN_MAX) )) { ANALYZE_PRINTF1 ("Switching to MELINERA protocol "); irmp_param.protocol = IRMP_MELINERA_PROTOCOL; irmp_param.pulse_0_len_min = MELINERA_0_PULSE_LEN_MIN; irmp_param.pulse_0_len_max = MELINERA_0_PULSE_LEN_MAX; irmp_param.pause_0_len_min = MELINERA_0_PAUSE_LEN_MIN; irmp_param.pulse_0_len_max = MELINERA_0_PAUSE_LEN_MAX; irmp_param.pulse_1_len_min = MELINERA_1_PULSE_LEN_MIN; irmp_param.pulse_1_len_max = MELINERA_1_PULSE_LEN_MAX; irmp_param.pause_1_len_min = MELINERA_1_PAUSE_LEN_MIN; irmp_param.pulse_1_len_max = MELINERA_1_PAUSE_LEN_MAX; irmp_param.address_offset = MELINERA_ADDRESS_OFFSET; irmp_param.address_end = MELINERA_ADDRESS_OFFSET + MELINERA_ADDRESS_LEN; irmp_param.command_offset = MELINERA_COMMAND_OFFSET; irmp_param.command_end = MELINERA_COMMAND_OFFSET + MELINERA_COMMAND_LEN; irmp_param.complete_len = MELINERA_COMPLETE_DATA_LEN; if (irmp_pause_time >= MELINERA_0_PAUSE_LEN_MIN && irmp_pause_time <= MELINERA_0_PAUSE_LEN_MAX) { ANALYZE_PUTCHAR ('0'); irmp_store_bit (0); } else { ANALYZE_PUTCHAR ('1'); irmp_store_bit (1); } ANALYZE_NEWLINE (); wait_for_space = 0; } else #endif // IRMP_SUPPORT_MELINERA_PROTOCOL { // timing incorrect! ANALYZE_PRINTF4 ("error 3: timing not correct: data bit %d, pulse: %d, pause: %d\n", irmp_bit, irmp_pulse_time, irmp_pause_time); ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); irmp_start_bit_detected = 0; // reset flags and wait for next start bit irmp_pause_time = 0; } irmp_pulse_time = 1; // set counter to 1, not 0 } } else { // counting the pulse length ... if (! irmp_input) // still light? { // yes... irmp_pulse_time++; // increment counter } else { // now it's dark! wait_for_space = 1; // let's count the time (see above) irmp_pause_time = 1; // set pause counter to 1, not 0 #if IRMP_SUPPORT_RCII_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RCII_PROTOCOL && waiting_for_2nd_pulse) { // fm: output is "1000 466" or "1533 466" // printf ("fm: %d %d\n", irmp_pulse_time * 1000000 / F_INTERRUPTS, RCII_BIT_LEN * 1000000 / F_INTERRUPTS); irmp_pulse_time -= RCII_BIT_LEN; last_value = 0; ANALYZE_PRINTF2 ("RCII: got 2nd pulse, irmp_pulse_time = %d\n", irmp_pulse_time); waiting_for_2nd_pulse = 0; } #endif } } if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == 0) // enough bits received? { if (last_irmp_command == irmp_tmp_command && key_repetition_len < AUTO_FRAME_REPETITION_LEN) { repetition_frame_number++; } else { repetition_frame_number = 0; } #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 // if SIRCS protocol and the code will be repeated within 50 ms, we will ignore 2nd and 3rd repetition frame if (irmp_param.protocol == IRMP_SIRCS_PROTOCOL && (repetition_frame_number == 1 || repetition_frame_number == 2)) { ANALYZE_PRINTF4 ("code skipped: SIRCS auto repetition frame #%d, counter = %u, auto repetition len = %u\n", repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 // if ORTEK protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL && repetition_frame_number == 1) { ANALYZE_PRINTF4 ("code skipped: ORTEK auto repetition frame #%d, counter = %d, auto repetition len = %d\n", repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif #if 0 && IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame // if KASEIKYO protocol and the code will be repeated within 50 ms, we will ignore 2nd repetition frame if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL && repetition_frame_number == 1) { ANALYZE_PRINTF4 ("code skipped: KASEIKYO auto repetition frame #%d, counter = %d, auto repetition len = %d\n", repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif #if 0 && IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 // fm 2015-12-02: don't ignore every 2nd frame // if SAMSUNG32 or SAMSUNG48 protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame if ((irmp_param.protocol == IRMP_SAMSUNG32_PROTOCOL || irmp_param.protocol == IRMP_SAMSUNG48_PROTOCOL) && (repetition_frame_number & 0x01)) { ANALYZE_PRINTF4 ("code skipped: SAMSUNG32/SAMSUNG48 auto repetition frame #%d, counter = %d, auto repetition len = %d\n", repetition_frame_number + 1, key_repetition_len, AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 // if NUBERT protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame if (irmp_param.protocol == IRMP_NUBERT_PROTOCOL && (repetition_frame_number & 0x01)) { ANALYZE_PRINTF4 ("code skipped: NUBERT auto repetition frame #%d, counter = %u, auto repetition len = %u\n", repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif #if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 // if SPEAKER protocol and the code will be repeated within 50 ms, we will ignore every 2nd frame if (irmp_param.protocol == IRMP_SPEAKER_PROTOCOL && (repetition_frame_number & 0x01)) { ANALYZE_PRINTF4 ("code skipped: SPEAKER auto repetition frame #%d, counter = %u, auto repetition len = %u\n", repetition_frame_number + 1, (unsigned int) key_repetition_len, (unsigned int) AUTO_FRAME_REPETITION_LEN); key_repetition_len = 0; } else #endif { ANALYZE_PRINTF3 ("%8.3fms code detected, length = %d\n", (double) (time_counter * 1000) / F_INTERRUPTS, irmp_bit); irmp_ir_detected = TRUE; #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 if (irmp_param.protocol == IRMP_KATHREIN_PROTOCOL && irmp_tmp_command == 0x0000) { if (irmp_tmp_command == 0x0000) // KATHREIN sends key release with command = 0x0000, ignore it { ANALYZE_PRINTF1 ("got KATHREIN release command, ignore it\n"); irmp_ir_detected = FALSE; } } else #endif // IRMP_SUPPORT_KATHREIN_PROTOCOL #if IRMP_SUPPORT_DENON_PROTOCOL == 1 if (irmp_param.protocol == IRMP_DENON_PROTOCOL) { // check for repetition frame if ((~irmp_tmp_command & 0x3FF) == last_irmp_denon_command) // command bits must be inverted { irmp_tmp_command = last_irmp_denon_command; // use command received before! last_irmp_denon_command = 0; irmp_protocol = irmp_param.protocol; // store protocol irmp_address = irmp_tmp_address; // store address irmp_command = irmp_tmp_command; // store command } else { if ((irmp_tmp_command & 0x01) == 0x00) { ANALYZE_PRINTF2 ("%8.3fms info Denon: waiting for inverted command repetition\n", (double) (time_counter * 1000) / F_INTERRUPTS); last_irmp_denon_command = irmp_tmp_command; denon_repetition_len = 0; irmp_ir_detected = FALSE; } else { ANALYZE_PRINTF2 ("%8.3fms warning Denon: got unexpected inverted command, ignoring it\n", (double) (time_counter * 1000) / F_INTERRUPTS); last_irmp_denon_command = 0; irmp_ir_detected = FALSE; } } } else #endif // IRMP_SUPPORT_DENON_PROTOCOL #if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 if (irmp_param.protocol == IRMP_GRUNDIG_PROTOCOL && irmp_tmp_command == 0x01ff) { // Grundig start frame? ANALYZE_PRINTF1 ("Detected GRUNDIG start frame, ignoring it\n"); irmp_ir_detected = FALSE; } else #endif // IRMP_SUPPORT_GRUNDIG_PROTOCOL #if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NOKIA_PROTOCOL && irmp_tmp_address == 0x00ff && irmp_tmp_command == 0x00fe) { // Nokia start frame? ANALYZE_PRINTF1 ("Detected NOKIA start frame, ignoring it\n"); irmp_ir_detected = FALSE; } else #endif // IRMP_SUPPORT_NOKIA_PROTOCOL { #if IRMP_SUPPORT_NEC_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC_PROTOCOL && irmp_bit == 0) // repetition frame { if (key_repetition_len < NEC_FRAME_REPEAT_PAUSE_LEN_MAX) { ANALYZE_PRINTF2 ("Detected NEC repetition frame, key_repetition_len = %u\n", (unsigned int) key_repetition_len); ANALYZE_ONLY_NORMAL_PRINTF1("REPETETION FRAME "); irmp_tmp_address = last_irmp_address; // address is last address irmp_tmp_command = last_irmp_command; // command is last command irmp_flags |= IRMP_FLAG_REPETITION; key_repetition_len = 0; } else { ANALYZE_PRINTF3 ("Detected NEC repetition frame, ignoring it: timeout occured, key_repetition_len = %u > %u\n", (unsigned int) key_repetition_len, (unsigned int) NEC_FRAME_REPEAT_PAUSE_LEN_MAX); irmp_ir_detected = FALSE; } } #endif // IRMP_SUPPORT_NEC_PROTOCOL #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 if (irmp_param.protocol == IRMP_KASEIKYO_PROTOCOL) { uint_fast8_t xor_value; xor_value = (xor_check[0] & 0x0F) ^ ((xor_check[0] & 0xF0) >> 4) ^ (xor_check[1] & 0x0F) ^ ((xor_check[1] & 0xF0) >> 4); if (xor_value != (xor_check[2] & 0x0F)) { ANALYZE_PRINTF3 ("error 4: wrong XOR check for customer id: 0x%1x 0x%1x\n", xor_value, xor_check[2] & 0x0F); irmp_ir_detected = FALSE; } xor_value = xor_check[2] ^ xor_check[3] ^ xor_check[4]; if (xor_value != xor_check[5]) { ANALYZE_PRINTF3 ("error 5: wrong XOR check for data bits: 0x%02x 0x%02x\n", xor_value, xor_check[5]); irmp_ir_detected = FALSE; } irmp_flags |= genre2; // write the genre2 bits into MSB of the flag byte } #endif // IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 if (irmp_param.protocol == IRMP_ORTEK_PROTOCOL) { if (parity == PARITY_CHECK_FAILED) { ANALYZE_PRINTF1 ("error 6: parity check failed\n"); irmp_ir_detected = FALSE; } if ((irmp_tmp_address & 0x03) == 0x02) { ANALYZE_PRINTF1 ("code skipped: ORTEK end of transmission frame (key release)\n"); irmp_ir_detected = FALSE; } irmp_tmp_address >>= 2; } #endif // IRMP_SUPPORT_ORTEK_PROTOCOL == 1 #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 if (irmp_param.protocol == IRMP_MITSU_HEAVY_PROTOCOL) { check = irmp_tmp_command >> 8; // inverted upper byte == lower byte? check = ~ check; if (check == (irmp_tmp_command & 0xFF)) { //ok: irmp_tmp_command &= 0xFF; } else mitsu_parity = PARITY_CHECK_FAILED; if (mitsu_parity == PARITY_CHECK_FAILED) { ANALYZE_PRINTF1 ("error 7: parity check failed\n"); irmp_ir_detected = FALSE; } } #endif // IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL #if IRMP_SUPPORT_RC6_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_LONG) // RC6 mode = 6? { irmp_protocol = IRMP_RC6A_PROTOCOL; } else if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_20) // RC6 mode = 6? { irmp_protocol = IRMP_RC6A20_PROTOCOL; } else if (irmp_param.protocol == IRMP_RC6_PROTOCOL && irmp_param.complete_len == RC6_COMPLETE_DATA_LEN_28) // RC6 mode = 6? { irmp_protocol = IRMP_RC6A28_PROTOCOL; } else #endif // IRMP_SUPPORT_RC6_PROTOCOL == 1 { irmp_protocol = irmp_param.protocol; } #if IRMP_SUPPORT_FDC_PROTOCOL == 1 if (irmp_param.protocol == IRMP_FDC_PROTOCOL) { if (irmp_tmp_command & 0x000F) // released key? { irmp_tmp_command = (irmp_tmp_command >> 4) | 0x80; // yes, set bit 7 } else { irmp_tmp_command >>= 4; // no, it's a pressed key } irmp_tmp_command |= (irmp_tmp_address << 2) & 0x0F00; // 000000CCCCAAAAAA -> 0000CCCC00000000 irmp_tmp_address &= 0x003F; } #endif irmp_address = irmp_tmp_address; // store address #if IRMP_SUPPORT_NEC_PROTOCOL == 1 if (irmp_param.protocol == IRMP_NEC_PROTOCOL) { last_irmp_address = irmp_tmp_address; // store as last address, too } #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 if (irmp_param.protocol == IRMP_RC5_PROTOCOL) { irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 } #endif #if IRMP_SUPPORT_S100_PROTOCOL == 1 if (irmp_param.protocol == IRMP_S100_PROTOCOL) { irmp_tmp_command |= rc5_cmd_bit6; // store bit 6 } #endif irmp_command = irmp_tmp_command; // store command #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 irmp_id = irmp_tmp_id; #endif } } if (irmp_ir_detected) { if (last_irmp_command == irmp_tmp_command && last_irmp_address == irmp_tmp_address && #if IRMP_AUTODETECT_REPEATRATE irmp_protocol == previous_irmp_protocol) { same_key = 1; } pass_on_delta_detection = delta_detection; delta_detection = 0; #else key_repetition_len < IRMP_KEY_REPETITION_LEN) // time after data frame, not total since start { irmp_flags |= IRMP_FLAG_REPETITION; } #endif last_irmp_address = irmp_tmp_address; // store as last address, too last_irmp_command = irmp_tmp_command; // store as last command, too #if IRMP_ENABLE_RELEASE_DETECTION == 1 key_released = FALSE; #endif key_repetition_len = 0; } else { ANALYZE_ONLY_NORMAL_PUTCHAR ('\n'); } irmp_start_bit_detected = 0; // and wait for next start bit irmp_tmp_command = 0; irmp_pulse_time = 0; irmp_pause_time = 0; #if IRMP_SUPPORT_JVC_PROTOCOL == 1 if (irmp_protocol == IRMP_JVC_PROTOCOL) // the stop bit of JVC frame is also start bit of next frame { // set pulse time here! irmp_pulse_time = ((uint_fast8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME)); } #endif // IRMP_SUPPORT_JVC_PROTOCOL == 1 } } } #if defined(STELLARIS_ARM_CORTEX_M4) // Clear the timer interrupt TimerIntClear(TIMER1_BASE, TIMER_TIMA_TIMEOUT); #endif #if (defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_)) && IRMP_USE_EVENT == 1 if (IRMP_EVENT_THREAD_PTR != nullptr && irmp_ir_detected) chEvtSignalI(IRMP_EVENT_THREAD_PTR,IRMP_EVENT_BIT); #endif #if IRMP_USE_COMPLETE_CALLBACK == 1 if (irmp_complete_callback_function != nullptr && irmp_ir_detected) { irmp_complete_callback_function(); } #endif #if IRMP_USE_IDLE_CALL == 1 // check if there is no ongoing transmission or repetition if (!irmp_start_bit_detected && !irmp_pulse_time && key_repetition_len > IRMP_KEY_REPETITION_LEN) { // no ongoing transmission // enough time passed since last decoded signal that a repetition won't affect our output irmp_idle(); } #endif // IRMP_USE_IDLE_CALL return (irmp_ir_detected); } #if defined(ANALYZE) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * main functions - for Unix/Linux + Windows only! * * AVR: see main.c! * * Compile it under linux with: * cc irmp.c -o irmp * * usage: ./irmp [-v|-s|-a|-l] < file * * options: * -v verbose * -s silent * -a analyze * -l list pulse/pauses *--------------------------------------------------------------------------------------------------------------------------------------------------- */ void print_spectrum (const char *text, int *buf, int is_pulse) { int i; int j; int min; int max; int max_value = 0; int value; int sum = 0; int counter = 0; double average = 0; double tolerance; puts ("-----------------------------------------------------------------------------"); printf ("%s:\n", text); for (i = 0; i < 256; i++) { if (buf[i] > max_value) { max_value = buf[i]; } } for (i = 1; i < 200; i++) { if (buf[i] > 0) { printf ("%3d ", i); value = (buf[i] * 60) / max_value; for (j = 0; j < value; j++) { putchar ('o'); } printf (" %d\n", buf[i]); sum += i * buf[i]; counter += buf[i]; } else { max = i - 1; if (counter > 0) { average = (float) sum / (float) counter; if (is_pulse) { printf ("pulse "); } else { printf ("pause "); } printf ("avg: %4.1f=%6.1f us, ", average, (1000000. * average) / (float) F_INTERRUPTS); printf ("min: %2d=%6.1f us, ", min, (1000000. * min) / (float) F_INTERRUPTS); printf ("max: %2d=%6.1f us, ", max, (1000000. * max) / (float) F_INTERRUPTS); tolerance = (max - average); if (average - min > tolerance) { tolerance = average - min; } tolerance = tolerance * 100 / average; printf ("tol: %4.1f%%\n", tolerance); } counter = 0; sum = 0; min = i + 1; } } } #define STATE_LEFT_SHIFT 0x01 #define STATE_RIGHT_SHIFT 0x02 #define STATE_LEFT_CTRL 0x04 #define STATE_LEFT_ALT 0x08 #define STATE_RIGHT_ALT 0x10 #define KEY_ESCAPE 0x1B // keycode = 0x006e #define KEY_MENUE 0x80 // keycode = 0x0070 #define KEY_BACK 0x81 // keycode = 0x0071 #define KEY_FORWARD 0x82 // keycode = 0x0072 #define KEY_ADDRESS 0x83 // keycode = 0x0073 #define KEY_WINDOW 0x84 // keycode = 0x0074 #define KEY_1ST_PAGE 0x85 // keycode = 0x0075 #define KEY_STOP 0x86 // keycode = 0x0076 #define KEY_MAIL 0x87 // keycode = 0x0077 #define KEY_FAVORITES 0x88 // keycode = 0x0078 #define KEY_NEW_PAGE 0x89 // keycode = 0x0079 #define KEY_SETUP 0x8A // keycode = 0x007a #define KEY_FONT 0x8B // keycode = 0x007b #define KEY_PRINT 0x8C // keycode = 0x007c #define KEY_ON_OFF 0x8E // keycode = 0x007c #define KEY_INSERT 0x90 // keycode = 0x004b #define KEY_DELETE 0x91 // keycode = 0x004c #define KEY_LEFT 0x92 // keycode = 0x004f #define KEY_HOME 0x93 // keycode = 0x0050 #define KEY_END 0x94 // keycode = 0x0051 #define KEY_UP 0x95 // keycode = 0x0053 #define KEY_DOWN 0x96 // keycode = 0x0054 #define KEY_PAGE_UP 0x97 // keycode = 0x0055 #define KEY_PAGE_DOWN 0x98 // keycode = 0x0056 #define KEY_RIGHT 0x99 // keycode = 0x0059 #define KEY_MOUSE_1 0x9E // keycode = 0x0400 #define KEY_MOUSE_2 0x9F // keycode = 0x0800 static uint_fast8_t get_fdc_key (uint_fast16_t cmd) { static const uint8_t key_table[128] = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x00, '^', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 0xDF, 0xB4, 0x00, '\b', '\t', 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', 'o', 'p', 0xFC, '+', 0x00, 0x00, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0xF6, 0xE4, '#', '\r', 0x00, '<', 'y', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '-', 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00, 0x00, 0xB0, '!', '"', 0xA7, '$', '%', '&', '/', '(', ')', '=', '?', 0x60, 0x00, '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', 'O', 'P', 0xDC, '*', 0x00, 0x00, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0xD6, 0xC4, '\'', '\r', 0x00, '>', 'Y', 'X', 'C', 'V', 'B', 'N', 'M', ';', ':', '_', 0x00, 0x00, 0x00, 0x00, 0x00, ' ', 0x00, 0x00 }; static uint_fast8_t state; uint_fast8_t key = 0; switch (cmd) { case 0x002C: state |= STATE_LEFT_SHIFT; break; // pressed left shift case 0x00AC: state &= ~STATE_LEFT_SHIFT; break; // released left shift case 0x0039: state |= STATE_RIGHT_SHIFT; break; // pressed right shift case 0x00B9: state &= ~STATE_RIGHT_SHIFT; break; // released right shift case 0x003A: state |= STATE_LEFT_CTRL; break; // pressed left ctrl case 0x00BA: state &= ~STATE_LEFT_CTRL; break; // released left ctrl case 0x003C: state |= STATE_LEFT_ALT; break; // pressed left alt case 0x00BC: state &= ~STATE_LEFT_ALT; break; // released left alt case 0x003E: state |= STATE_RIGHT_ALT; break; // pressed left alt case 0x00BE: state &= ~STATE_RIGHT_ALT; break; // released left alt case 0x006e: key = KEY_ESCAPE; break; case 0x004b: key = KEY_INSERT; break; case 0x004c: key = KEY_DELETE; break; case 0x004f: key = KEY_LEFT; break; case 0x0050: key = KEY_HOME; break; case 0x0051: key = KEY_END; break; case 0x0053: key = KEY_UP; break; case 0x0054: key = KEY_DOWN; break; case 0x0055: key = KEY_PAGE_UP; break; case 0x0056: key = KEY_PAGE_DOWN; break; case 0x0059: key = KEY_RIGHT; break; case 0x0400: key = KEY_MOUSE_1; break; case 0x0800: key = KEY_MOUSE_2; break; default: { if (!(cmd & 0x80)) // pressed key { if (cmd >= 0x70 && cmd <= 0x7F) // function keys { key = cmd + 0x10; // 7x -> 8x } else if (cmd < 64) // key listed in key_table { if (state & (STATE_LEFT_ALT | STATE_RIGHT_ALT)) { switch (cmd) { case 0x0003: key = 0xB2; break; // upper 2 case 0x0008: key = '{'; break; case 0x0009: key = '['; break; case 0x000A: key = ']'; break; case 0x000B: key = '}'; break; case 0x000C: key = '\\'; break; case 0x001C: key = '~'; break; case 0x002D: key = '|'; break; case 0x0034: key = 0xB5; break; // Mu } } else if (state & (STATE_LEFT_CTRL)) { if (key_table[cmd] >= 'a' && key_table[cmd] <= 'z') { key = key_table[cmd] - 'a' + 1; } else { key = key_table[cmd]; } } else { int idx = cmd + ((state & (STATE_LEFT_SHIFT | STATE_RIGHT_SHIFT)) ? 64 : 0); if (key_table[idx]) { key = key_table[idx]; } } } } break; } } return (key); } static int analyze = FALSE; static int list = FALSE; static IRMP_DATA irmp_data; static int expected_protocol; static int expected_address; static int expected_command; static int do_check_expected_values; static void next_tick (void) { if (! analyze && ! list) { (void) irmp_ISR (); if (irmp_get_data (&irmp_data)) { uint_fast8_t key; ANALYZE_ONLY_NORMAL_PUTCHAR (' '); if (verbose) { printf ("%8.3fms ", (double) (time_counter * 1000) / F_INTERRUPTS); } if (irmp_data.protocol == IRMP_ACP24_PROTOCOL) { uint16_t temp = (irmp_data.command & 0x000F) + 15; printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, temp=%d", irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, temp); } else if (irmp_data.protocol == IRMP_FDC_PROTOCOL && (key = get_fdc_key (irmp_data.command)) != 0) { if ((key >= 0x20 && key < 0x7F) || key >= 0xA0) { printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key='%c'", irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, key); } else if (key == '\r' || key == '\t' || key == KEY_ESCAPE || (key >= 0x80 && key <= 0x9F)) // function keys { const char * p = (const char *) nullptr; switch (key) { case '\t' : p = "TAB"; break; case '\r' : p = "CR"; break; case KEY_ESCAPE : p = "ESCAPE"; break; case KEY_MENUE : p = "MENUE"; break; case KEY_BACK : p = "BACK"; break; case KEY_FORWARD : p = "FORWARD"; break; case KEY_ADDRESS : p = "ADDRESS"; break; case KEY_WINDOW : p = "WINDOW"; break; case KEY_1ST_PAGE : p = "1ST_PAGE"; break; case KEY_STOP : p = "STOP"; break; case KEY_MAIL : p = "MAIL"; break; case KEY_FAVORITES : p = "FAVORITES"; break; case KEY_NEW_PAGE : p = "NEW_PAGE"; break; case KEY_SETUP : p = "SETUP"; break; case KEY_FONT : p = "FONT"; break; case KEY_PRINT : p = "PRINT"; break; case KEY_ON_OFF : p = "ON_OFF"; break; case KEY_INSERT : p = "INSERT"; break; case KEY_DELETE : p = "DELETE"; break; case KEY_LEFT : p = "LEFT"; break; case KEY_HOME : p = "HOME"; break; case KEY_END : p = "END"; break; case KEY_UP : p = "UP"; break; case KEY_DOWN : p = "DOWN"; break; case KEY_PAGE_UP : p = "PAGE_UP"; break; case KEY_PAGE_DOWN : p = "PAGE_DOWN"; break; case KEY_RIGHT : p = "RIGHT"; break; case KEY_MOUSE_1 : p = "KEY_MOUSE_1"; break; case KEY_MOUSE_2 : p = "KEY_MOUSE_2"; break; default : p = ""; break; } printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x, key=%s", irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key, p); } else { printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x, asc=0x%02x", irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags, key); } } else { printf ("p=%2d (%s), a=0x%04x, c=0x%04x, f=0x%02x", irmp_data.protocol, irmp_protocol_names[irmp_data.protocol], irmp_data.address, irmp_data.command, irmp_data.flags); } if (do_check_expected_values) { if (irmp_data.protocol != expected_protocol || irmp_data.address != expected_address || irmp_data.command != expected_command) { printf ("\nerror 7: expected values differ: p=%2d (%s), a=0x%04x, c=0x%04x\n", expected_protocol, irmp_protocol_names[expected_protocol], expected_address, expected_command); } else { printf (" checked!\n"); } do_check_expected_values = FALSE; // only check 1st frame in a line! } else { putchar ('\n'); } } } } int main (int argc, char ** argv) { int i; int ch; int last_ch = 0; int pulse = 0; int pause = 0; int start_pulses[256]; int start_pauses[256]; int pulses[256]; int pauses[256]; int first_pulse = TRUE; int first_pause = TRUE; if (argc == 2) { if (! strcmp (argv[1], "-v")) { verbose = TRUE; } else if (! strcmp (argv[1], "-l")) { list = TRUE; } else if (! strcmp (argv[1], "-a")) { analyze = TRUE; } else if (! strcmp (argv[1], "-s")) { silent = TRUE; } } for (i = 0; i < 256; i++) { start_pulses[i] = 0; start_pauses[i] = 0; pulses[i] = 0; pauses[i] = 0; } if (IRMP_HIGH_ACTIVE) { IRMP_PIN = 0x00; } else { IRMP_PIN = 0xFF; } while ((ch = getchar ()) != EOF) { if (ch == '_' || ch == '0') { if (last_ch != ch) { if (pause > 0) { if (list) { printf ("pause: %d\n", pause); } if (analyze) { if (first_pause) { if (pause < 256) { start_pauses[pause]++; } first_pause = FALSE; } else { if (pause < 256) { pauses[pause]++; } } } } pause = 0; } pulse++; if (IRMP_HIGH_ACTIVE) { IRMP_PIN = 0xff; } else { IRMP_PIN = 0x00; } } else if (ch == 0xaf || ch == '-' || ch == '1') { if (last_ch != ch) { if (list) { printf ("pulse: %d ", pulse); } if (analyze) { if (first_pulse) { if (pulse < 256) { start_pulses[pulse]++; } first_pulse = FALSE; } else { if (pulse < 256) { pulses[pulse]++; } } } pulse = 0; } pause++; if (IRMP_HIGH_ACTIVE) { IRMP_PIN = 0x00; } else { IRMP_PIN = 0xff; } } else if (ch == '\n') { if (IRMP_HIGH_ACTIVE) { IRMP_PIN = 0x00; } else { IRMP_PIN = 0xff; } time_counter = 0; if (list && pause > 0) { printf ("pause: %d\n", pause); } pause = 0; if (! analyze) { for (i = 0; i < (int) ((10000.0 * F_INTERRUPTS) / 10000); i++) // newline: long pause of 10000 msec { next_tick (); } } first_pulse = TRUE; first_pause = TRUE; } else if (ch == '#') { time_counter = 0; if (analyze) { while ((ch = getchar()) != '\n' && ch != EOF) { ; } } else { char buf[1024]; char * p; int idx = -1; puts ("----------------------------------------------------------------------"); putchar (ch); while ((ch = getchar()) != '\n' && ch != EOF) { if (ch != '\r') // ignore CR in DOS/Windows files { if (ch == '[' && idx == -1) { idx = 0; } else if (idx >= 0) { if (ch == ']') { do_check_expected_values = FALSE; buf[idx] = '\0'; idx = -1; expected_protocol = atoi (buf); if (expected_protocol > 0) { p = buf; while (*p) { if (*p == 'x') { p++; if (sscanf (p, "%x", &expected_address) == 1) { do_check_expected_values = TRUE; } break; } p++; } if (do_check_expected_values) { do_check_expected_values = FALSE; while (*p) { if (*p == 'x') { p++; if (sscanf (p, "%x", &expected_command) == 1) { do_check_expected_values = TRUE; } break; } p++; } if (do_check_expected_values) { // printf ("!%2d %04x %04x!\n", expected_protocol, expected_address, expected_command); } } } } else if (idx < 1024 - 2) { buf[idx++] = ch; } } putchar (ch); } } putchar ('\n'); } } last_ch = ch; next_tick (); } if (analyze) { print_spectrum ("START PULSES", start_pulses, TRUE); print_spectrum ("START PAUSES", start_pauses, FALSE); print_spectrum ("PULSES", pulses, TRUE); print_spectrum ("PAUSES", pauses, FALSE); puts ("-----------------------------------------------------------------------------"); } return 0; } #endif // ANALYZE ================================================ FILE: src/irmpArduinoExt.h ================================================ /* * irmpArduinoExt.h Arduino extensions to the original irmp.h * * Copyright (C) 2020 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 . * */ #if defined(ARDUINO) #ifndef _IRMP_ARDUINO_EXT_H #define _IRMP_ARDUINO_EXT_H #include // for Print #include "irmpVersion.h" #include "IRFeedbackLED.h" // for redefinition of #include "digitalWriteFast.h" // we use pinModeFast() and digitalReadFast() and digitalWriteFast() in turn /* * For debugging purposes. The timing test pin for some platforms is specified in the PinDefinitionsAndMore.h files included in each example. */ //#define IRMP_MEASURE_TIMING //#define IR_TIMING_TEST_PIN // /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Enable dynamic pin configuration in contrast to the static one which is known at compile time and saves program memory and CPU cycles. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ //#define IRMP_IRSND_ALLOW_DYNAMIC_PINS // // /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Enable PinChangeInterrupt add on for irmp_ISR(). Tested for NEC, Kaseiko, Denon, RC6 protocols and Arduino Uno and Arduino ATmega. * Receives IR protocol data by using pin change interrupts and no polling by timer. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ //#define IRMP_ENABLE_PIN_CHANGE_INTERRUPT #if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) # if ! (defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)) /* ATtinyX5 */ \ && ! ( (defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && ( (defined(ARDUINO_AVR_DIGISPARKPRO) && ((IRMP_INPUT_PIN == 3) || (IRMP_INPUT_PIN == 9))) /*ATtinyX7(digisparkpro) and pin 3 or 9 */\ || (! defined(ARDUINO_AVR_DIGISPARKPRO) && ((IRMP_INPUT_PIN == 3) || (IRMP_INPUT_PIN == 14)))) ) /*ATtinyX7(ATTinyCore) and pin 3 or 14 */ \ && ! ( ( defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__) \ || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) \ || defined(__AVR_ATmega8__) || defined(__AVR_ATmega48__) || defined(__AVR_ATmega48P__) || defined(__AVR_ATmega48PB__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__) \ || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168PA__) || defined(__AVR_ATmega168PB__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)) \ && ((IRMP_INPUT_PIN == 2) || (IRMP_INPUT_PIN == 3)) ) /* ATmegas and pin 2 or 3 */ # define IRMP_USE_ARDUINO_ATTACH_INTERRUPT // cannot use any static ISR vector here # endif # undef F_INTERRUPTS # define F_INTERRUPTS 15625 // 15625 interrupts per second gives 64 us period #endif #if defined(__AVR__) #define uint_fast8_t uint8_t #define uint_fast16_t uint16_t #elif defined(ESP8266) #include "ets_sys.h" #include "osapi.h" #include "gpio.h" #include "os_type.h" #include "c_types.h" #elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 #include "mbed.h" #elif defined(ESP32) #elif defined(STM32F1xx) // for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager #elif defined(ARDUINO_ARCH_STM32) // Untested! use settings from BluePill / STM32F1xx #elif defined(__STM32F1__) // for "Generic STM32F103C series" from "STM32F1 Boards (STM32duino.com)" of Arduino Board manager #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for Arduino IDE if no IRMP_INPUT_PIN specified * Should be first, since it covers multiple platforms *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) extern uint_fast8_t irmp_InputPin; // global variable to hold input pin number. Is referenced by defining IRMP_INPUT_PIN as irmp_InputPin. #undef IRMP_INPUT_PIN #define IRMP_INPUT_PIN irmp_InputPin #else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) # if !defined(IRMP_INPUT_PIN) // Arduino IDE uses IRMP_INPUT_PIN instead of PORT and BIT #define IRMP_INPUT_PIN 2 # endif #endif #if defined(IRMP_INPUT_PIN) # if defined(__AVR__) # define input(x) (__builtin_constant_p(IRMP_INPUT_PIN) ) ? digitalReadFast(IRMP_INPUT_PIN) : digitalRead(IRMP_INPUT_PIN) # else # define input(x) digitalRead(IRMP_INPUT_PIN) # endif #endif #if !defined(IR_TIMING_TEST_PIN) // Only for test purposes #define IR_TIMING_TEST_PIN 5 #endif 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); bool irmp_IsBusy(); extern uint32_t irmp_last_change_micros; void irmp_result_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr); void irmp_result_print(IRMP_DATA *aIRMPDataPtr); void irmp_PCI_ISR(void); void enablePCIInterrupt(void); void disablePCIInterrupt(void); void irmp_print_active_protocols(Print *aSerial); void irmp_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber); extern const uint8_t irmp_used_protocol_index[] PROGMEM; extern const char *const irmp_used_protocol_names[] PROGMEM; #endif // _IRMP_ARDUINO_EXT_H #endif // ARDUINO ================================================ FILE: src/irmpArduinoExt.hpp ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpArduinoExt.hpp - Arduino extensions to the original irmp.c * * Copyright (c) 2019-2020 Armin Joachimsmeyer * * This file is part of IRMP https://github.com/IRMP-org/IRMP. * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // // Must be included after declaration of irmp_start_bit_detected etc. #if defined(ARDUINO) #undef _IRSND_H_ // We are in IRMP now! Remove old symbol maybe set from former including irsnd.hpp. #include "IRTimer.hpp" // include code for timer #include "IRFeedbackLED.hpp" // include code for Feedback LED #include "irmpprotocols.hpp" // include protocol strings and array of strings #if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) #include "irmpPinChangeInterrupt.hpp" #endif // defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) uint_fast8_t irmp_InputPin; // global variable to hold input pin number. Is referenced by defining IRMP_INPUT_PIN as irmp_InputPin. /* * Initialize, and activate feedback LED function */ void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow) { irmp_InputPin = aIrmpInputPin; #if !defined(NO_LED_FEEDBACK_CODE) irmp_irsnd_LedFeedbackPin = aFeedbackLedPin; irmp_irsnd_LedFeedbackPinIsActiveLow = aIrmpLedFeedbackPinIsActiveLow; /* * enable feedback LED if (aFeedbackLedPin != 0) */ irmp_irsnd_LEDFeedback(aFeedbackLedPin); #else (void) aFeedbackLedPin; // to avoid compiler warnings (void) aIrmpLedFeedbackPinIsActiveLow; // to avoid compiler warnings #endif # if defined IRMP_ENABLE_PIN_CHANGE_INTERRUPT enablePCIInterrupt(); # else initIRTimerForReceive(); # endif # if defined(IRMP_MEASURE_TIMING) pinModeFast(IR_TIMING_TEST_PIN, OUTPUT); # endif } /* * Initialize, and activate feedback LED function * @param irmp_irsnd_LedFeedbackPin if 0 feedback led is not activated */ void irmp_init(uint_fast8_t aIrmpInputPin, uint_fast8_t aFeedbackLedPin) { #if defined(NO_LED_FEEDBACK_CODE) irmp_init(aIrmpInputPin, aFeedbackLedPin, false); #else irmp_init(aIrmpInputPin, aFeedbackLedPin, irmp_irsnd_LedFeedbackPinIsActiveLow); #endif } /* * Initialize, but do not activate feedback LED by default, using irmp_irsnd_LedFeedbackPin as led pin. */ void irmp_init(uint_fast8_t aIrmpInputPin) { #if defined(NO_LED_FEEDBACK_CODE) irmp_init(aIrmpInputPin, 0, false); #else irmp_init(aIrmpInputPin, irmp_irsnd_LedFeedbackPin, irmp_irsnd_LedFeedbackPinIsActiveLow); #endif # if defined(IRMP_FEEDBACK_LED_PIN) // set pin if we have one at hand irmp_irsnd_LedFeedbackPin = IRMP_FEEDBACK_LED_PIN; # endif } #endif // if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) void irmp_init(void) { # if defined(IRMP_INPUT_PIN) pinModeFast(IRMP_INPUT_PIN, INPUT); // set pin to input # else IRMP_PORT &= ~_BV(IRMP_BIT); // deactivate pullup IRMP_DDR &= ~_BV(IRMP_BIT);// set pin to input # endif # if defined IRMP_ENABLE_PIN_CHANGE_INTERRUPT enablePCIInterrupt(); # else initIRTimerForReceive(); # endif # if defined(IRMP_MEASURE_TIMING) pinModeFast(IR_TIMING_TEST_PIN, OUTPUT); # endif } /* * Called from the receiver ISR IRMP_ISR() with the raw input value. Receiver signal input is active low! * With -oS it is taken as inline function */ #if defined(ESP8266) || defined(ESP32) void IRAM_ATTR irmp_DoLEDFeedback(bool aSwitchLedOff) #else void irmp_DoLEDFeedback(bool aSwitchLedOff) #endif { #if !defined(NO_LED_FEEDBACK_CODE) if (irmp_irsnd_LedFeedbackEnabled) { irmp_irsnd_SetFeedbackLED(!aSwitchLedOff); } #else (void) aSwitchLedOff; // to avoid compiler warnings #endif } /* * returns true, if there is an ongoing transmission or repetition */ bool irmp_IsBusy() { #if defined(IRMP_ENABLE_PIN_CHANGE_INTERRUPT) uint32_t tTicks = micros() - irmp_last_change_micros; tTicks = (tTicks << 2) >> 8; return (irmp_start_bit_detected || irmp_pulse_time || tTicks <= IRMP_KEY_REPETITION_LEN); #else return (irmp_start_bit_detected || irmp_pulse_time || key_repetition_len <= IRMP_KEY_REPETITION_LEN); #endif } /* * irmp_used_protocol_index holds the protocol numbers (from irmpprotocols.h) * for the included protocol name entries of the irmp_used_protocol_names array below * E.g. irmp_used_protocol_index=2,7 and irmp_used_protocol_names="NEC","RC5". * * Both arrays together are generally smaller than the complete irmp_protocol_names array * allowing them to be used on ATtinies even if program code for access is bigger. * Flash size is more than 100 bytes less (for 15 protocols) using these arrays. */ const uint8_t irmp_used_protocol_index[] PROGMEM = { IRMP_UNKNOWN_PROTOCOL, #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 IRMP_SIRCS_PROTOCOL, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 IRMP_NEC_PROTOCOL, #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 IRMP_SAMSUNG_PROTOCOL, #endif #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 IRMP_MATSUSHITA_PROTOCOL, #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 IRMP_KASEIKYO_PROTOCOL, #endif #if IRMP_SUPPORT_RECS80_PROTOCOL == 1 IRMP_RECS80_PROTOCOL, #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 IRMP_RC5_PROTOCOL, #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 IRMP_DENON_PROTOCOL, #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 IRMP_RC6_PROTOCOL, #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 IRMP_SAMSUNG32_PROTOCOL, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 IRMP_APPLE_PROTOCOL, #endif #if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 IRMP_RECS80EXT_PROTOCOL, #endif #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 IRMP_NUBERT_PROTOCOL, #endif #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 IRMP_BANG_OLUFSEN_PROTOCOL, #endif #if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 IRMP_GRUNDIG_PROTOCOL, #endif #if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 IRMP_NOKIA_PROTOCOL, #endif #if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 IRMP_SIEMENS_PROTOCOL, #endif #if IRMP_SUPPORT_FDC_PROTOCOL == 1 IRMP_FDC_PROTOCOL, #endif #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 IRMP_RCCAR_PROTOCOL, #endif #if IRMP_SUPPORT_JVC_PROTOCOL == 1 IRMP_JVC_PROTOCOL, #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 IRMP_RC6A_PROTOCOL, #endif #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 IRMP_NIKON_PROTOCOL, #endif #if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 IRMP_RUWIDO_PROTOCOL, #endif #if IRMP_SUPPORT_IR60_PROTOCOL == 1 IRMP_IR60_PROTOCOL, #endif #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 IRMP_KATHREIN_PROTOCOL, #endif #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 IRMP_NETBOX_PROTOCOL, #endif #if IRMP_SUPPORT_NEC16_PROTOCOL == 1 IRMP_NEC16_PROTOCOL, #endif #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 IRMP_NEC42_PROTOCOL, #endif #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 IRMP_LEGO_PROTOCOL, #endif #if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 IRMP_THOMSON_PROTOCOL, #endif #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 IRMP_BOSE_PROTOCOL, #endif #if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 IRMP_A1TVBOX_PROTOCOL, #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 IRMP_ORTEK_PROTOCOL, #endif #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 IRMP_TELEFUNKEN_PROTOCOL, #endif #if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 IRMP_ROOMBA_PROTOCOL, #endif #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 IRMP_RCMM32_PROTOCOL, IRMP_RCMM24_PROTOCOL, IRMP_RCMM12_PROTOCOL, #endif #if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 IRMP_SPEAKER_PROTOCOL, #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 IRMP_LGAIR_PROTOCOL, #endif #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 IRMP_SAMSUNG48_PROTOCOL, #endif #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 IRMP_MERLIN_PROTOCOL, #endif #if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 IRMP_PENTAX_PROTOCOL, #endif #if IRMP_SUPPORT_FAN_PROTOCOL == 1 IRMP_FAN_PROTOCOL, #endif #if IRMP_SUPPORT_S100_PROTOCOL == 1 IRMP_S100_PROTOCOL, #endif #if IRMP_SUPPORT_ACP24_PROTOCOL == 1 IRMP_ACP24_PROTOCOL, #endif #if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 IRMP_TECHNICS_PROTOCOL, #endif #if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 || IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // Panasonic vendor ID for kaseikyo IRMP_PANASONIC_PROTOCOL, #endif #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 IRMP_MITSU_HEAVY_PROTOCOL, #endif #if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 IRMP_VINCENT_PROTOCOL, #endif #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 IRMP_SAMSUNGAH_PROTOCOL, #endif #if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 IRMP_IRMP16_PROTOCOL, #endif #if IRMP_SUPPORT_GREE_PROTOCOL == 1 IRMP_GREE_PROTOCOL, #endif #if IRMP_SUPPORT_RCII_PROTOCOL == 1 IRMP_RCII_PROTOCOL, #endif #if IRMP_SUPPORT_METZ_PROTOCOL == 1 IRMP_METZ_PROTOCOL, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 IRMP_ONKYO_PROTOCOL, #endif #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 RF_GEN24_PROTOCOL, #endif #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 RF_X10_PROTOCOL, #endif #if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 RF_MEDION_PROTOCOL #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 IRMP_MELINERA_PROTOCOL #endif #if IRMP_SUPPORT_RC6A20_PROTOCOL == 1 IRMP_RC6A20_PROTOCOL #endif #if IRMP_SUPPORT_RC6A28_PROTOCOL == 1 IRMP_RC6A28_PROTOCOL #endif }; const char * const irmp_used_protocol_names[] PROGMEM = { proto_unknown, #if IRMP_SUPPORT_SIRCS_PROTOCOL == 1 proto_sircs, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 proto_nec, #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 proto_samsung, #endif #if IRMP_SUPPORT_MATSUSHITA_PROTOCOL == 1 proto_matsushita, #endif #if IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 proto_kaseikyo, #endif #if IRMP_SUPPORT_RECS80_PROTOCOL == 1 proto_recs80, #endif #if IRMP_SUPPORT_RC5_PROTOCOL == 1 proto_rc5, #endif #if IRMP_SUPPORT_DENON_PROTOCOL == 1 proto_denon, #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 proto_rc6, #endif #if IRMP_SUPPORT_SAMSUNG_PROTOCOL == 1 proto_samsung32, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 proto_apple, #endif #if IRMP_SUPPORT_RECS80EXT_PROTOCOL == 1 proto_recs80ext, #endif #if IRMP_SUPPORT_NUBERT_PROTOCOL == 1 proto_nubert, #endif #if IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 proto_bang_olufsen, #endif #if IRMP_SUPPORT_GRUNDIG_PROTOCOL == 1 proto_grundig, #endif #if IRMP_SUPPORT_NOKIA_PROTOCOL == 1 proto_nokia, #endif #if IRMP_SUPPORT_SIEMENS_PROTOCOL == 1 proto_siemens, #endif #if IRMP_SUPPORT_FDC_PROTOCOL == 1 proto_fdc, #endif #if IRMP_SUPPORT_RCCAR_PROTOCOL == 1 proto_rccar, #endif #if IRMP_SUPPORT_JVC_PROTOCOL == 1 proto_jvc, #endif #if IRMP_SUPPORT_RC6_PROTOCOL == 1 proto_rc6a, #endif #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 proto_nikon, #endif #if IRMP_SUPPORT_RUWIDO_PROTOCOL == 1 proto_ruwido, #endif #if IRMP_SUPPORT_IR60_PROTOCOL == 1 proto_ir60, #endif #if IRMP_SUPPORT_KATHREIN_PROTOCOL == 1 proto_kathrein, #endif #if IRMP_SUPPORT_NETBOX_PROTOCOL == 1 proto_netbox, #endif #if IRMP_SUPPORT_NEC16_PROTOCOL == 1 proto_nec16, #endif #if IRMP_SUPPORT_NEC42_PROTOCOL == 1 proto_nec42, #endif #if IRMP_SUPPORT_LEGO_PROTOCOL == 1 proto_lego, #endif #if IRMP_SUPPORT_THOMSON_PROTOCOL == 1 proto_thomson, #endif #if IRMP_SUPPORT_BOSE_PROTOCOL == 1 proto_bose, #endif #if IRMP_SUPPORT_A1TVBOX_PROTOCOL == 1 proto_a1tvbox, #endif #if IRMP_SUPPORT_ORTEK_PROTOCOL == 1 proto_ortek, #endif #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 proto_telefunken, #endif #if IRMP_SUPPORT_ROOMBA_PROTOCOL == 1 proto_roomba, #endif #if IRMP_SUPPORT_RCMM_PROTOCOL == 1 proto_rcmm32, proto_rcmm24, proto_rcmm12, #endif #if IRMP_SUPPORT_SPEAKER_PROTOCOL == 1 proto_speaker, #endif #if IRMP_SUPPORT_LGAIR_PROTOCOL == 1 proto_lgair, #endif #if IRMP_SUPPORT_SAMSUNG48_PROTOCOL == 1 proto_samsung48, #endif #if IRMP_SUPPORT_MERLIN_PROTOCOL == 1 proto_merlin, #endif #if IRMP_SUPPORT_PENTAX_PROTOCOL == 1 proto_pentax, #endif #if IRMP_SUPPORT_FAN_PROTOCOL == 1 proto_fan, #endif #if IRMP_SUPPORT_S100_PROTOCOL == 1 proto_s100, #endif #if IRMP_SUPPORT_ACP24_PROTOCOL == 1 proto_acp24, #endif #if IRMP_SUPPORT_TECHNICS_PROTOCOL == 1 proto_technics, #endif #if IRMP_SUPPORT_PANASONIC_PROTOCOL == 1 || IRMP_SUPPORT_KASEIKYO_PROTOCOL == 1 // Panasonic vendor ID for kaseikyo proto_panasonic, #endif #if IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 proto_mitsu_heavy, #endif #if IRMP_SUPPORT_VINCENT_PROTOCOL == 1 proto_vincent, #endif #if IRMP_SUPPORT_SAMSUNGAH_PROTOCOL == 1 proto_samsungah, #endif #if IRMP_SUPPORT_IRMP16_PROTOCOL == 1 proto_irmp16, #endif #if IRMP_SUPPORT_GREE_PROTOCOL == 1 proto_gree, #endif #if IRMP_SUPPORT_RCII_PROTOCOL == 1 proto_rcii, #endif #if IRMP_SUPPORT_METZ_PROTOCOL == 1 proto_metz, #endif #if IRMP_SUPPORT_NEC_PROTOCOL == 1 proto_onkyo, #endif #if IRMP_SUPPORT_RF_GEN24_PROTOCOL == 1 proto_rf_gen24, #endif #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 proto_rf_x10, #endif #if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 proto_rf_medion #endif #if IRMP_SUPPORT_MELINERA_PROTOCOL == 1 proto_melinera #endif #if IRMP_SUPPORT_RC6A20_PROTOCOL == 1 proto_rc6a20 #endif #if IRMP_SUPPORT_RC6A28_PROTOCOL == 1 proto_rc6a28 #endif }; /* * No newline after printing */ void irmp_print_active_protocols(Print *aSerial) { // skip protocol 0 = UNKNOWN for (uint_fast8_t i = 1; i < sizeof(irmp_used_protocol_index); ++i) { #if IRMP_PROTOCOL_NAMES == 1 /* * Read names of protocol from array and print */ # if defined(__AVR__) const char* tProtocolStringPtr = (char*) pgm_read_word(&irmp_used_protocol_names[i]); aSerial->print((__FlashStringHelper *) (tProtocolStringPtr)); # else aSerial->print(irmp_used_protocol_names[i]); # endif #else /* * Print just numbers of the protocols not the names */ # if defined(__AVR__) uint8_t tProtocolNumber = (uint8_t) pgm_read_byte(&irmp_used_protocol_index[i]); aSerial->print(tProtocolNumber); # else aSerial->print(irmp_used_protocol_index[i]); # endif #endif aSerial->print(", "); } } void irmp_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber) { #if IRMP_PROTOCOL_NAMES == 1 # if defined(__AVR__) for (uint_fast8_t i = 0; i < sizeof(irmp_used_protocol_index); ++i) { if(pgm_read_byte(&irmp_used_protocol_index[i]) == aProtocolNumber) { const char* tProtocolStringPtr = (char*) pgm_read_word(&irmp_used_protocol_names[i]); aSerial->print((__FlashStringHelper *) (tProtocolStringPtr)); return; } } # else // no need to save space aSerial->print(irmp_protocol_names[aProtocolNumber]); # endif #endif // append protocol number aSerial->print(F(" | 0x")); aSerial->print(aProtocolNumber, HEX); } /* * Print protocol name or number, address, code and repetition flag * needs appr. 2 milliseconds for output */ void irmp_result_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr) { /* * Print protocol name or number */ aSerial->print(F("P=")); irmp_print_protocol_name(aSerial, aIRMPDataPtr->protocol); /* * Print address, code and repetition flag */ aSerial->print(F(" A=0x")); aSerial->print(aIRMPDataPtr->address, HEX); aSerial->print(F(" C=0x")); aSerial->print(aIRMPDataPtr->command, HEX); if (aIRMPDataPtr->flags & IRMP_FLAG_REPETITION) { aSerial->print(F(" R")); } aSerial->println(); } /* * Do not just call irmp_result_print( &Serial, aIRMPDataPtr) above, since this is not always possible for ATtinies. */ void irmp_result_print(IRMP_DATA *aIRMPDataPtr) { /* * Print protocol name or number */ Serial.print(F("P=")); // Wee need to check if &Serial is of type Print in order not to get errors on e.g. ATtinies // This is not the exact right condition, but on ATtinies you will mostly disable protocol names #if IRMP_PROTOCOL_NAMES == 1 irmp_print_protocol_name(&Serial, aIRMPDataPtr->protocol); #else Serial.print(F("0x")); Serial.print(aIRMPDataPtr->protocol, HEX); #endif /* * Print address, code and repetition flag */ Serial.print(F(" A=0x")); Serial.print(aIRMPDataPtr->address, HEX); Serial.print(F(" C=0x")); Serial.print(aIRMPDataPtr->command, HEX); if (aIRMPDataPtr->flags & IRMP_FLAG_REPETITION) { Serial.print(F(" R")); } Serial.println(); } #endif // defined(ARDUINO) ================================================ FILE: src/irmpPinChangeInterrupt.hpp ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpPinChangeInterrupt.hpp * * Functions and ISR for the pin change interrupt functionality for IRMP - For Arduino platform * Must be included after irmp_ISR to have all the internal variables of irmp_ISR declared * * Copyright (C) 2020 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 . * */ #ifndef _IRMP_PIN_CHANGE_INTERRUPT_HPP #define _IRMP_PIN_CHANGE_INTERRUPT_HPP //#define PCI_DEBUG # if defined(__AVR__) void irmp_debug_print(const __FlashStringHelper *aMessage, bool aDoShortOutput = true); # else void irmp_debug_print(const char *aMessage, bool aDoShortOutput); # endif uint32_t irmp_last_change_micros; // microseconds of last Pin Change Interrupt. Used for irmp_IsBusy(). /* * Wrapper for irmp_ISR() in order to run it with Pin Change Interrupts. * Needs additional 8-9us per call and 13us for signal going inactive and 19us for going active. * Tested for NEC, Kaseiko, Denon, RC6, Samsung and others. * Requires micros() for timing. */ //#define PCI_DEBUG #if defined(ESP8266) || defined(ESP32) void IRAM_ATTR irmp_PCI_ISR(void) #else void irmp_PCI_ISR(void) #endif { // save IR input level - negative logic, true means inactive / IR pause uint_fast8_t irmp_input = input(IRMP_PIN); /* * 1. compute ticks after last change */ uint32_t tMicros = micros(); uint32_t tTicks = tMicros - irmp_last_change_micros; // values up to 10000 irmp_last_change_micros = tMicros; #if (F_INTERRUPTS == 15625) // F_INTERRUPTS value of 31250 does not work (maybe 8 bit overflow?) tTicks = (tTicks << 2) >> 8;// saves 1.3 us #else #error F_INTERRUPTS must be 15625 (to avoid a time consuming division) #endif if (tTicks != 0) { tTicks -= 1; // adjust for irmp_pulse_time / irmp_pause_time incremented in irmp_ISR() } /* * 2. check for input level and tweak timings */ if (irmp_input) // true means inactive / IR pause { // start of pause -> just set pulse width irmp_pulse_time += tTicks; } else { if (irmp_start_bit_detected) { irmp_pause_time += tTicks; } else { // start pulse here -> set pause or time between repetitions if (tTicks > UINT16_MAX) { // avoid overflow for 16 bit key_repetition_len tTicks = UINT16_MAX; } key_repetition_len = tTicks; } } /* * 3. call the protocol detection routine */ irmp_ISR(); if (!irmp_ir_detected && irmp_input) { /* * No valid protocol detected and IR input is inactive now -> simulate end for protocols. * IRMP may be waiting for stop bit, but detects it only at the next call, so do one additional call. * !!! ATTENTION !!! This will NOT work if we try to receive simultaneously two protocols which are only different in length like NEC16 and NEC42 */ #if defined(PCI_DEBUG) Serial.write('x'); if (irmp_bit > 0 && irmp_bit == irmp_param.complete_len) { Serial.println(irmp_start_bit_detected); // print start bit if complete_len is reached } #endif if (irmp_start_bit_detected && irmp_bit == irmp_param.complete_len && irmp_param.stop_bit == TRUE) { // Try to detect a nec repeat irmp_bit is 0 #if defined(PCI_DEBUG) irmp_debug_print(F("R")); #endif PAUSE_LEN irmp_pause_time_store = irmp_pause_time; irmp_pause_time = STOP_BIT_PAUSE_LEN_MIN + 1; // set pause time to minimal pause required to detect a stop bit irmp_ISR(); // Call to detect a NEC repeat #if defined(PCI_DEBUG) irmp_debug_print(F("E")); // print info after call Serial.println(); #endif if (irmp_ir_detected) { // no protocol detected -> restore irmp_pause_time. Not sure if this is really required. irmp_pause_time = irmp_pause_time_store; } } // For condition see also line 4203 and 5098 in irmp.hpp if (irmp_start_bit_detected && irmp_bit > 0 && irmp_bit == irmp_param.complete_len) { // Complete length of bit now received -> try to detect end of protocol #if defined(PCI_DEBUG) irmp_debug_print(F("S")); // print info before call #endif PAUSE_LEN irmp_pause_time_store = irmp_pause_time; irmp_pause_time = STOP_BIT_PAUSE_LEN_MIN + 1; // set pause time to minimal pause required to detect a stop bit irmp_ISR(); // Call to detect end of protocol, irmp_param.stop_bit (printed as Sb) should be set to 0 if stop bit was successfully detected. #if defined(PCI_DEBUG) irmp_debug_print(F("E")); // print info after call Serial.println(); #endif if (irmp_ir_detected) { // no protocol detected -> restore irmp_pause_time. Not sure if this is really required. irmp_pause_time = irmp_pause_time_store; } } #if (IRMP_SUPPORT_MANCHESTER == 1) /* * Simulate end for Manchester/biphase protocols - 130 bytes */ if (((irmp_bit == irmp_param.complete_len - 1 && tTicks < irmp_param.pause_1_len_max) || (irmp_bit == irmp_param.complete_len - 2 && tTicks > irmp_param.pause_1_len_max)) && (irmp_param.flags & IRMP_PARAM_FLAG_IS_MANCHESTER) && irmp_start_bit_detected) { # if defined(PCI_DEBUG) Serial.println('M'); // Try to detect a Manchester end of protocol # endif irmp_pause_time = 2 * irmp_param.pause_1_len_max; irmp_ISR(); // Write last one (with value 0) or 2 (with last value 1) data bits and set wait for dummy stop bit irmp_ISR();// process dummy stop bit irmp_ISR();// reset stop bit and call callback } #endif } } void enablePCIInterrupt() { #if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) attachInterrupt(IRMP_INPUT_PIN, irmp_PCI_ISR, CHANGE); // 14.2 us before LED Feedback compared to 12 if configured with macros and less compatible #elif ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) # if defined(ARDUINO_ARCH_SAMD) // see https://www.arduino.cc/reference/tr/language/functions/external-interrupts/attachinterrupt/ paragraph: Syntax attachInterrupt(IRMP_INPUT_PIN, irmp_PCI_ISR, CHANGE); # else attachInterrupt(digitalPinToInterrupt(IRMP_INPUT_PIN), irmp_PCI_ISR, CHANGE); // CHANGE can be an enum :-( # endif #else # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // use PinChangeInterrupt PCMSK |= _BV(IRMP_INPUT_PIN); // clear interrupt bit GIFR |= 1 << PCIF; // enable interrupt on next change GIMSK |= 1 << PCIE; # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(ARDUINO_AVR_DIGISPARKPRO) # if (IRMP_INPUT_PIN == 3) // interrupt on any logical change EICRA |= _BV(ISC00); // clear interrupt bit EIFR |= 1 << INTF0; // enable interrupt on next change EIMSK |= 1 << INT0; # elif (IRMP_INPUT_PIN == 9) EICRA |= _BV(ISC10); // clear interrupt bit EIFR |= 1 << INTF1; // enable interrupt on next change EIMSK |= 1 << INT1; # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 9 or 3." # endif // if (IRMP_INPUT_PIN == 9) # else // defined(ARDUINO_AVR_DIGISPARKPRO) # if (IRMP_INPUT_PIN == 14) // interrupt on any logical change EICRA |= _BV(ISC00); // clear interrupt bit EIFR |= 1 << INTF0; // enable interrupt on next change EIMSK |= 1 << INT0; # elif (IRMP_INPUT_PIN == 3) EICRA |= _BV(ISC10); // clear interrupt bit EIFR |= 1 << INTF1; // enable interrupt on next change EIMSK |= 1 << INT1; # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 14 or 3." # endif // if (IRMP_INPUT_PIN == 14) # endif # else // defined(__AVR_ATtiny25__) /* * ATmegas here */ # if (IRMP_INPUT_PIN == 2) // interrupt on any logical change EICRA |= _BV(ISC00); // clear interrupt bit EIFR |= 1 << INTF0; // enable interrupt on next change EIMSK |= 1 << INT0; # elif (IRMP_INPUT_PIN == 3) EICRA |= _BV(ISC10); // clear interrupt bit EIFR |= 1 << INTF1; // enable interrupt on next change EIMSK |= 1 << INT1; # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 2 or 3." # endif // if (IRMP_INPUT_PIN == 2) # endif // defined(__AVR_ATtiny25__) #endif // ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) } void disablePCIInterrupt() { #if defined(__AVR_ATtiny1616__) || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) detachInterrupt(IRMP_INPUT_PIN); #elif ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) detachInterrupt(digitalPinToInterrupt(IRMP_INPUT_PIN)); #else # if defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) // clear interrupt bit GIFR |= 1 << PCIF; // disable interrupt on next change GIMSK &= ~(1 << PCIE); # elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__) # if defined(ARDUINO_AVR_DIGISPARKPRO) # if (IRMP_INPUT_PIN == 3) // clear interrupt bit EIFR |= 1 << INTF0; // disable interrupt on next change EIMSK &= ~( 1 << INT0); # elif (IRMP_INPUT_PIN == 9) // clear interrupt bit EIFR |= 1 << INTF1; // disable interrupt on next change EIMSK &= ~(1 << INT1); # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 9 or 3." # endif // if (IRMP_INPUT_PIN == 9) # else // defined(ARDUINO_AVR_DIGISPARKPRO) # if (IRMP_INPUT_PIN == 14) // clear interrupt bit EIFR |= 1 << INTF0; // disable interrupt on next change EIMSK &= ~(1 << INT0); # elif (IRMP_INPUT_PIN == 3) // clear interrupt bit EIFR |= 1 << INTF1; // disable interrupt on next change EIMSK &= ~(1 << INT1); # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 14 or 3." # endif // if (IRMP_INPUT_PIN == 14) # endif # else // defined(__AVR_ATtiny25__) /* * ATmegas here */ # if (IRMP_INPUT_PIN == 2) // clear interrupt bit EIFR |= 1 << INTF0; // disable interrupt on next change EIMSK &= ~(1 << INT0); # elif (IRMP_INPUT_PIN == 3) // clear interrupt bit EIFR |= 1 << INTF1; // disable interrupt on next change EIMSK &= ~(1 << INT1); # else # error "For interrupt mode (IRMP_ENABLE_PIN_CHANGE_INTERRUPT is defined) IRMP_INPUT_PIN must be 2 or 3." # endif // if (IRMP_INPUT_PIN == 2) # endif // defined(__AVR_ATtiny25__) #endif // ! defined(__AVR__) || defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) } /* * Specify the right INT0, INT1 or PCINT0 interrupt vector according to different pins and cores */ #if defined(__AVR__) && !defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) # if (IRMP_INPUT_PIN == 2) ISR(INT0_vect) // Pin 2 global assignment # elif (IRMP_INPUT_PIN == 3) # if defined(ARDUINO_AVR_DIGISPARKPRO) ISR(INT0_vect) // Pin 3 / PB6 / INT0 is connected to USB+ on DigisparkPro boards # else ISR(INT1_vect) // Pin 3 global assignment # endif # elif (IRMP_INPUT_PIN == 9) // Digispark pro ISR(INT1_vect) # elif (IRMP_INPUT_PIN == 14) // For AVR_ATtiny167 INT0 is on pin 14 / PB6 ISR(INT0_vect) # elif (! defined(ISC10)) || ((defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)) && INT1_PIN != 3) // on ATtinyX5 we do not have a INT1_vect but we can use the PCINT0_vect ISR(PCINT0_vect) # endif // (IRMP_INPUT_PIN == 2) { irmp_PCI_ISR(); } #endif // defined(__AVR__) && !defined(IRMP_USE_ARDUINO_ATTACH_INTERRUPT) #if defined(__AVR__) void irmp_debug_print(const __FlashStringHelper *aMessage, bool aDoShortOutput) #else void irmp_debug_print(const char *aMessage, bool aDoShortOutput) #endif { Serial.print(aMessage); Serial.print(' '); Serial.print(irmp_ir_detected); // valid IR command detected Serial.print(F(" St")); Serial.print(irmp_start_bit_detected); Serial.print(F(" Ws")); Serial.print(wait_for_space); // true if in data/address section and no signal. Now increment pause time. Serial.print(F(" Wss")); Serial.print(wait_for_start_space); // true if we have received start bit Serial.print(F(" L")); Serial.print(irmp_param.complete_len); // maximum bit position Serial.print(F(" B")); Serial.print((int8_t) irmp_bit); // current bit position - FF(-1) is start value Serial.print(F(" Pu")); Serial.print(irmp_pulse_time); // bit time for pulse Serial.print(F(" Pa")); Serial.print(irmp_pause_time); Serial.print(F(" Sb")); Serial.print(irmp_param.stop_bit); // boolean. 1 = stop bit required if (!aDoShortOutput) { Serial.print(F(" F")); Serial.print(irmp_flags); // currently only repetition flag Serial.print(F(" K")); Serial.print(key_repetition_len); // the pause after a command to distinguish repetitions from new commands Serial.print(F(" R")); Serial.print(repetition_frame_number); // Number of repetitions } Serial.println(); } #endif // _IRMP_PIN_CHANGE_INTERRUPT_HPP ================================================ FILE: src/irmpSelectAllProtocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpSelectAllProtocols.h * 42 + 1 protocols enabled * 8 Protocols disabled since they conflicts with the enabled ones * Depending on the value of F_INTERRUPTS 2 other protocols (LEGO and RCMM or PENTAX and GREE) are disabled too - see F_INTERRUPTS below * * * Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_SELECT_PROTOCOLS_H #define _IRMP_SELECT_PROTOCOLS_H /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more decoders. * This saves program memory. * * 1 enable decoder * 0 disable decoder * * The standard decoders are enabled per default. * Less common protocols are disabled here, you need to enable them manually. * * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required. * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. * You cannot enable both DENON and RUWIDO, only enable one of them. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 1: IR decoders * If you use a RF receiver, deactivate all IR protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // 4 typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes #define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes // 11 more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~100 bytes #define IRMP_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~300 bytes #define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes #define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes #define IRMP_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~250 bytes #define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes #define IRMP_SUPPORT_IR60_PROTOCOL 1 // IR60 (SDA2008) >= 10000 ~300 bytes #define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes #define IRMP_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens Gigaset >= 15000 ~550 bytes #define IRMP_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~300 bytes // 27 + 8 exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_BOSE_PROTOCOL 1 // BOSE >= 10000 ~150 bytes #define IRMP_SUPPORT_KATHREIN_PROTOCOL 1 // Kathrein >= 10000 ~200 bytes #define IRMP_SUPPORT_NUBERT_PROTOCOL 1 // NUBERT >= 10000 ~50 bytes #define IRMP_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~50 bytes conflicts with NUBERT #define IRMP_SUPPORT_SPEAKER_PROTOCOL 1 // SPEAKER (~NUBERT) >= 10000 ~50 bytes #define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 1 // Bang & Olufsen >= 10000 ~200 bytes #define IRMP_SUPPORT_RECS80_PROTOCOL 1 // RECS80 (SAA3004) >= 15000 ~50 bytes #define IRMP_SUPPORT_RECS80EXT_PROTOCOL 1 // RECS80EXT (SAA3008) >= 15000 ~50 bytes #define IRMP_SUPPORT_THOMSON_PROTOCOL 1 // Thomson >= 10000 ~250 bytes #define IRMP_SUPPORT_NIKON_PROTOCOL 1 // NIKON camera >= 10000 ~250 bytes #define IRMP_SUPPORT_NETBOX_PROTOCOL 1 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!) #define IRMP_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 ~150 bytes conflicts with FDC and NETBOX #define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 1 // Telefunken 1560 >= 10000 ~150 bytes #define IRMP_SUPPORT_FDC_PROTOCOL 1 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5) #define IRMP_SUPPORT_RCCAR_PROTOCOL 1 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5) #define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes conflicts with RC6 #define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes conflicts with DENON #define IRMP_SUPPORT_A1TVBOX_PROTOCOL 1 // A1 TV BOX >= 15000 (better 20000) ~300 bytes #define IRMP_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes #define IRMP_SUPPORT_RCMM_PROTOCOL 1 // RCMM 12,24, or 32 >= 20000 ~150 bytes #define IRMP_SUPPORT_LGAIR_PROTOCOL 1 // LG Air Condition >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 1 // Samsung48 >= 10000 ~100 bytes (SAMSUNG must be enabled!) #define IRMP_SUPPORT_MERLIN_PROTOCOL 1 // Merlin >= 15000 (better 20000) ~300 bytes (requires IRMP_32_BIT=1) #define IRMP_SUPPORT_PENTAX_PROTOCOL 1 // Pentax >= 10000 <=17000 ~150 bytes (<= 17000 due to 8 bit timing overflow issue) #define IRMP_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 ~250 bytes conflicts with RC5 #define IRMP_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~250 bytes conflicts with DENON #define IRMP_SUPPORT_TECHNICS_PROTOCOL 1 // TECHNICS >= 10000 ~250 bytes #define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~250 bytes Panasonic is Kaseikyo with vendor code 0x2002 and you cannot distinguish it by start bit timing. #define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi Aircond >= 10000 ~250 bytes Mitsubishi is Kaseikyo with vendor code 0xCB23 and you cannot distinguish it by start bit timing. #define IRMP_SUPPORT_VINCENT_PROTOCOL 1 // VINCENT >= 10000 ~250 bytes #define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 1 // SAMSUNG AH >= 10000 ~250 bytes #define IRMP_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes #define IRMP_SUPPORT_GREE_PROTOCOL 1 // GREE CLIMATE >= 10000 <=17000 ~250 bytes #define IRMP_SUPPORT_RCII_PROTOCOL 0 // RCII T+A >= 15000 ~250 bytes conflicts with GRUNDIG and NOKIA #define IRMP_SUPPORT_METZ_PROTOCOL 1 #define IRMP_SUPPORT_MELINERA_PROTOCOL 1 // MELINERA (Lidl) >= 10000 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 2: RF decoders * If you use an IR sensor, deactivate all RF protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes #endif // _IRMP_SELECT_ALL_PROTOCOLS_H ================================================ FILE: src/irmpSelectAllRFProtocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpSelectAllRFProtocols.h * 2 protocols enabled * * Copyright (c) 2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_SELECT_ALL_RF_PROTOCOLS_H #define _IRMP_SELECT_ALL_RF_PROTOCOLS_H /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more decoders. * This saves program memory. * * 1 enable decoder * 0 disable decoder *--------------------------------------------------------------------------------------------------------------------------------------------------- */ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 2: RF decoders * If you use an IR sensor, deactivate all RF protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_SUPPORT_RF_GEN24_PROTOCOL 1 // RF GEN24 (generic) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_X10_PROTOCOL 1 // RF PC X10 (Medion) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_MEDION_PROTOCOL 1 // RF PC Medion >= 15000 ~250 bytes // Usually IR sensors are low active, RF receivers are high active. #define IRMP_HIGH_ACTIVE 1 // set to 1 if you use a RF receiver! #endif // _IRMP_SELECT_ALL_RF_PROTOCOLS_H ================================================ FILE: src/irmpSelectMain15Protocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpSelectMain15Protocols.h * * * Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_SELECT_PROTOCOLS_H #define _IRMP_SELECT_PROTOCOLS_H /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 (or deactivate it) if you want to disable one or more decoders. * This saves program memory. * * 1 enable decoder * 0 disable decoder * * The standard decoders are enabled per default. * Less common protocols are disabled here, you need to enable them manually. * * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required. * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. * You cannot enable both DENON and RUWIDO, only enable one of them. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes #define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes // more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~100 bytes #define IRMP_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~300 bytes #define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~50 bytes #define IRMP_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~250 bytes #define IRMP_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~250 bytes #define IRMP_SUPPORT_RC6_PROTOCOL 1 // RC6 & RC6A >= 10000 ~250 bytes #define IRMP_SUPPORT_IR60_PROTOCOL 1 // IR60 (SDA2008) >= 10000 ~300 bytes #define IRMP_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes #define IRMP_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens Gigaset >= 15000 ~550 bytes #define IRMP_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~300 bytes #endif // _IRMP_SELECT_PROTOCOLS_H ================================================ FILE: src/irmpVersion.h ================================================ /* * irmpVersion.h * * Is used for IRMP and IRSND, and therefore a separate file * * Created on: 28.05.2020 * Author: Armin */ #ifndef _IRMPVERSION_H #define _IRMPVERSION_H #define VERSION_IRMP "3.7.0" #define VERSION_IRMP_MAJOR 3 #define VERSION_IRMP_MINOR 7 #define VERSION_IRMP_PATCH 0 /* * Macro to convert 3 version parts into an integer * To be used in preprocessor comparisons, such as #if VERSION_IRMP_HEX >= VERSION_HEX_VALUE(3, 7, 0) */ #define VERSION_HEX_VALUE(major, minor, patch) ((major << 16) | (minor << 8) | (patch)) #define VERSION_IRMP_HEX VERSION_HEX_VALUE(VERSION_IRMP_MAJOR, VERSION_IRMP_MINOR, VERSION_IRMP_PATCH) #endif /* _IRMPVERSION_H */ ================================================ FILE: src/irmpconfig.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpconfig.h * * DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H! * * Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de * Extensions for PIC 12F1820 W.Strobl 2014-07-20 * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_H_ # error please include only irmp.h, not irmpconfig.h #endif #if defined(IRMPCONFIG_STAGE1_H) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change IRMP_32_BIT here * * Normally, IRMP_32_BIT ist 0. Then we use irmp.command as a 16 bit value. * If you set IRMP_32_BIT to 1, we will use irmp.command as a 32 bit value. * A 32 bit command costs more CPU resources on 8 bit processors (e.g. AVR), * but there are IR protocols which need more than 16 bits for a reasonable * command value. * * If you want to use one of the following protocols, set IRMP_32_BIT to 1, * otherwise set it to 0: * - MERLIN *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_32_BIT) # if __SIZEOF_INT__ == 4 # define IRMP_32_BIT 1 // use 32 bit command value, 0 or 1 # else # define IRMP_32_BIT 0 // use 32 bit command value, 0 or 1 # endif #endif #endif // IRMPCONFIG_STAGE1_H #if defined(IRMPCONFIG_STAGE2_H) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change F_INTERRUPTS if you change the number of interrupts per second, * Normally, F_INTERRUPTS should be in the range from 10000 to 15000, typical is 15000 * A value above 15000 costs additional program memory, absolute maximum value is 20000. * A value of 20000 is needed for Support of LEGO and RCMM, but it prevents using PENTAX or GREE * since for 20000 they have 8 bit overflow issues because of the long start bits. * On PIC with XC8/C18 Compiler, use 15151 as the correct value. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(F_INTERRUPTS) # define F_INTERRUPTS 15000 // interrupts per second, 66,66us, min: 10000, max: 20000, typ: 15000 #endif #if ! defined(ARDUINO) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more decoders. * This saves program memory. * * 1 enable decoder * 0 disable decoder * * The standard decoders are enabled per default. * Less common protocols are disabled here, you need to enable them manually. * * If you want to use FDC or RCCAR simultaneous with RC5 protocol, additional program memory is required. * If you don't need RC5 when using FDC/RCCAR, you should disable RC5. * You cannot enable both DENON and RUWIDO, only enable one of them. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 1: IR decoders * If you use a RF receiver, deactivate all IR protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE + ONKYO >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsg32 >= 10000 ~300 bytes #define IRMP_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~250 bytes // more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes #define IRMP_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~100 bytes #define IRMP_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~300 bytes #define IRMP_SUPPORT_MATSUSHITA_PROTOCOL 0 // Matsushita >= 10000 ~50 bytes #define IRMP_SUPPORT_DENON_PROTOCOL 0 // DENON, Sharp >= 10000 ~250 bytes #define IRMP_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~250 bytes #define IRMP_SUPPORT_RC6_PROTOCOL 0 // RC6 & RC6A >= 10000 ~250 bytes #define IRMP_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~300 bytes #define IRMP_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes #define IRMP_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens Gigaset >= 15000 ~550 bytes #define IRMP_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~300 bytes // exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRMP_SUPPORT_BOSE_PROTOCOL 0 // BOSE >= 10000 ~150 bytes #define IRMP_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 ~200 bytes #define IRMP_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~50 bytes #define IRMP_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~50 bytes #define IRMP_SUPPORT_SPEAKER_PROTOCOL 0 // SPEAKER (~NUBERT) >= 10000 ~50 bytes #define IRMP_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang & Olufsen >= 10000 ~200 bytes #define IRMP_SUPPORT_RECS80_PROTOCOL 0 // RECS80 (SAA3004) >= 15000 ~50 bytes #define IRMP_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT (SAA3008) >= 15000 ~50 bytes #define IRMP_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes #define IRMP_SUPPORT_NIKON_PROTOCOL 0 // NIKON camera >= 10000 ~250 bytes #define IRMP_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 ~400 bytes (PROTOTYPE!) #define IRMP_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 ~150 bytes #define IRMP_SUPPORT_TELEFUNKEN_PROTOCOL 0 // Telefunken 1560 >= 10000 ~150 bytes #define IRMP_SUPPORT_FDC_PROTOCOL 0 // FDC3402 keyboard >= 10000 (better 15000) ~150 bytes (~400 in combination with RC5) #define IRMP_SUPPORT_RCCAR_PROTOCOL 0 // RC Car >= 10000 (better 15000) ~150 bytes (~500 in combination with RC5) #define IRMP_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes #define IRMP_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~550 bytes #define IRMP_SUPPORT_A1TVBOX_PROTOCOL 0 // A1 TV BOX >= 15000 (better 20000) ~300 bytes #define IRMP_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes #define IRMP_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 ~150 bytes #define IRMP_SUPPORT_LGAIR_PROTOCOL 0 // LG Air Condition >= 10000 ~300 bytes #define IRMP_SUPPORT_SAMSUNG48_PROTOCOL 0 // Samsung48 >= 10000 ~100 bytes (SAMSUNG must be enabled!) #define IRMP_SUPPORT_MERLIN_PROTOCOL 0 // Merlin >= 15000 (better 20000) ~300 bytes (requires IRMP_32_BIT=1) #define IRMP_SUPPORT_PENTAX_PROTOCOL 0 // Pentax >= 10000 ~150 bytes #define IRMP_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 ~250 bytes #define IRMP_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~250 bytes #define IRMP_SUPPORT_TECHNICS_PROTOCOL 0 // TECHNICS >= 10000 ~250 bytes #define IRMP_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~250 bytes #define IRMP_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi Aircond >= 10000 ~250 bytes #define IRMP_SUPPORT_VINCENT_PROTOCOL 0 // VINCENT >= 10000 ~250 bytes #define IRMP_SUPPORT_SAMSUNGAH_PROTOCOL 0 // SAMSUNG AH >= 10000 ~250 bytes #define IRMP_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes #define IRMP_SUPPORT_GREE_PROTOCOL 0 // GREE CLIMATE >= 10000 ~250 bytes #define IRMP_SUPPORT_RCII_PROTOCOL 0 // RCII T+A >= 15000 ~250 bytes #define IRMP_SUPPORT_METZ_PROTOCOL 0 // METZ >= 15000 ~250 bytes /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 2: RF decoders * If you use an IR sensor, deactivate all RF protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes #define IRMP_SUPPORT_MELINERA_PROTOCOL 0 // MELINERA (Lidl) >= 10000 #endif // ! defined(ARDUINO) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for ATMEL ATmega/ATTiny/XMega *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined (ATMEL_AVR) || defined (__AVR_XMEGA__) // use PB6 as IR input on AVR # define IRMP_PORT_LETTER B # define IRMP_BIT_NUMBER 6 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for PIC C18 or XC8 compiler *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (PIC_C18) // use RB4 as IR input on PIC (C18 or XC8 compiler) # if defined(__12F1840) # define IRMP_PIN RA5 // on 12F1840 with XC8 compiler # else # define IRMP_PIN PORTBbits.RB4 // PIC C18 # endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for PIC XC32 or ChipKIT compiler *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (PIC_XC32) // use RB13 as IR input on PIC (XC32 or ChipKIT compiler) # define IRMP_PIN PORTBbits.RB13 # define IRMP_ANSELBIT ANSELBbits.ANSB13 // leave this undefined if the pin has no analog function /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for PIC CCS compiler *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (PIC_CCS) # define IRMP_PIN PIN_B4 // use PB4 as IR input on PIC (CCS compiler) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for ARM STM32 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (ARM_STM32) // use C13 as IR input on STM32 # define IRMP_PORT_LETTER C # define IRMP_BIT_NUMBER 13 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Hardware pin for ARM STM32 (HAL) - don't change here, define IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN in STM32Cube (Main.h) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (ARM_STM32_HAL) // STM32: IRMP_RECEIVE_GPIO_Port & IRMP_RECEIVE_PIN must be defined in STM32Cube # define IRMP_PORT_LETTER IRMP_Receive_GPIO_Port # define IRMP_BIT_NUMBER IRMP_Receive_Pin /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for Stellaris ARM Cortex M4 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (STELLARIS_ARM_CORTEX_M4) // use B4 as IR input on Stellaris LM4F # define IRMP_PORT_LETTER B # define IRMP_BIT_NUMBER 4 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for STM8 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (SDCC_STM8) // use PA1 as IR input on STM8 # define IRMP_PORT_LETTER A // change here # define IRMP_BIT_NUMBER 1 // change here /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for ESP8266 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (__xtensa__) # define IRMP_BIT_NUMBER 12 // use GPIO12 (Pin 7 UEXT) on ESP8266-EVB evaluation board /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for Teensy 3.x with teensyduino gcc compiler *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (TEENSY_ARM_CORTEX_M4) # define IRMP_PIN 1 // use Digital pin 1 as IR input on Teensy /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for MBED *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined(__MBED__) # define IRMP_PIN P0_22 // use P1_27 on LPC1347 # define IRMP_PINMODE PullUp // hardware dependent /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change hardware pin here for ChibiOS HAL *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined(_CHIBIOS_HAL_) # define IRMP_PIN LINE_IR_IN // use pin names as defined in the board config file, prefixed with "LINE_" # define IRMP_LOGGING_SD SD1 // the ChibiOS HAL Serial Driver instance to log to // (when IRMP_LOGGING is enabled below). // Make sure SERIAL_BUFFERS_SIZE is large enough when enabling logging #elif defined(ARDUINO) // specified here to avoid else case /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Handling of unknown target system: DON'T CHANGE *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif !defined (UNIX_OR_WINDOWS) # error target system not defined. #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change if sensor is high active * * Usually IR sensors are low active, RF receivers are high active. Change here if you use a RF receiver! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_HIGH_ACTIVE) # define IRMP_HIGH_ACTIVE 0 // set to 1 if you use a RF receiver! #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Enable detection of key releases * * If user releases a key on the remote control, last protocol/address/command will be returned with flag IRMP_FLAG_RELEASE set *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_ENABLE_RELEASE_DETECTION) # define IRMP_ENABLE_RELEASE_DETECTION 0 // enable detection of key releases #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Set IRMP_LOGGING to 1 if want to log data to UART with 9600Bd *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_LOGGING) # define IRMP_LOGGING 0 // 1: log IR signal (scan), 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Use external logging routines * If you enable external logging, you have also to enable IRMP_LOGGING above *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_EXT_LOGGING) # define IRMP_EXT_LOGGING 0 // 1: use external logging, 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Set IRMP_PROTOCOL_NAMES to 1 if want to access protocol names (for logging etc), costs ~300 bytes RAM! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_PROTOCOL_NAMES) # define IRMP_PROTOCOL_NAMES 0 // 1: access protocol names, 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Use Callbacks to indicate input signal *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_USE_CALLBACK) # define IRMP_USE_CALLBACK 0 // 1: use callbacks. 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Call the user-provided irmp_idle() function when IRMP is idle. * Can be used to disable the timer irq and enter a sleep mode to save power *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_USE_IDLE_CALL) # define IRMP_USE_IDLE_CALL 0 // 1: use idle calls. 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Use Callback if complete data was received *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRMP_USE_COMPLETE_CALLBACK) # define IRMP_USE_COMPLETE_CALLBACK 0 // 1: use callback. 0: do not. default is 0 #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Autodetect repeat rate * For precise detection of key repetition (and key release) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef IRMP_AUTODETECT_REPEATRATE # define IRMP_AUTODETECT_REPEATRATE 0 // 1: autodetect repeat rate. 0: do not. default is 0 # define JITTER_COMPENSATION 3 // percent, increase for remote controls with big jitter #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Use ChibiOS Events to signal that valid IR data was received *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined(_CHIBIOS_RT_) || defined(_CHIBIOS_NIL_) # if !defined(IRMP_USE_EVENT) # define IRMP_USE_EVENT 0 // 1: use event. 0: do not. default is 0 # endif # if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_BIT) # define IRMP_EVENT_BIT 1 // event flag or bit to send # endif # if IRMP_USE_EVENT == 1 && !defined(IRMP_EVENT_THREAD_PTR) # define IRMP_EVENT_THREAD_PTR ir_receive_thread_p // pointer to the thread to send the event to extern thread_t *IRMP_EVENT_THREAD_PTR; // the pointer must be defined and initialized elsewhere # endif #endif // _CHIBIOS_RT_ || _CHIBIOS_NIL_ #endif // _IRMPCONFIG_STAGE2_H_ ================================================ FILE: src/irmpprotocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpprotocols.h - irmp protocols * * DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRMP.H or IRSND.H! * * Copyright (c) 2013-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMP_PROTOCOLS_H_ #define _IRMP_PROTOCOLS_H_ #if !defined(_IRMP_H_) && !defined(_IRSND_H_) # error please include only irmp.h or irsnd.h, not irmpprotocols.h #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IR protocols: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_UNKNOWN_PROTOCOL 0 // unknown protocol #define IRMP_SIRCS_PROTOCOL 1 // Sony #define IRMP_NEC_PROTOCOL 2 // NEC with 32 bits, 16 address + 8 (+ 8 generated) command bits, Pioneer, JVC, Toshiba, NoName etc. #define IRMP_SAMSUNG_PROTOCOL 3 // Samsung #define IRMP_MATSUSHITA_PROTOCOL 4 // Matsushita #define IRMP_KASEIKYO_PROTOCOL 5 // Kaseikyo (Panasonic etc) #define IRMP_RECS80_PROTOCOL 6 // Philips, Thomson, Nordmende, Telefunken, Saba #define IRMP_RC5_PROTOCOL 7 // Philips etc #define IRMP_DENON_PROTOCOL 8 // Denon, Sharp #define IRMP_RC6_PROTOCOL 9 // Philips etc #define IRMP_SAMSUNG32_PROTOCOL 10 // Samsung32: no sync pulse at bit 16, length 32 instead of 37 #define IRMP_APPLE_PROTOCOL 11 // Apple, very similar to NEC #define IRMP_RECS80EXT_PROTOCOL 12 // Philips, Technisat, Thomson, Nordmende, Telefunken, Saba #define IRMP_NUBERT_PROTOCOL 13 // Nubert #define IRMP_BANG_OLUFSEN_PROTOCOL 14 // Bang & Olufsen #define IRMP_GRUNDIG_PROTOCOL 15 // Grundig #define IRMP_NOKIA_PROTOCOL 16 // Nokia #define IRMP_SIEMENS_PROTOCOL 17 // Siemens, e.g. Gigaset #define IRMP_FDC_PROTOCOL 18 // FDC keyboard #define IRMP_RCCAR_PROTOCOL 19 // RC Car #define IRMP_JVC_PROTOCOL 20 // JVC (NEC with 16 bits) #define IRMP_RC6A_PROTOCOL 21 // RC6A, e.g. Kathrein, XBOX #define IRMP_NIKON_PROTOCOL 22 // Nikon #define IRMP_RUWIDO_PROTOCOL 23 // Ruwido, e.g. T-Home Mediareceiver #define IRMP_IR60_PROTOCOL 24 // IR60 (SDA2008) #define IRMP_KATHREIN_PROTOCOL 25 // Kathrein #define IRMP_NETBOX_PROTOCOL 26 // Netbox keyboard (bitserial) #define IRMP_NEC16_PROTOCOL 27 // NEC with 16 bits (incl. sync) #define IRMP_NEC42_PROTOCOL 28 // NEC with 42 bits #define IRMP_LEGO_PROTOCOL 29 // LEGO Power Functions RC #define IRMP_THOMSON_PROTOCOL 30 // Thomson #define IRMP_BOSE_PROTOCOL 31 // BOSE #define IRMP_A1TVBOX_PROTOCOL 32 // A1 TV Box #define IRMP_ORTEK_PROTOCOL 33 // ORTEK - Hama #define IRMP_TELEFUNKEN_PROTOCOL 34 // Telefunken (1560) #define IRMP_ROOMBA_PROTOCOL 35 // iRobot Roomba vacuum cleaner #define IRMP_RCMM32_PROTOCOL 36 // Fujitsu-Siemens (Activy remote control) #define IRMP_RCMM24_PROTOCOL 37 // Fujitsu-Siemens (Activy keyboard) #define IRMP_RCMM12_PROTOCOL 38 // Fujitsu-Siemens (Activy keyboard) #define IRMP_SPEAKER_PROTOCOL 39 // Another loudspeaker protocol, similar to Nubert #define IRMP_LGAIR_PROTOCOL 40 // LG air conditioner #define IRMP_SAMSUNG48_PROTOCOL 41 // air conditioner with SAMSUNG protocol (48 bits) #define IRMP_MERLIN_PROTOCOL 42 // Merlin (Pollin 620 185) #define IRMP_PENTAX_PROTOCOL 43 // Pentax camera #define IRMP_FAN_PROTOCOL 44 // FAN (ventilator), very similar to NUBERT, but last bit is data bit instead of stop bit #define IRMP_S100_PROTOCOL 45 // very similar to RC5, but 14 instead of 13 data bits #define IRMP_ACP24_PROTOCOL 46 // Stiebel Eltron ACP24 air conditioner #define IRMP_TECHNICS_PROTOCOL 47 // Technics, similar to Matsushita, but 22 instead of 24 bits #define IRMP_PANASONIC_PROTOCOL 48 // Panasonic (Beamer), start bits similar to KASEIKYO #define IRMP_MITSU_HEAVY_PROTOCOL 49 // Mitsubishi-Heavy Aircondition, similar timing as Panasonic beamer #define IRMP_VINCENT_PROTOCOL 50 // Vincent #define IRMP_SAMSUNGAH_PROTOCOL 51 // SAMSUNG AH #define IRMP_IRMP16_PROTOCOL 52 // IRMP specific protocol for data transfer, e.g. between two microcontrollers via IR #define IRMP_GREE_PROTOCOL 53 // Gree climate #define IRMP_RCII_PROTOCOL 54 // RC II Infra Red Remote Control Protocol for FM8 #define IRMP_METZ_PROTOCOL 55 // METZ #define IRMP_ONKYO_PROTOCOL 56 // Like NEC but with 16 address + 16 command bits #define RF_GEN24_PROTOCOL 57 // RF Generic, 24 Bits (Pollin 550666, EAN 4049702006022 and many other similar RF remote controls)) #define RF_X10_PROTOCOL 58 // RF PC X10 Remote Control (Medion, Pollin 721815) #define RF_MEDION_PROTOCOL 59 // RF PC Medion Remote Control (Medion) #define IRMP_MELINERA_PROTOCOL 60 #define IRMP_RC6A20_PROTOCOL 61 // RC6A20, e.g. Sky+ #define IRMP_RC6A28_PROTOCOL 62 // RC6A28, e.g. Sky Q (Sky+ Pro) #define IRMP_N_PROTOCOLS 62 // number of supported protocols #if defined(UNIX_OR_WINDOWS) || IRMP_PROTOCOL_NAMES == 1 || IRSND_PROTOCOL_NAMES == 1 extern const char proto_unknown[] PROGMEM; extern const char proto_sircs[] PROGMEM; extern const char proto_nec[] PROGMEM; extern const char proto_samsung[] PROGMEM; extern const char proto_matsushita[] PROGMEM; extern const char proto_kaseikyo[] PROGMEM; extern const char proto_recs80[] PROGMEM; extern const char proto_rc5[] PROGMEM; extern const char proto_denon[] PROGMEM; extern const char proto_rc6[] PROGMEM; extern const char proto_samsung32[] PROGMEM; extern const char proto_apple[] PROGMEM; extern const char proto_recs80ext[] PROGMEM; extern const char proto_nubert[] PROGMEM; extern const char proto_bang_olufsen[] PROGMEM; extern const char proto_grundig[] PROGMEM; extern const char proto_nokia[] PROGMEM; extern const char proto_siemens[] PROGMEM; extern const char proto_fdc[] PROGMEM; extern const char proto_rccar[] PROGMEM; extern const char proto_jvc[] PROGMEM; extern const char proto_rc6a[] PROGMEM; extern const char proto_nikon[] PROGMEM; extern const char proto_ruwido[] PROGMEM; extern const char proto_ir60[] PROGMEM; extern const char proto_kathrein[] PROGMEM; extern const char proto_netbox[] PROGMEM; extern const char proto_nec16[] PROGMEM; extern const char proto_nec42[] PROGMEM; extern const char proto_lego[] PROGMEM; extern const char proto_thomson[] PROGMEM; extern const char proto_bose[] PROGMEM; extern const char proto_a1tvbox[] PROGMEM; extern const char proto_ortek[] PROGMEM; extern const char proto_telefunken[] PROGMEM; extern const char proto_roomba[] PROGMEM; extern const char proto_rcmm32[] PROGMEM; extern const char proto_rcmm24[] PROGMEM; extern const char proto_rcmm12[] PROGMEM; extern const char proto_speaker[] PROGMEM; extern const char proto_lgair[] PROGMEM; extern const char proto_samsung48[] PROGMEM; extern const char proto_merlin[] PROGMEM; extern const char proto_pentax[] PROGMEM; extern const char proto_fan[] PROGMEM; extern const char proto_s100[] PROGMEM; extern const char proto_acp24[] PROGMEM; extern const char proto_technics[] PROGMEM; extern const char proto_panasonic[] PROGMEM; extern const char proto_mitsu_heavy[] PROGMEM; extern const char proto_vincent[] PROGMEM; extern const char proto_samsungah[] PROGMEM; extern const char proto_irmp16[] PROGMEM; extern const char proto_gree[] PROGMEM; extern const char proto_rcii[] PROGMEM; extern const char proto_metz[] PROGMEM; extern const char proto_onkyo[] PROGMEM; extern const char proto_rf_gen24[] PROGMEM; extern const char proto_rf_x10[] PROGMEM; extern const char proto_rf_medion[] PROGMEM; extern const char proto_melinera[] PROGMEM; extern const char proto_rc6a20[] PROGMEM; extern const char proto_rc6a28[] PROGMEM; #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * timing constants: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // fm 22.09.2011: may not be more than 16000L, otherwise some JVC codes will not be accepted #define IRMP_TIMEOUT_TIME 15500.0e-6 // timeout after 15.5 ms darkness #define IRMP_TIMEOUT_TIME_MS 15500L // timeout after 15.5 ms darkness #if IRMP_SUPPORT_NIKON_PROTOCOL == 1 # define IRMP_TIMEOUT_NIKON_TIME 29500.0e-6 // 2nd timeout after 29.5 ms darkness (only for NIKON!) # define IRMP_TIMEOUT_NIKON_TIME_MS 29500L // 2nd timeout after 29.5 ms darkness typedef uint16_t PAUSE_LEN; # define IRMP_TIMEOUT_NIKON_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_NIKON_TIME + 0.5) #else # if (F_INTERRUPTS * IRMP_TIMEOUT_TIME_MS) / 1000000 >= 254 typedef uint16_t PAUSE_LEN; # else typedef uint8_t PAUSE_LEN; # endif #endif #define IRMP_TIMEOUT_LEN (PAUSE_LEN)(F_INTERRUPTS * IRMP_TIMEOUT_TIME + 0.5) #define IRMP_KEY_RELEASE_TIME 25.0e-3 // key release timeout detection after 25.0 ms darkness #define IRMP_KEY_RELEASE_LEN (uint16_t)(F_INTERRUPTS * IRMP_KEY_RELEASE_TIME + 0.5) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * flags of struct IRMP_PARAMETER: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_PARAM_FLAG_IS_MANCHESTER 0x01 #define IRMP_PARAM_FLAG_1ST_PULSE_IS_1 0x02 #define IRMP_PARAM_FLAG_IS_SERIAL 0x04 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * SIRCS: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define SIRCS_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse #define SIRCS_START_BIT_PAUSE_TIME 600.0e-6 // 600 usec pause #define SIRCS_1_PULSE_TIME 1200.0e-6 // 1200 usec pulse #define SIRCS_0_PULSE_TIME 600.0e-6 // 600 usec pulse #define SIRCS_PAUSE_TIME 600.0e-6 // 600 usec pause #define SIRCS_FRAMES 3 // SIRCS sends each frame 3 times #define SIRCS_AUTO_REPETITION_PAUSE_TIME 25.0e-3 // auto repetition after 25ms #define SIRCS_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms #define SIRCS_ADDRESS_OFFSET 15 // skip 15 bits #define SIRCS_ADDRESS_LEN 5 // read up to 5 address bits #define SIRCS_COMMAND_OFFSET 0 // skip 0 bits #define SIRCS_COMMAND_LEN 15 // read 12-15 command bits #define SIRCS_MINIMUM_DATA_LEN 12 // minimum data length #define SIRCS_COMPLETE_DATA_LEN 20 // complete length - may be up to 20 #define SIRCS_STOP_BIT 0 // has no stop bit #define SIRCS_LSB 1 // LSB...MSB #define SIRCS_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * NEC & NEC42 & NEC16 & LGAIR & MELINERA: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define NEC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse #define NEC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause #define NEC_REPEAT_START_BIT_PAUSE_TIME 2250.0e-6 // 2250 usec pause #define NEC_PULSE_TIME 560.0e-6 // 560 usec pulse #define NEC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause #define NEC_0_PAUSE_TIME 560.0e-6 // 560 usec pause #define NEC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define NEC_ADDRESS_OFFSET 0 // skip 0 bits #define NEC_ADDRESS_LEN 16 // read 16 address bits #define NEC_COMMAND_OFFSET 16 // skip 16 bits (8 address + 8 /address) #define NEC_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) #define NEC_COMPLETE_DATA_LEN 32 // complete length #define NEC_STOP_BIT 1 // has stop bit #define NEC_LSB 1 // LSB...MSB #define NEC_FLAGS 0 // flags #define NEC42_ADDRESS_OFFSET 0 // skip 0 bits #define NEC42_ADDRESS_LEN 13 // read 13 address bits #define NEC42_COMMAND_OFFSET 26 // skip 26 bits (2 x 13 address bits) #define NEC42_COMMAND_LEN 8 // read 8 command bits #define NEC42_COMPLETE_DATA_LEN 42 // complete length (2 x 13 + 2 x 8) #define LGAIR_ADDRESS_OFFSET 0 // skip 0 bits #define LGAIR_ADDRESS_LEN 8 // read 8 address bits #define LGAIR_COMMAND_OFFSET 8 // skip 8 bits (8 address) #define LGAIR_COMMAND_LEN 16 // read 16 bits (16 command) #define LGAIR_COMPLETE_DATA_LEN 28 // complete length (8 address + 16 command + 4 checksum) #define NEC16_ADDRESS_OFFSET 0 // skip 0 bits #define NEC16_ADDRESS_LEN 8 // read 8 address bits #define NEC16_COMMAND_OFFSET 8 // skip 8 bits (8 address) #define NEC16_COMMAND_LEN 8 // read 8 bits (8 command) #define NEC16_COMPLETE_DATA_LEN 16 // complete length #define MELINERA_START_BIT_PULSE_TIME 8800.0e-6 // 8800 usec pulse #define MELINERA_START_BIT_PAUSE_TIME 4100.0e-6 // 4100 usec pause #define MELINERA_0_PULSE_TIME 440.0e-6 // 430 usec pause #define MELINERA_0_PAUSE_TIME 590.0e-6 // 600 usec pause #define MELINERA_1_PULSE_TIME 970.0e-6 // 910 usec pause #define MELINERA_1_PAUSE_TIME 1140.0e-6 // 1160 usec pause #define MELINERA_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define MELINERA_ADDRESS_OFFSET 0 // skip 0 bits #define MELINERA_ADDRESS_LEN 0 // read 0 address bits #define MELINERA_COMMAND_OFFSET 0 // skip 0 bits (0 address) #define MELINERA_COMMAND_LEN 8 // read 8 bits (8 command) #define MELINERA_COMPLETE_DATA_LEN 8 // complete length #define MELINERA_STOP_BIT 1 // has stop bit #define MELINERA_LSB 0 // MSB #define MELINERA_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * SAMSUNG & SAMSUNG32 & SAMSUNG48: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define SAMSUNG_START_BIT_PULSE_TIME 4500.0e-6 // 4500 usec pulse #define SAMSUNG_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause #define SAMSUNG_PULSE_TIME 550.0e-6 // 550 usec pulse #define SAMSUNG_1_PAUSE_TIME 1500.0e-6 // 1550 usec pause #define SAMSUNG_0_PAUSE_TIME 500.0e-6 // 500 usec pause #define SAMSUNG_FRAME_REPEAT_PAUSE_TIME 25.0e-3 // frame repeat after 25ms #define SAMSUNG_ADDRESS_OFFSET 0 // skip 0 bits #define SAMSUNG_ADDRESS_LEN 16 // read 16 address bits #define SAMSUNG_ID_OFFSET 17 // skip 16 + 1 sync bit #define SAMSUNG_ID_LEN 4 // read 4 id bits #define SAMSUNG_COMMAND_OFFSET 21 // skip 16 + 1 sync + 4 data bits #define SAMSUNG_COMMAND_LEN 16 // read 16 command bits #define SAMSUNG_COMPLETE_DATA_LEN 37 // complete length #define SAMSUNG_STOP_BIT 1 // has stop bit #define SAMSUNG_LSB 1 // LSB...MSB? #define SAMSUNG_FLAGS 0 // flags #define SAMSUNG32_COMMAND_OFFSET 16 // skip 16 bits #define SAMSUNG32_COMMAND_LEN 16 // read 16 command bits #define SAMSUNG32_COMPLETE_DATA_LEN 32 // complete length #define SAMSUNG32_FRAMES 1 // SAMSUNG32 sends one frame #define SAMSUNG32_AUTO_REPETITION_PAUSE_TIME 47.0e-3 // repetition after 47 ms #define SAMSUNG32_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms #define SAMSUNG48_COMMAND_OFFSET 16 // skip 16 bits #define SAMSUNG48_COMMAND_LEN 32 // read 32 command bits #define SAMSUNG48_COMPLETE_DATA_LEN 48 // complete length #define SAMSUNG48_FRAMES 2 // SAMSUNG48 sends each frame 2 times #define SAMSUNG48_AUTO_REPETITION_PAUSE_TIME 5.0e-3 // repetition after 5 ms #define SAMSUNG48_FRAME_REPEAT_PAUSE_TIME 47.0e-3 // frame repeat after 47ms /*--------------------------------------------------------------------------------------------------------------------------------------------------- * SAMSUNGAH: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define SAMSUNGAH_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse #define SAMSUNGAH_START_BIT_PAUSE_TIME 1900.0e-6 // 1900 usec pause #define SAMSUNGAH_PULSE_TIME 450.0e-6 // 450 usec pulse #define SAMSUNGAH_1_PAUSE_TIME 1100.0e-6 // 1100 usec pause #define SAMSUNGAH_0_PAUSE_TIME 450.0e-6 // 450 usec pause #define SAMSUNGAH_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define SAMSUNGAH_ADDRESS_OFFSET 0 // skip 0 bits #define SAMSUNGAH_ADDRESS_LEN 16 // read 16 address bits, ignore 17..31 #define SAMSUNGAH_COMMAND_OFFSET 32 // skip 32 bits #define SAMSUNGAH_COMMAND_LEN 16 // read 32 bits #define SAMSUNGAH_COMPLETE_DATA_LEN 48 // complete length #define SAMSUNGAH_STOP_BIT 1 // has stop bit #define SAMSUNGAH_LSB 1 // LSB...MSB? #define SAMSUNGAH_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * MATSUSHITA: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define MATSUSHITA_START_BIT_PULSE_TIME 3488.0e-6 // 3488 usec pulse #define MATSUSHITA_START_BIT_PAUSE_TIME 3488.0e-6 // 3488 usec pause #define MATSUSHITA_PULSE_TIME 872.0e-6 // 872 usec pulse #define MATSUSHITA_1_PAUSE_TIME 2616.0e-6 // 2616 usec pause #define MATSUSHITA_0_PAUSE_TIME 872.0e-6 // 872 usec pause #define MATSUSHITA_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define MATSUSHITA_ADDRESS_OFFSET 12 // skip 12 bits #define MATSUSHITA_ADDRESS_LEN 12 // read 12 address bits #define MATSUSHITA_COMMAND_OFFSET 0 // skip 0 bits #define MATSUSHITA_COMMAND_LEN 12 // read 12 bits (6 custom + 6 command) #define MATSUSHITA_COMPLETE_DATA_LEN 24 // complete length #define MATSUSHITA_STOP_BIT 1 // has stop bit #define MATSUSHITA_LSB 1 // LSB...MSB? #define MATSUSHITA_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * TECHNICS: same timings as MATSUSHITA *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define TECHNICS_ADDRESS_LEN 0 // read 0 address bits #define TECHNICS_COMMAND_LEN 11 // read 11 bits #define TECHNICS_COMPLETE_DATA_LEN 22 // complete length /*--------------------------------------------------------------------------------------------------------------------------------------------------- * KASEIKYO: 48 bit *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define KASEIKYO_START_BIT_PULSE_TIME 3456.0e-6 // 3380 usec pulse #define KASEIKYO_START_BIT_PAUSE_TIME 1728.0e-6 // 1690 usec pause #define KASEIKYO_PULSE_TIME 432.0e-6 // 525 usec pulse #define KASEIKYO_1_PAUSE_TIME 1296.0e-6 // 525 usec pause #define KASEIKYO_0_PAUSE_TIME 432.0e-6 // 1690 usec pause #define KASEIKYO_AUTO_REPETITION_PAUSE_TIME 74.0e-3 // repetition after 74 ms #define KASEIKYO_FRAME_REPEAT_PAUSE_TIME 74.0e-3 // frame repeat after 74 ms #define KASEIKYO_ADDRESS_OFFSET 0 // skip 0 bits #define KASEIKYO_ADDRESS_LEN 16 // read 16 address / manufacturer bits #define KASEIKYO_COMMAND_OFFSET 28 // skip 28 bits (16 manufacturer & 4 parity & 8 genre) #define KASEIKYO_COMMAND_LEN 12 // read 12 command bits (10 real command & 2 id) #define KASEIKYO_COMPLETE_DATA_LEN 48 // complete length #define KASEIKYO_STOP_BIT 1 // has stop bit #define KASEIKYO_LSB 1 // LSB...MSB? #define KASEIKYO_FRAMES 1 // KASEIKYO sends 1 frame #define KASEIKYO_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * PANASONIC (Beamer), start bit timings similar to KASEIKYO 56 bit *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define PANASONIC_START_BIT_PULSE_TIME 3600.0e-6 // 3600 usec pulse #define PANASONIC_START_BIT_PAUSE_TIME 1600.0e-6 // 1690 usec pause #define PANASONIC_PULSE_TIME 432.0e-6 // 565 usec pulse #define PANASONIC_1_PAUSE_TIME 1296.0e-6 // 1140 usec pause #define PANASONIC_0_PAUSE_TIME 432.0e-6 // 316 usec pause #define PANASONIC_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40 ms? #define PANASONIC_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms #define PANASONIC_ADDRESS_OFFSET 24 // skip 24 bits: 010000000000010000000001 #define PANASONIC_ADDRESS_LEN 16 // read 16 address bits #define PANASONIC_COMMAND_OFFSET 40 // skip 40 bits #define PANASONIC_COMMAND_LEN 16 // read 16 command bits #define PANASONIC_COMPLETE_DATA_LEN 56 // complete length #define PANASONIC_STOP_BIT 1 // has stop bit #define PANASONIC_LSB 1 // LSB...MSB? #define PANASONIC_FRAMES 1 // PANASONIC sends 1 frame #define PANASONIC_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * MITSUBISHI-Heavy Aircondition, timings similar to PANASONIC beamer 88 bit *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define MITSU_HEAVY_START_BIT_PULSE_TIME 3200.0e-6 // 3600 usec pulse #define MITSU_HEAVY_START_BIT_PAUSE_TIME 1560.0e-6 // 1690 usec pause #define MITSU_HEAVY_PULSE_TIME 400.0e-6 // 565 usec pulse #define MITSU_HEAVY_1_PAUSE_TIME 1200.0e-6 // 1140 usec pause #define MITSU_HEAVY_0_PAUSE_TIME 430.0e-6 // 316 usec pause #define MITSU_HEAVY_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms #define MITSU_HEAVY_ADDRESS_OFFSET 40 // skip 24 bits: 010000000000010000000001 #define MITSU_HEAVY_ADDRESS_LEN 16 // read 16 address bits #define MITSU_HEAVY_COMMAND_OFFSET 56 // skip 40 bits #define MITSU_HEAVY_COMMAND_LEN 16 // read 16 command bits #define MITSU_HEAVY_COMPLETE_DATA_LEN 88 // complete length #define MITSU_HEAVY_STOP_BIT 1 // has stop bit #define MITSU_HEAVY_LSB 0 // LSB...MSB? #define MITSU_HEAVY_FRAMES 1 // PANASONIC sends 1 frame #define MITSU_HEAVY_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * VINCENT *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define VINCENT_START_BIT_PULSE_TIME 2500.0e-6 // 2500 usec pulse #define VINCENT_START_BIT_PAUSE_TIME 4600.0e-6 // 4600 usec pause #define VINCENT_PULSE_TIME 550.0e-6 // 550 usec pulse #define VINCENT_1_PAUSE_TIME 1540.0e-6 // 1540 usec pause #define VINCENT_0_PAUSE_TIME 550.0e-6 // 550 usec pause #define VINCENT_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40 ms ? #define VINCENT_ADDRESS_OFFSET 0 // skip 0 bits #define VINCENT_ADDRESS_LEN 16 // read 16 address bits #define VINCENT_COMMAND_OFFSET 16 // skip 16 bits #define VINCENT_COMMAND_LEN 16 // read 16 command bits #define VINCENT_COMPLETE_DATA_LEN 32 // complete length #define VINCENT_STOP_BIT 1 // has stop bit #define VINCENT_LSB 0 // LSB...MSB? #define VINCENT_FRAMES 1 // VINCENT sends 1 frame #define VINCENT_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RECS80: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RECS80_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse #define RECS80_START_BIT_PAUSE_TIME 7432.0e-6 // 7432 usec pause #define RECS80_PULSE_TIME 158.0e-6 // 158 usec pulse #define RECS80_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause #define RECS80_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause #define RECS80_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define RECS80_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit) #define RECS80_ADDRESS_LEN 3 // read 3 address bits #define RECS80_COMMAND_OFFSET 4 // skip 4 bits (1 toggle + 3 address) #define RECS80_COMMAND_LEN 6 // read 6 command bits #define RECS80_COMPLETE_DATA_LEN 10 // complete length #define RECS80_STOP_BIT 1 // has stop bit #define RECS80_LSB 0 // MSB...LSB #define RECS80_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RC5: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RC5_BIT_TIME 889.0e-6 // 889 usec pulse/pause #define RC5_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms #define RC5_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) #define RC5_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits #define RC5_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) #define RC5_COMMAND_LEN 6 // read 6 command bits #define RC5_COMPLETE_DATA_LEN 13 // complete length #define RC5_STOP_BIT 0 // has no stop bit #define RC5_LSB 0 // MSB...LSB #define RC5_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RCII: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RCII_START_BIT_PULSE_TIME 512.0e-6 // 512 usec pulse #define RCII_START_BIT_PAUSE_TIME 2560.0e-6 // 2560 usec pause #define RCII_START_BIT2_PULSE_TIME 1024.0e-6 // 1024 usec pulse #define RCII_BIT_TIME 512.0e-6 // 512 usec pulse/pause #define RCII_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // frame repeat after 117.76ms #define RCII_ADDRESS_OFFSET 0 // skip 1 bit (2nd start) #define RCII_ADDRESS_LEN 0 // no address #define RCII_COMMAND_OFFSET 0 // command offset is 0 #define RCII_COMMAND_LEN 10 // read 1 + 9 command bits #define RCII_COMPLETE_DATA_LEN 10 // complete length #define RCII_STOP_BIT 0 // has no stop bit #define RCII_LSB 0 // MSB...LSB #define RCII_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * S100: very similar to RC5, but 14 insted of 13 bits *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define S100_BIT_TIME 889.0e-6 // 889 usec pulse/pause #define S100_FRAME_REPEAT_PAUSE_TIME 88.9e-3 // frame repeat after 88.9ms #define S100_ADDRESS_OFFSET 1 // skip 1 bit (2nd start) #define S100_ADDRESS_LEN 6 // read 1 toggle bit (for key repetition detection) + 5 address bits #define S100_COMMAND_OFFSET 7 // skip 5 bits (2nd start + 1 toggle + 5 address) #define S100_COMMAND_LEN 7 // read 7 command bits #define S100_COMPLETE_DATA_LEN 14 // complete length #define S100_STOP_BIT 0 // has no stop bit #define S100_LSB 0 // MSB...LSB #define S100_FLAGS IRMP_PARAM_FLAG_IS_MANCHESTER // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * DENON: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define DENON_PULSE_TIME 310.0e-6 // 310 usec pulse in practice, 275 in theory #define DENON_1_PAUSE_TIME 1780.0e-6 // 1780 usec pause in practice, 1900 in theory #define DENON_0_PAUSE_TIME 745.0e-6 // 745 usec pause in practice, 775 in theory #define DENON_FRAMES 2 // DENON sends each frame 2 times #define DENON_AUTO_REPETITION_PAUSE_TIME 45.0e-3 // inverted repetition after 45ms #define DENON_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define DENON_ADDRESS_OFFSET 0 // skip 0 bits #define DENON_ADDRESS_LEN 5 // read 5 address bits #define DENON_COMMAND_OFFSET 5 // skip 5 #define DENON_COMMAND_LEN 10 // read 10 command bits #define DENON_COMPLETE_DATA_LEN 15 // complete length #define DENON_STOP_BIT 1 // has stop bit #define DENON_LSB 0 // MSB...LSB #define DENON_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RC6: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RC6_START_BIT_PULSE_TIME 2666.0e-6 // 2.666 msec pulse #define RC6_START_BIT_PAUSE_TIME 889.0e-6 // 889 usec pause #define RC6_TOGGLE_BIT_TIME 889.0e-6 // 889 msec pulse/pause #define RC6_BIT_TIME 444.0e-6 // 444 usec pulse/pause #define RC6_BIT_2_TIME 889.0e-6 // 889 usec pulse/pause #define RC6_BIT_3_TIME 1333.0e-6 // 1333 usec pulse/pause #define RC6_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define RC6_ADDRESS_OFFSET 5 // skip "1" + 3 mode bits + 1 toggle bit #define RC6_ADDRESS_LEN 8 // read 8 address bits #define RC6_COMMAND_OFFSET 13 // skip 12 bits ("1" + 3 mode + 1 toggle + 8 address) #define RC6_COMMAND_LEN 8 // read 8 command bits #define RC6_COMPLETE_DATA_LEN_SHORT 21 // complete length #define RC6_COMPLETE_DATA_LEN_20 25 // complete length #define RC6_COMPLETE_DATA_LEN_28 33 // complete length #define RC6_COMPLETE_DATA_LEN_LONG 36 // complete length #define RC6_STOP_BIT 0 // has no stop bit #define RC6_LSB 0 // MSB...LSB #define RC6_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RECS80EXT: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RECS80EXT_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse #define RECS80EXT_START_BIT_PAUSE_TIME 3637.0e-6 // 3637 usec pause #define RECS80EXT_PULSE_TIME 158.0e-6 // 158 usec pulse #define RECS80EXT_1_PAUSE_TIME 7432.0e-6 // 7432 usec pause #define RECS80EXT_0_PAUSE_TIME 4902.0e-6 // 4902 usec pause #define RECS80EXT_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define RECS80EXT_ADDRESS_OFFSET 2 // skip 2 bits (2nd start + 1 toggle) #define RECS80EXT_ADDRESS_LEN 4 // read 4 address bits #define RECS80EXT_COMMAND_OFFSET 6 // skip 6 bits (2nd start + 1 toggle + 4 address) #define RECS80EXT_COMMAND_LEN 6 // read 6 command bits #define RECS80EXT_COMPLETE_DATA_LEN 12 // complete length #define RECS80EXT_STOP_BIT 1 // has stop bit #define RECS80EXT_LSB 0 // MSB...LSB #define RECS80EXT_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * NUBERT: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define NUBERT_START_BIT_PULSE_TIME 1340.0e-6 // 1340 usec pulse #define NUBERT_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause #define NUBERT_1_PULSE_TIME 1340.0e-6 // 1340 usec pulse #define NUBERT_1_PAUSE_TIME 340.0e-6 // 340 usec pause #define NUBERT_0_PULSE_TIME 500.0e-6 // 500 usec pulse #define NUBERT_0_PAUSE_TIME 1300.0e-6 // 1300 usec pause #define NUBERT_FRAMES 2 // Nubert sends 2 frames #define NUBERT_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms #define NUBERT_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms #define NUBERT_ADDRESS_OFFSET 0 // skip 0 bits #define NUBERT_ADDRESS_LEN 0 // read 0 address bits #define NUBERT_COMMAND_OFFSET 0 // skip 0 bits #define NUBERT_COMMAND_LEN 10 // read 10 bits #define NUBERT_COMPLETE_DATA_LEN 10 // complete length #define NUBERT_STOP_BIT 1 // has stop bit #define NUBERT_LSB 0 // MSB? #define NUBERT_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * FAN: (ventilator) * * Similar to NUBERT, but * - has data bit instead of stop bit * - has NO frame repetition *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define FAN_START_BIT_PULSE_TIME 1280.0e-6 // 1280 usec pulse #define FAN_START_BIT_PAUSE_TIME 380.0e-6 // 380 usec pause #define FAN_1_PULSE_TIME 1280.0e-6 // 1280 usec pulse #define FAN_1_PAUSE_TIME 380.0e-6 // 380 usec pause #define FAN_0_PULSE_TIME 380.0e-6 // 380 usec pulse #define FAN_0_PAUSE_TIME 1280.0e-6 // 1280 usec pause #define FAN_FRAMES 1 // FAN sends only 1 frame (NUBERT sends 2) #define FAN_AUTO_REPETITION_PAUSE_TIME 6.6e-3 // auto repetition after 6.6ms #define FAN_FRAME_REPEAT_PAUSE_TIME 6.6e-3 // frame repeat after 6.6ms #define FAN_ADDRESS_OFFSET 0 // skip 0 bits #define FAN_ADDRESS_LEN 0 // read 0 address bits #define FAN_COMMAND_OFFSET 0 // skip 0 bits #define FAN_COMMAND_LEN 11 // read 10 bits #define FAN_COMPLETE_DATA_LEN 11 // complete length #define FAN_STOP_BIT 0 // has NO stop bit (fm: this seems to be wrong) #define FAN_LSB 0 // MSB #define FAN_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * SPEAKER: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define SPEAKER_START_BIT_PULSE_TIME 440.0e-6 // 440 usec pulse #define SPEAKER_START_BIT_PAUSE_TIME 1250.0e-6 // 1250 usec pause #define SPEAKER_1_PULSE_TIME 1250.0e-6 // 1250 usec pulse #define SPEAKER_1_PAUSE_TIME 440.0e-6 // 440 usec pause #define SPEAKER_0_PULSE_TIME 440.0e-6 // 440 usec pulse #define SPEAKER_0_PAUSE_TIME 1250.0e-6 // 1250 usec pause #define SPEAKER_FRAMES 2 // SPEAKER sends 2 frames #define SPEAKER_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms #define SPEAKER_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 45ms #define SPEAKER_ADDRESS_OFFSET 0 // skip 0 bits #define SPEAKER_ADDRESS_LEN 0 // read 0 address bits #define SPEAKER_COMMAND_OFFSET 0 // skip 0 bits #define SPEAKER_COMMAND_LEN 10 // read 10 bits #define SPEAKER_COMPLETE_DATA_LEN 10 // complete length #define SPEAKER_STOP_BIT 1 // has stop bit #define SPEAKER_LSB 0 // MSB? #define SPEAKER_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * BANG_OLUFSEN: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define BANG_OLUFSEN_START_BIT1_PULSE_TIME 200.0e-6 // 200 usec pulse #define BANG_OLUFSEN_START_BIT1_PAUSE_TIME 3125.0e-6 // 3125 usec pause #define BANG_OLUFSEN_START_BIT2_PULSE_TIME 200.0e-6 // 200 usec pulse #define BANG_OLUFSEN_START_BIT2_PAUSE_TIME 3125.0e-6 // 3125 usec pause #define BANG_OLUFSEN_START_BIT3_PULSE_TIME 200.0e-6 // 200 usec pulse #define BANG_OLUFSEN_START_BIT3_PAUSE_TIME 15625.0e-6 // 15625 usec pause #define BANG_OLUFSEN_START_BIT4_PULSE_TIME 200.0e-6 // 200 usec pulse #define BANG_OLUFSEN_START_BIT4_PAUSE_TIME 3125.0e-6 // 3125 usec pause #define BANG_OLUFSEN_PULSE_TIME 200.0e-6 // 200 usec pulse #define BANG_OLUFSEN_1_PAUSE_TIME 9375.0e-6 // 9375 usec pause #define BANG_OLUFSEN_0_PAUSE_TIME 3125.0e-6 // 3125 usec pause #define BANG_OLUFSEN_R_PAUSE_TIME 6250.0e-6 // 6250 usec pause (repeat last bit) #define BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME 12500.0e-6 // 12500 usec pause (trailer bit) #define BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define BANG_OLUFSEN_ADDRESS_OFFSET 0 // no address bits #define BANG_OLUFSEN_ADDRESS_LEN 0 // no address bits #define BANG_OLUFSEN_COMMAND_OFFSET 3 // skip startbits 2, 3, 4 #define BANG_OLUFSEN_COMMAND_LEN 16 // read 16 command bits #define BANG_OLUFSEN_COMPLETE_DATA_LEN 20 // complete length: startbits 2, 3, 4 + 16 data bits + trailer bit #define BANG_OLUFSEN_STOP_BIT 1 // has stop bit #define BANG_OLUFSEN_LSB 0 // MSB...LSB #define BANG_OLUFSEN_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * GRUNDIG & NOKIA *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define GRUNDIG_NOKIA_IR60_BIT_TIME 528.0e-6 // 528 usec pulse/pause #define GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME 2639.0e-6 // 2639 usec pause after pre bit #define GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME 117.76e-3 // info frame repeat after 117.76 ms #define GRUNDIG_NOKIA_IR60_STOP_BIT 0 // has no stop bit #define GRUNDIG_NOKIA_IR60_LSB 1 // MSB...LSB #define GRUNDIG_NOKIA_IR60_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags #define GRUNDIG_FRAMES 2 // GRUNDIG sends each frame 1+1 times #define GRUNDIG_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms #define GRUNDIG_ADDRESS_OFFSET 0 // no address #define GRUNDIG_ADDRESS_LEN 0 // no address #define GRUNDIG_COMMAND_OFFSET 1 // skip 1 start bit #define GRUNDIG_COMMAND_LEN 9 // read 9 command bits #define GRUNDIG_COMPLETE_DATA_LEN 10 // complete length: 1 start bit + 9 data bits #define NOKIA_FRAMES 3 // NOKIA sends each frame 1 + 1 + 1 times #define NOKIA_AUTO_REPETITION_PAUSE_TIME 20.0e-3 // repetition after 20ms #define NOKIA_ADDRESS_OFFSET 9 // skip 9 bits (1 start bit + 8 data bits) #define NOKIA_ADDRESS_LEN 8 // 7 address bits #define NOKIA_COMMAND_OFFSET 1 // skip 1 bit (1 start bit) #define NOKIA_COMMAND_LEN 8 // read 8 command bits #define NOKIA_COMPLETE_DATA_LEN 17 // complete length: 1 start bit + 8 address bits + 8 command bits /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IR60: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IR60_FRAMES 2 // IR60 sends each frame 1+1 times #define IR60_AUTO_REPETITION_PAUSE_TIME 22.2e-3 // repetition after 22.2ms #define IR60_TIMEOUT_TIME 5000.0e-6 // timeout grundig frame, switch to IR60 #define IR60_ADDRESS_OFFSET 0 // skip 1 bits #define IR60_ADDRESS_LEN 0 // read 0 address bits #define IR60_COMMAND_OFFSET 0 // skip 1 bit (start bit after pre bit, always 1) #define IR60_COMMAND_LEN 7 // read 6 command bits #define IR60_COMPLETE_DATA_LEN 7 // complete length /*--------------------------------------------------------------------------------------------------------------------------------------------------- * SIEMENS & RUWIDO: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME 275.0e-6 // 275 usec pulse #define SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME 550.0e-6 // 550 usec pause #define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME 275.0e-6 // 275 usec short pulse #define SIEMENS_OR_RUWIDO_BIT_PULSE_TIME_2 550.0e-6 // 550 usec long pulse #define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME 275.0e-6 // 275 usec short pause #define SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME_2 550.0e-6 // 550 usec long pause #define SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define SIEMENS_OR_RUWIDO_STOP_BIT 0 // has no stop bit #define SIEMENS_OR_RUWIDO_LSB 0 // MSB...LSB #define SIEMENS_OR_RUWIDO_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags #define RUWIDO_ADDRESS_OFFSET 0 // skip 0 bits #define RUWIDO_ADDRESS_LEN 9 // read 9 address bits #define RUWIDO_COMMAND_OFFSET 9 // skip 9 bits #define RUWIDO_COMMAND_LEN 8 // read 7 + 1 command bits, last bit is only check bit #define RUWIDO_COMPLETE_DATA_LEN 17 // complete length #define SIEMENS_ADDRESS_OFFSET 0 // skip 0 bits #define SIEMENS_ADDRESS_LEN 11 // read 11 bits #define SIEMENS_COMMAND_OFFSET 11 // skip 11 bits #define SIEMENS_COMMAND_LEN 11 // read 10 + 1 command bits, last bit is only check bit #define SIEMENS_COMPLETE_DATA_LEN 22 // complete length /*--------------------------------------------------------------------------------------------------------------------------------------------------- * FDC: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define FDC_START_BIT_PULSE_TIME 2085.0e-6 // 2085 usec pulse #define FDC_START_BIT_PAUSE_TIME 966.0e-6 // 966 usec pause #define FDC_PULSE_TIME 300.0e-6 // 300 usec pulse #define FDC_1_PAUSE_TIME 715.0e-6 // 715 usec pause #define FDC_0_PAUSE_TIME 220.0e-6 // 220 usec pause #define FDC_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms #define FDC_ADDRESS_OFFSET 0 // skip 0 bits #define FDC_ADDRESS_LEN 14 // read 14 address bits, but use only 6, shift 8 into command #define FDC_COMMAND_OFFSET 20 // skip 20 bits #define FDC_COMMAND_LEN 12 // read 12 bits #define FDC_COMPLETE_DATA_LEN 40 // complete length #define FDC_STOP_BIT 1 // has stop bit #define FDC_LSB 1 // LSB...MSB #define FDC_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RCCAR: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RCCAR_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse #define RCCAR_START_BIT_PAUSE_TIME 2000.0e-6 // 2000 usec pause #define RCCAR_PULSE_TIME 600.0e-6 // 360 usec pulse #define RCCAR_1_PAUSE_TIME 450.0e-6 // 650 usec pause #define RCCAR_0_PAUSE_TIME 900.0e-6 // 180 usec pause #define RCCAR_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define RCCAR_ADDRESS_OFFSET 0 // skip 0 bits #define RCCAR_ADDRESS_LEN 0 // read 0 address bits #define RCCAR_COMMAND_OFFSET 0 // skip 0 bits #define RCCAR_COMMAND_LEN 13 // read 13 bits #define RCCAR_COMPLETE_DATA_LEN 13 // complete length #define RCCAR_STOP_BIT 1 // has stop bit #define RCCAR_LSB 1 // LSB...MSB #define RCCAR_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * JVC: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define JVC_START_BIT_PULSE_TIME 9000.0e-6 // 9000 usec pulse #define JVC_START_BIT_PAUSE_TIME 4500.0e-6 // 4500 usec pause #define JVC_PULSE_TIME 560.0e-6 // 560 usec pulse #define JVC_1_PAUSE_TIME 1690.0e-6 // 1690 usec pause #define JVC_0_PAUSE_TIME 560.0e-6 // 560 usec pause #define JVC_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms #define JVC_ADDRESS_OFFSET 0 // skip 0 bits #define JVC_ADDRESS_LEN 4 // read 4 address bits #define JVC_COMMAND_OFFSET 4 // skip 4 bits #define JVC_COMMAND_LEN 12 // read 12 bits #define JVC_COMPLETE_DATA_LEN 16 // complete length #define JVC_STOP_BIT 1 // has stop bit #define JVC_LSB 1 // LSB...MSB #define JVC_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * NIKON: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define NIKON_START_BIT_PULSE_TIME 2200.0e-6 // 2200 usec pulse #define NIKON_START_BIT_PAUSE_TIME 27100.0e-6 // 27100 usec pause #define NIKON_PULSE_TIME 500.0e-6 // 500 usec pulse #define NIKON_1_PAUSE_TIME 3500.0e-6 // 3500 usec pause #define NIKON_0_PAUSE_TIME 1500.0e-6 // 1500 usec pause #define NIKON_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms #define NIKON_ADDRESS_OFFSET 0 // skip 0 bits #define NIKON_ADDRESS_LEN 0 // read 0 address bits #define NIKON_COMMAND_OFFSET 0 // skip 0 bits #define NIKON_COMMAND_LEN 2 // read 2 bits #define NIKON_COMPLETE_DATA_LEN 2 // complete length #define NIKON_STOP_BIT 1 // has stop bit #define NIKON_LSB 0 // LSB...MSB #define NIKON_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * KATHREIN: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define KATHREIN_START_BIT_PULSE_TIME 210.0e-6 // 1340 usec pulse #define KATHREIN_START_BIT_PAUSE_TIME 6218.0e-6 // 340 usec pause #define KATHREIN_1_PULSE_TIME 210.0e-6 // 1340 usec pulse #define KATHREIN_1_PAUSE_TIME 3000.0e-6 // 340 usec pause #define KATHREIN_0_PULSE_TIME 210.0e-6 // 500 usec pulse #define KATHREIN_0_PAUSE_TIME 1400.0e-6 // 1300 usec pause #define KATHREIN_SYNC_BIT_PAUSE_LEN_TIME 4600.0e-6 // 4600 usec sync (on 6th and/or 8th bit) #define KATHREIN_FRAMES 1 // Kathrein sends 1 frame #define KATHREIN_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms #define KATHREIN_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms #define KATHREIN_ADDRESS_OFFSET 1 // skip 1 bits #define KATHREIN_ADDRESS_LEN 4 // read 4 address bits #define KATHREIN_COMMAND_OFFSET 5 // skip 5 bits #define KATHREIN_COMMAND_LEN 7 // read 7 bits #define KATHREIN_COMPLETE_DATA_LEN 13 // complete length #define KATHREIN_STOP_BIT 1 // has stop bit #define KATHREIN_LSB 0 // MSB #define KATHREIN_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * NETBOX: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define NETBOX_START_BIT_PULSE_TIME 2400.0e-6 // 2400 usec pulse #define NETBOX_START_BIT_PAUSE_TIME 800.0e-6 // 800 usec pause #define NETBOX_PULSE_TIME 800.0e-6 // 800 usec pulse #define NETBOX_PAUSE_TIME 800.0e-6 // 800 usec pause #define NETBOX_FRAMES 1 // Netbox sends 1 frame #define NETBOX_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // auto repetition after 35ms #define NETBOX_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms #define NETBOX_ADDRESS_OFFSET 0 // skip 0 bits #define NETBOX_ADDRESS_LEN 3 // read 3 address bits #define NETBOX_COMMAND_OFFSET 3 // skip 3 bits #define NETBOX_COMMAND_LEN 13 // read 13 bits #define NETBOX_COMPLETE_DATA_LEN 16 // complete length #define NETBOX_STOP_BIT 0 // has no stop bit #define NETBOX_LSB 1 // LSB #define NETBOX_FLAGS IRMP_PARAM_FLAG_IS_SERIAL // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * LEGO: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define LEGO_START_BIT_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) #define LEGO_START_BIT_PAUSE_TIME 1026.0e-6 // 1026 usec pause (39 x 1/38kHz) #define LEGO_PULSE_TIME 158.0e-6 // 158 usec pulse ( 6 x 1/38kHz) #define LEGO_1_PAUSE_TIME 553.0e-6 // 553 usec pause (21 x 1/38kHz) #define LEGO_0_PAUSE_TIME 263.0e-6 // 263 usec pause (10 x 1/38kHz) #define LEGO_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define LEGO_ADDRESS_OFFSET 0 // skip 0 bits #define LEGO_ADDRESS_LEN 0 // read 0 address bits #define LEGO_COMMAND_OFFSET 0 // skip 0 bits #define LEGO_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) #define LEGO_COMPLETE_DATA_LEN 16 // complete length #define LEGO_STOP_BIT 1 // has stop bit #define LEGO_LSB 0 // MSB...LSB #define LEGO_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * THOMSON: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define THOMSON_PULSE_TIME 550.0e-6 // 550 usec pulse #define THOMSON_1_PAUSE_TIME 4500.0e-6 // 4500 usec pause #define THOMSON_0_PAUSE_TIME 2000.0e-6 // 2000 usec pause #define THOMSON_FRAMES 1 // THOMSON sends 1 frame #define THOMSON_AUTO_REPETITION_PAUSE_TIME 35.0e-3 // repetition after 35ms #define THOMSON_FRAME_REPEAT_PAUSE_TIME 35.0e-3 // frame repeat after 35ms #define THOMSON_ADDRESS_OFFSET 0 // skip 0 bits #define THOMSON_ADDRESS_LEN 4 // read 4 address bits #define THOMSON_COMMAND_OFFSET 5 // skip 4 address bits + 1 toggle bit #define THOMSON_COMMAND_LEN 7 // read 7 command bits #define THOMSON_COMPLETE_DATA_LEN 12 // complete length #define THOMSON_STOP_BIT 1 // has stop bit #define THOMSON_LSB 0 // MSB...LSB #define THOMSON_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * BOSE: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define BOSE_START_BIT_PULSE_TIME 1060.0e-6 // 1060 usec pulse #define BOSE_START_BIT_PAUSE_TIME 1425.0e-6 // 1425 usec pause #define BOSE_PULSE_TIME 550.0e-6 // 550 usec pulse #define BOSE_1_PAUSE_TIME 1425.0e-6 // 1425 usec pause #define BOSE_0_PAUSE_TIME 437.0e-6 // 437 usec pause #define BOSE_FRAMES 1 #define BOSE_AUTO_REPETITION_PAUSE_TIME 40.0e-3 // repetition after 40ms? #define BOSE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms? #define BOSE_ADDRESS_OFFSET 0 // skip 0 bits #define BOSE_ADDRESS_LEN 0 // read 16 address bits #define BOSE_COMMAND_OFFSET 0 // skip 16 bits (8 address + 8 /address) #define BOSE_COMMAND_LEN 16 // read 16 bits (8 command + 8 /command) #define BOSE_COMPLETE_DATA_LEN 16 // complete length #define BOSE_STOP_BIT 1 // has stop bit #define BOSE_LSB 1 // LSB...MSB #define BOSE_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * A1TVBOX: * In reality A1 TV Box has no start bit with 300/340 usec. There are 2 start bits "10" with 250us pulse + 150us pause + 150us pause + 250us pulse * This is not very easy to detect, because 1st and 2nd pause of both start bits are closely spaced. * So IRMP looks for pseudo start bit with 300/340 usec and ignores the second half of the 2nd bit (250us pulse) * This method only works because the first data bit (which is the 3rd bit) following is always "1": * IRMP treats the first "long" pulse (250us of 2nd start bit + 250us of 1st data bit) of this "1" as a first _short_ pulse. * This is a bug in IRMP's manchester decoder, but a good feature here ;-) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define A1TVBOX_START_BIT_PULSE_TIME 300.0e-6 // 300 usec pulse #define A1TVBOX_START_BIT_PAUSE_TIME 340.0e-6 // 340 usec pause #define A1TVBOX_BIT_PULSE_TIME 250.0e-6 // 250 usec pulse #define A1TVBOX_BIT_PAUSE_TIME 150.0e-6 // 150 usec pulse #define A1TVBOX_STOP_BIT 0 // has no stop bit #define A1TVBOX_LSB 0 // MSB...LSB #define A1TVBOX_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags #define A1TVBOX_FRAMES 1 // A1TVBOX sends each frame 1 times #define A1TVBOX_ADDRESS_OFFSET 1 // skip 1 bits #define A1TVBOX_ADDRESS_LEN 8 // read 8 address bits #define A1TVBOX_COMMAND_OFFSET 9 // skip 9 bits (start bit + address) #define A1TVBOX_COMMAND_LEN 8 // read 8 command bits #define A1TVBOX_COMPLETE_DATA_LEN 17 // complete length incl. start bit #define A1TVBOX_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct /*--------------------------------------------------------------------------------------------------------------------------------------------------- * MERLIN: * See notes for A1TVBOX *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define MERLIN_START_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse #define MERLIN_START_BIT_PAUSE_TIME 420.0e-6 // 429 usec pause #define MERLIN_BIT_PULSE_TIME 210.0e-6 // 210 usec pulse #define MERLIN_BIT_PAUSE_TIME 210.0e-6 // 210 usec pulse #define MERLIN_STOP_BIT 0 // has no stop bit #define MERLIN_LSB 0 // MSB...LSB #define MERLIN_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1 ) // flags #define MERLIN_FRAMES 1 // MERLIN sends each frame 1 times #define MERLIN_ADDRESS_OFFSET 2 // skip 1 bits #define MERLIN_ADDRESS_LEN 9 // read 9 address bits #define MERLIN_COMMAND_OFFSET 11 // skip 11 bits (start bit + address) #define MERLIN_COMMAND_LEN 16 // read up to 16 command bits (could be up to 32) #define MERLIN_COMPLETE_DATA_LEN 27 // complete length incl. start bit #define MERLIN_FRAME_REPEAT_PAUSE_TIME 50.0e-3 // 50 msec pause between frames, don't know if it is correct /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ORTEK (Hama): 6 address bits + 2 frame type bits + 6 command bits + 1 parity bit + 1 unknown bit + "1" + "0" *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define ORTEK_START_BIT_PULSE_TIME 2000.0e-6 // 2000 usec pulse #define ORTEK_START_BIT_PAUSE_TIME 1000.0e-6 // 1000 usec pause #define ORTEK_BIT_TIME 500.0e-6 // 500 usec pulse/pause #define ORTEK_FRAME_REPEAT_PAUSE_TIME 45.0e-3 // frame repeat after 45ms #define ORTEK_ADDRESS_OFFSET 0 // skip 0 bits #define ORTEK_ADDRESS_LEN 8 // read 6 address bits + 2 special bits #define ORTEK_COMMAND_OFFSET 8 // skip 6 address bits + 2 special bits #define ORTEK_COMMAND_LEN 6 // read 6 command bits #define ORTEK_COMPLETE_DATA_LEN 18 // complete length #define ORTEK_STOP_BIT 0 // has no stop bit #define ORTEK_LSB 0 // MSB...LSB #define ORTEK_FLAGS (IRMP_PARAM_FLAG_IS_MANCHESTER | IRMP_PARAM_FLAG_1ST_PULSE_IS_1) // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * TELEFUNKEN: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define TELEFUNKEN_START_BIT_PULSE_TIME 600.0e-6 // 600 usec pulse #define TELEFUNKEN_START_BIT_PAUSE_TIME 1500.0e-6 // 1500 usec pause #define TELEFUNKEN_PULSE_TIME 600.0e-6 // 600 usec pulse #define TELEFUNKEN_1_PAUSE_TIME 1500.0e-6 // 1500 usec pause #define TELEFUNKEN_0_PAUSE_TIME 600.0e-6 // 600 usec pause #define TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after XX ms ????? #define TELEFUNKEN_ADDRESS_OFFSET 0 // skip 0 bits #define TELEFUNKEN_ADDRESS_LEN 0 // read 0 address bits #define TELEFUNKEN_COMMAND_OFFSET 0 // skip 0 bits #define TELEFUNKEN_COMMAND_LEN 15 // read 15 bits #define TELEFUNKEN_COMPLETE_DATA_LEN 15 // complete length #define TELEFUNKEN_STOP_BIT 1 // has stop bit #define TELEFUNKEN_LSB 0 // LSB...MSB #define TELEFUNKEN_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ROOMBA *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define ROOMBA_START_BIT_PULSE_TIME 2790.0e-6 // 2790 usec pulse #define ROOMBA_START_BIT_PAUSE_TIME 930.0e-6 // 930 usec pause #define ROOMBA_0_PULSE_TIME 930.0e-6 // 930 usec pulse #define ROOMBA_1_PULSE_TIME 2790.0e-6 // 2790 usec pulse #define ROOMBA_0_PAUSE_TIME 2790.0e-6 // 2790 usec pause #define ROOMBA_1_PAUSE_TIME 930.0e-6 // 930 usec pause #define ROOMBA_FRAME_REPEAT_PAUSE_TIME 18.0e-3 // frame repeat after 18ms #define ROOMBA_ADDRESS_OFFSET 0 // skip 0 bits #define ROOMBA_ADDRESS_LEN 0 // read 0 address bits #define ROOMBA_COMMAND_OFFSET 0 // skip 0 bits #define ROOMBA_COMMAND_LEN 7 // read 7 bits #define ROOMBA_COMPLETE_DATA_LEN 7 // complete length #define ROOMBA_STOP_BIT 0 // has stop bit (fm: sure?) #define ROOMBA_LSB 0 // MSB...LSB #define ROOMBA_FLAGS 0 // flags #define ROOMBA_FRAMES 8 // ROOMBA sends 8 frames (this is a lie, but more comfortable) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RC-MM (32, 24, or 12 bit) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RCMM32_START_BIT_PULSE_TIME 500.0e-6 // 500 usec pulse #define RCMM32_START_BIT_PAUSE_TIME 220.0e-6 // 220 usec pause #define RCMM32_PULSE_TIME 230.0e-6 // 230 usec pulse #define RCMM32_00_PAUSE_TIME 220.0e-6 // 220 usec pause #define RCMM32_01_PAUSE_TIME 370.0e-6 // 370 usec pause #define RCMM32_10_PAUSE_TIME 540.0e-6 // 540 usec pause #define RCMM32_11_PAUSE_TIME 720.0e-6 // 720 usec pause #define RCMM32_FRAME_REPEAT_PAUSE_TIME 80.0e-3 // frame repeat after 80 ms #define RCMM32_ADDRESS_OFFSET 0 // skip 0 bits #define RCMM32_ADDRESS_LEN 16 // read 16 address bits #define RCMM32_COMMAND_OFFSET 17 // skip 17 bits #define RCMM32_COMMAND_LEN 15 // read 15 bits #define RCMM32_COMPLETE_DATA_LEN 32 // complete length #define RCMM32_STOP_BIT 1 // has stop bit #define RCMM32_LSB 0 // LSB...MSB #define RCMM32_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * PENTAX: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define PENTAX_START_BIT_PULSE_TIME 13000.0e-6 // 13 msec pulse #define PENTAX_START_BIT_PAUSE_TIME 3000.0e-6 // 3 msec pause #define PENTAX_PULSE_TIME 1000.0e-6 // 1 msec pulse #define PENTAX_1_PAUSE_TIME 3000.0e-6 // 3 msec pause #define PENTAX_0_PAUSE_TIME 1000.0e-6 // 1 msec pause #define PENTAX_FRAME_REPEAT_PAUSE_TIME 60.0e-3 // frame repeat after 60ms #define PENTAX_ADDRESS_OFFSET 0 // skip 0 bits #define PENTAX_ADDRESS_LEN 0 // read 0 address bits #define PENTAX_COMMAND_OFFSET 0 // skip 0 bits #define PENTAX_COMMAND_LEN 6 // read 6 bits #define PENTAX_COMPLETE_DATA_LEN 6 // complete length #define PENTAX_STOP_BIT 1 // has stop bit #define PENTAX_LSB 0 // LSB...MSB #define PENTAX_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ACP24: Stiebel Eltron ACP24 air conditioner *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define ACP24_START_BIT_PULSE_TIME 390.0e-6 // 390 usec pulse #define ACP24_START_BIT_PAUSE_TIME 950.0e-6 // 950 usec pause #define ACP24_PULSE_TIME 390.0e-6 // 390 usec pulse #define ACP24_1_PAUSE_TIME 1300.0e-6 // 1300 usec pause #define ACP24_0_PAUSE_TIME 950.0e-6 // 950 usec pause #define ACP24_FRAME_REPEAT_PAUSE_TIME 22.0e-3 // frame repeat after 22ms? #define ACP24_ADDRESS_OFFSET 0 // skip 0 bits #define ACP24_ADDRESS_LEN 0 // read 6 address bits #define ACP24_COMMAND_OFFSET 0 // skip 6 bits #define ACP24_COMMAND_LEN 0 // read 0 bits (70 bits will be read and compressed by special routine) #define ACP24_COMPLETE_DATA_LEN 70 // complete length #define ACP24_STOP_BIT 1 // has stop bit #define ACP24_LSB 0 // LSB...MSB #define ACP24_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IRMP16: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP16_START_BIT_PULSE_TIME 842.0e-6 // 842 usec pulse (32 x 1/38kHz) #define IRMP16_START_BIT_PAUSE_TIME 1052.0e-6 // 1052 usec pause (40 x 1/38kHz) #define IRMP16_PULSE_TIME 421.0e-6 // 421 usec pulse (16 x 1/38kHz) #define IRMP16_1_PAUSE_TIME 842.0e-6 // 842 usec pause (32 x 1/38kHz) #define IRMP16_0_PAUSE_TIME 421.0e-6 // 421 usec pause (16 x 1/38kHz) #define IRMP16_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define IRMP16_ADDRESS_OFFSET 0 // skip 0 bits #define IRMP16_ADDRESS_LEN 0 // read 0 address bits #define IRMP16_COMMAND_OFFSET 0 // skip 0 bits #define IRMP16_COMMAND_LEN 16 // read 16 bits (12 command + 4 CRC) #define IRMP16_COMPLETE_DATA_LEN 16 // complete length #define IRMP16_STOP_BIT 1 // has stop bit #define IRMP16_LSB 1 // LSB...MSB #define IRMP16_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * GREE - climate: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define GREE_START_BIT_PULSE_TIME 12000.0e-6 // 12000 usec pulse (32 x 1/38kHz) #define GREE_START_BIT_PAUSE_TIME 6000.0e-6 // 6000 usec pause (40 x 1/38kHz) #define GREE_PULSE_TIME 900.0e-6 // 900 usec pulse (16 x 1/38kHz) #define GREE_1_PAUSE_TIME 700.0e-6 // 700 usec pause (32 x 1/38kHz) #define GREE_0_PAUSE_TIME 2100.0e-6 // 2100 usec pause (16 x 1/38kHz) #define GREE_FRAME_REPEAT_PAUSE_TIME 40.0e-3 // frame repeat after 40ms #define GREE_ADDRESS_OFFSET 0 // skip 0 bits #define GREE_ADDRESS_LEN 16 // read 16 address bits #define GREE_COMMAND_OFFSET 16 // skip 16 bits #define GREE_COMMAND_LEN 16 // read 16 bits #define GREE_COMPLETE_DATA_LEN 32 // complete length #define GREE_STOP_BIT 1 // has stop bit #define GREE_LSB 1 // LSB...MSB #define GREE_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * METZ: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define METZ_START_BIT_PULSE_TIME 870.0e-6 // 870 usec pulse #define METZ_START_BIT_PAUSE_TIME 2300.0e-6 // 2300 usec pause #define METZ_PULSE_TIME 435.0e-6 // 435 usec pulse #define METZ_1_PAUSE_TIME 1680.0e-6 // 1680 usec pause #define METZ_0_PAUSE_TIME 960.0e-6 // 960 usec pause #define METZ_FRAME_REPEAT_PAUSE_TIME 122.0e-3 // frame repeat after 122ms #define METZ_ADDRESS_OFFSET 1 // skip 1 bit (toggle bit) #define METZ_ADDRESS_LEN 6 // read 6 address bits #define METZ_COMMAND_OFFSET 7 // skip 7 bits #define METZ_COMMAND_LEN 13 // read 13 bits #define METZ_COMPLETE_DATA_LEN 20 // complete length #define METZ_STOP_BIT 0 // has no stop bit #define METZ_LSB 0 // MSB...LSB #define METZ_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RF GEN24 generic remote control (Pollin 550666, EAN 4049702006022 and many other similar RF remote controls) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RF_GEN24_0_PULSE_TIME 400.0e-6 // 400 usec pulse #define RF_GEN24_0_PAUSE_TIME 1066.0e-6 // 1066 usec pause #define RF_GEN24_1_PULSE_TIME 1066.0e-6 // 1066 usec pulse #define RF_GEN24_1_PAUSE_TIME 400.0e-6 // 400 usec pause #define RF_GEN24_FRAME_REPEAT_PAUSE_TIME 10.0e-3 // frame repeat after 10 msec #define RF_GEN24_ADDRESS_OFFSET 0 // skip 0 bits #define RF_GEN24_ADDRESS_LEN 10 // read 10 address bits #define RF_GEN24_COMMAND_OFFSET 10 // skip 0 + 10 bits #define RF_GEN24_COMMAND_LEN 14 // read 14 command bits #define RF_GEN24_COMPLETE_DATA_LEN 24 // complete length #define RF_GEN24_STOP_BIT 1 // has stop bit #define RF_GEN24_LSB 0 // MSB...LSB #define RF_GEN24_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RF X10 remote control (MEDION, Pollin 721815) * * Frame: * 1 toggle bit + 7 checksum bits + 1 toggle bit + 7 command bits + 4 channel bits * * Rule: * checksum = (command + 0x0055 + (channel << 4)) & 0x7F * * Here we store checksum in address, command incl. 4 channel bits in command * * In irmp_get_data(): * irmp_command = command << 4 * irmp_address = channel + 1 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RF_X10_START_BIT_PULSE_TIME 2850.0e-6 // 2850 usec pulse #define RF_X10_START_BIT_PAUSE_TIME 1710.0e-6 // 1710 usec pulse #define RF_X10_0_PULSE_TIME 570.0e-6 // 570 usec pulse #define RF_X10_0_PAUSE_TIME 570.0e-6 // 570 usec pause #define RF_X10_1_PULSE_TIME 570.0e-6 // 570 usec pulse #define RF_X10_1_PAUSE_TIME 1710.0e-6 // 1710 usec pause #define RF_X10_FRAME_REPEAT_PAUSE_TIME 4456.0e-6 // frame repeat after 4460 usec #define RF_X10_ADDRESS_OFFSET 1 // skip 1st toggle bit #define RF_X10_ADDRESS_LEN 7 // store 7 command bits in address #define RF_X10_COMMAND_OFFSET 9 // skip 1st toggle bit + 7 command bits + 2nd toggle bit #define RF_X10_COMMAND_LEN 11 // read 7 alternative command bits plus 4 0-bits #define RF_X10_COMPLETE_DATA_LEN 20 // complete length #define RF_X10_STOP_BIT 1 // has stop bit #define RF_X10_LSB 0 // MSB...LSB #define RF_X10_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * RF MEDION PC remote control (MEDION) * * Frame is simular to RF_X10, see above. Only the start bit timing differs. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define RF_MEDION_START_BIT_PULSE_TIME 3960.0e-6 // 3960 usec pulse #define RF_MEDION_START_BIT_PAUSE_TIME 610.0e-6 // 610 usec pulse #define RF_MEDION_0_PULSE_TIME 570.0e-6 // 570 usec pulse #define RF_MEDION_0_PAUSE_TIME 570.0e-6 // 570 usec pause #define RF_MEDION_1_PULSE_TIME 570.0e-6 // 570 usec pulse #define RF_MEDION_1_PAUSE_TIME 1710.0e-6 // 1710 usec pause #define RF_MEDION_FRAME_REPEAT_PAUSE_TIME 5000.0e-6 // frame repeat after 5000 usec #define RF_MEDION_ADDRESS_OFFSET 1 // skip 1st toggle bit #define RF_MEDION_ADDRESS_LEN 7 // store 7 command bits in address #define RF_MEDION_COMMAND_OFFSET 9 // skip 1st toggle bit + 7 command bits + 2nd toggle bit #define RF_MEDION_COMMAND_LEN 11 // read 7 alternative command bits plus 4 0-bits #define RF_MEDION_COMPLETE_DATA_LEN 20 // complete length #define RF_MEDION_STOP_BIT 1 // has stop bit #define RF_MEDION_LSB 0 // MSB...LSB #define RF_MEDION_FLAGS 0 // flags /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Frame Repetitions: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define AUTO_FRAME_REPETITION_TIME 80.0e-3 // SIRCS/SAMSUNG32/NUBERT: automatic repetition after 25-50ms #endif // _IRMP_PROTOCOLS_H_ ================================================ FILE: src/irmpprotocols.hpp ================================================ /* * irmpprotocols.hpp - irmp protocols * * 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 . * */ #ifndef IRMP_PROTOCOLS_HPP #define IRMP_PROTOCOLS_HPP /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IR protocol strings for IRMP and IRSND: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ const char proto_unknown[] PROGMEM = "UNKNOWN"; const char proto_sircs[] PROGMEM = "SIRCS"; const char proto_nec[] PROGMEM = "NEC"; const char proto_samsung[] PROGMEM = "SAMSUNG"; const char proto_matsushita[] PROGMEM = "MATSUSH"; const char proto_kaseikyo[] PROGMEM = "KASEIKYO"; const char proto_recs80[] PROGMEM = "RECS80"; const char proto_rc5[] PROGMEM = "RC5"; const char proto_denon[] PROGMEM = "DENON"; const char proto_rc6[] PROGMEM = "RC6"; const char proto_samsung32[] PROGMEM = "SAMSG32"; const char proto_apple[] PROGMEM = "APPLE"; const char proto_recs80ext[] PROGMEM = "RECS80EX"; const char proto_nubert[] PROGMEM = "NUBERT"; const char proto_bang_olufsen[] PROGMEM = "BANG OLU"; const char proto_grundig[] PROGMEM = "GRUNDIG"; const char proto_nokia[] PROGMEM = "NOKIA"; const char proto_siemens[] PROGMEM = "SIEMENS"; const char proto_fdc[] PROGMEM = "FDC"; const char proto_rccar[] PROGMEM = "RCCAR"; const char proto_jvc[] PROGMEM = "JVC"; const char proto_rc6a[] PROGMEM = "RC6A"; const char proto_nikon[] PROGMEM = "NIKON"; const char proto_ruwido[] PROGMEM = "RUWIDO"; const char proto_ir60[] PROGMEM = "IR60"; const char proto_kathrein[] PROGMEM = "KATHREIN"; const char proto_netbox[] PROGMEM = "NETBOX"; const char proto_nec16[] PROGMEM = "NEC16"; const char proto_nec42[] PROGMEM = "NEC42"; const char proto_lego[] PROGMEM = "LEGO"; const char proto_thomson[] PROGMEM = "THOMSON"; const char proto_bose[] PROGMEM = "BOSE"; const char proto_a1tvbox[] PROGMEM = "A1TVBOX"; const char proto_ortek[] PROGMEM = "ORTEK"; const char proto_telefunken[] PROGMEM = "TELEFUNKEN"; const char proto_roomba[] PROGMEM = "ROOMBA"; const char proto_rcmm32[] PROGMEM = "RCMM32"; const char proto_rcmm24[] PROGMEM = "RCMM24"; const char proto_rcmm12[] PROGMEM = "RCMM12"; const char proto_speaker[] PROGMEM = "SPEAKER"; const char proto_lgair[] PROGMEM = "LGAIR"; const char proto_samsung48[] PROGMEM = "SAMSG48"; const char proto_merlin[] PROGMEM = "MERLIN"; const char proto_pentax[] PROGMEM = "PENTAX"; const char proto_fan[] PROGMEM = "FAN"; const char proto_s100[] PROGMEM = "S100"; const char proto_acp24[] PROGMEM = "ACP24"; const char proto_technics[] PROGMEM = "TECHNICS"; const char proto_panasonic[] PROGMEM = "PANASONIC"; const char proto_mitsu_heavy[] PROGMEM = "MITSU_HEAVY"; const char proto_vincent[] PROGMEM = "VINCENT"; const char proto_samsungah[] PROGMEM = "SAMSUNGAH"; const char proto_irmp16[] PROGMEM = "IRMP16"; const char proto_gree[] PROGMEM = "GREE"; const char proto_rcii[] PROGMEM = "RCII"; const char proto_metz[] PROGMEM = "METZ"; const char proto_onkyo[] PROGMEM = "ONKYO"; const char proto_rf_gen24[] PROGMEM = "RF_GEN24"; const char proto_rf_x10[] PROGMEM = "RF_X10"; const char proto_rf_medion[] PROGMEM = "RF_MEDION"; const char proto_melinera[] PROGMEM = "MELINERA"; const char proto_rc6a20[] PROGMEM = "RC6A20"; const char proto_rc6a28[] PROGMEM = "RC6A28"; /* * Must be in the same order as the Protocol numbers in irmpprotocols.h starting with IRMP_UNKNOWN_PROTOCOL = 0 */ const char * const irmp_protocol_names[IRMP_N_PROTOCOLS + 1] PROGMEM = { proto_unknown, proto_sircs, proto_nec, proto_samsung, proto_matsushita, proto_kaseikyo, proto_recs80, proto_rc5, proto_denon, proto_rc6, proto_samsung32, proto_apple, proto_recs80ext, proto_nubert, proto_bang_olufsen, proto_grundig, proto_nokia, proto_siemens, proto_fdc, proto_rccar, proto_jvc, proto_rc6a, proto_nikon, proto_ruwido, proto_ir60, proto_kathrein, proto_netbox, proto_nec16, proto_nec42, proto_lego, proto_thomson, proto_bose, proto_a1tvbox, proto_ortek, proto_telefunken, proto_roomba, proto_rcmm32, proto_rcmm24, proto_rcmm12, proto_speaker, proto_lgair, proto_samsung48, proto_merlin, proto_pentax, proto_fan, proto_s100, proto_acp24, proto_technics, proto_panasonic, proto_mitsu_heavy, proto_vincent, proto_samsungah, proto_irmp16, proto_gree, proto_rcii, proto_metz, proto_onkyo, proto_rf_gen24, proto_rf_x10, proto_rf_medion, proto_melinera, proto_rc6a20, proto_rc6a28 }; #endif // IRMP_PROTOCOLS_HPP ================================================ FILE: src/irmpsystem.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irmpsystem.h - system specific includes and defines * * Copyright (c) 2009-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRMPSYSTEM_H_ #define _IRMPSYSTEM_H_ #if !defined(_IRMP_H_) && !defined(_IRSND_H_) # error please include only irmp.h or irsnd.h, not irmpsystem.h #endif #if defined(ARDUINO) // AVR Arduino. Should be first, since it covers multiple platforms // to avoid the other includes and defines which are incompatible with ARDUINO #elif defined(__18CXX) // Microchip PIC C18 compiler # define PIC_C18 #elif defined(__XC8) // PIC XC8 compiler # include # define PIC_C18 #elif defined(__XC32) // XC32 or ChipKit compiler # define PIC_XC32 #elif defined(__PCM__) || defined(__PCB__) || defined(__PCH__) // CCS PIC compiler # define PIC_CCS #elif defined(STM32L1XX_MD) || defined(STM32L1XX_MDP) || defined(STM32L1XX_HD) // ARM STM32 # include # define ARM_STM32 # define ARM_STM32L1XX # define F_CPU (SysCtlClockGet()) #elif defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) \ || defined(STM32F10X_MD) || defined(STM32F10X_MD_VL) \ || defined(STM32F10X_HD) || defined(STM32F10X_HD_VL) \ || defined(STM32F10X_XL) || defined(STM32F10X_CL) // ARM STM32 # include # define ARM_STM32 # define ARM_STM32F10X # define F_CPU (SysCtlClockGet()) #elif defined(STM32F30X) // ARM STM32 # include # define ARM_STM32 # define ARM_STM32F30X # define F_CPU (SysCtlClockGet()) #elif defined(STM32F4XX) // ARM STM32 # include # define ARM_STM32 # define ARM_STM32F4XX # define F_CPU (SysCtlClockGet()) #elif defined(STM32L1) || defined(STM32F1) || defined(STM32F3) || defined(STM32F4) // ARM STM32 OPENCM3 # include # include # include # include # include # include "../config.h" # define ARM_STM32_OPENCM3 # define F_CPU rcc_ahb_frequency #elif defined(USE_HAL_DRIVER) // ARM STM32 with HAL Library # include "gpio.h" # if defined(_IRSND_H_) # include"tim.h" # endif # define ARM_STM32_HAL # define F_CPU SystemCoreClock #elif defined(__SDCC_stm8) // STM8 # define SDCC_STM8 #elif defined(TARGET_IS_BLIZZARD_RA2) // TI Stellaris (tested on Stellaris Launchpad with Code Composer Studio) # define STELLARIS_ARM_CORTEX_M4 # define F_CPU (SysCtlClockGet()) #elif defined(__xtensa__) // ESP8266 (Arduino) # include "Arduino.h" # include "ets_sys.h" # include "osapi.h" # include "gpio.h" # include "os_type.h" # include "c_types.h" # define uint_fast8_t uint8_t # define uint_fast16_t uint16_t #elif defined(TEENSYDUINO) && (defined(__MK20DX256__) || defined(__MK20DX128__)) // Teensy 3.x (tested on Teensy 3.1 in Arduino 1.6.5 / Teensyduino 1.2.5) # include # define TEENSY_ARM_CORTEX_M4 #elif defined(unix) || defined(WIN32) || defined(__APPLE__) // Unix/Linux or Windows or Apple # define UNIX_OR_WINDOWS #elif defined(__MBED__) // mbed platform // #include "mbed.h" // if mbed.h is used, source must be compiled as cpp #include "gpio_api.h" #elif defined(IRMP_CHIBIOS_HAL) // ChibiOS HAL # include "hal.h" #elif defined(PICO_RP2040) // rp2040 with the pico-sdk # include "hardware/clocks.h" # include "hardware/pwm.h" # include "pico/stdlib.h" # define F_CPU (clock_get_hz(clk_sys)) #else # define ATMEL_AVR // ATMEL AVR #endif #include #if defined(UNIX_OR_WINDOWS) // Analyze on Unix/Linux or Windows # include # include # define F_CPU 8000000L # define ANALYZE # include # ifdef _MSC_VER # define IRMP_PACKED_STRUCT # endif #endif #if defined(ARDUINO) // AVR Arduino. Should be first, since it covers multiple platforms // to avoid the other includes and defines which are incompatible with ARDUINO #elif defined(ATMEL_AVR) # include # include # include # include # include # include # define IRSND_OC2 0 // OC2 # define IRSND_OC2A 1 // OC2A # define IRSND_OC2B 2 // OC2B # define IRSND_OC0 3 // OC0 # define IRSND_OC0A 4 // OC0A # define IRSND_OC0B 5 // OC0B # define IRSND_XMEGA_OC0A 0 // OC0A # define IRSND_XMEGA_OC0B 1 // OC0B # define IRSND_XMEGA_OC0C 2 // OC0C # define IRSND_XMEGA_OC0D 3 // OC0D # define IRSND_XMEGA_OC1A 4 // OC1A # define IRSND_XMEGA_OC1B 5 // OC1B #elif defined(STELLARIS_ARM_CORTEX_M4) # include "inc/hw_ints.h" # include "inc/hw_memmap.h" # include "inc/hw_types.h" # include "inc/hw_gpio.h" # include "driverlib/fpu.h" # include "driverlib/sysctl.h" # include "driverlib/interrupt.h" # include "driverlib/gpio.h" # include "driverlib/rom.h" # include "driverlib/systick.h" # include "driverlib/pin_map.h" # include "driverlib/timer.h" # define PROGMEM # define memcpy_P memcpy # define APP_SYSTICKS_PER_SEC 32 #elif defined(ARM_STM32F10X) # include "stm32f10x_gpio.h" # include "stm32f10x_rcc.h" # include "stm32f10x_tim.h" # include "misc.h" # define PROGMEM # define memcpy_P memcpy #elif defined(SDCC_STM8) # include "stm8s.h" # define PROGMEM # define memcpy_P memcpy # define __attribute__(x) # define uint_fast8_t uint8_t # define uint_fast16_t uint16_t #elif defined(TEENSY_ARM_CORTEX_M4) # define PROGMEM # define memcpy_P memcpy #elif defined(__xtensa__) # define PROGMEM # define memcpy_P memcpy #elif defined(__MBED__) # define PROGMEM # define memcpy_P memcpy #else # if ! defined(PROGMEM) # define PROGMEM # endif # if ! defined(memcpy_P) # define memcpy_P memcpy # endif #endif #if defined(PIC_CCS) || defined(PIC_C18) typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned char uint_fast8_t; typedef unsigned short uint_fast16_t; #endif #if defined (PIC_C18) // PIC C18 or XC8 compiler # include // main PIC18 h file #ifndef __XC8 # include // timer lib # include // pwm lib #endif # define IRSND_PIC_CCP1 1 // PIC C18 RC2 = PWM1 module # define IRSND_PIC_CCP2 2 // PIC C18 RC1 = PWM2 module #endif #if !defined(TRUE) # define TRUE 1 # define FALSE 0 #endif #if defined(PIC_XC32) // XC32 or ChipKit compiler # include # include #endif #if defined(PIC_C18) # define IRMP_PACKED_STRUCT #else # if !defined(IRMP_PACKED_STRUCT) # define IRMP_PACKED_STRUCT __attribute__ ((__packed__)) # endif #endif typedef struct IRMP_PACKED_STRUCT IRMP_DATA { uint8_t protocol; // protocol, e.g. IRMP_NEC_PROTOCOL uint16_t address; // address uint16_t command; // command uint8_t flags; // flags, e.g. repetition } IRMP_DATA; #endif // _IRMPSYSTEM_H_ ================================================ FILE: src/irsnd.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irsnd.h * * Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRSND_H_ #define _IRSND_H_ #include "irmpsystem.h" #if !defined(IRSND_USE_AS_LIB) # include "irsndconfig.h" #endif #if defined(ARDUINO) # include "irsndArduinoExt.h" #elif defined (ARM_STM32) // STM32 # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRSND_PORT CONCAT(GPIO, IRSND_PORT_LETTER) # if defined (ARM_STM32L1XX) # define IRSND_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRSND_PORT_LETTER) # define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER) # elif defined (ARM_STM32F10X) # define IRSND_PORT_RCC CONCAT(RCC_APB2Periph_GPIO, IRSND_PORT_LETTER) # elif defined (ARM_STM32F30X) # define IRSND_PORT_RCC CONCAT(RCC_AHBPeriph_GPIO, IRSND_PORT_LETTER) # elif defined (ARM_STM32F4XX) # define IRSND_PORT_RCC CONCAT(RCC_AHB1Periph_GPIO, IRSND_PORT_LETTER) # define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER) # endif # define IRSND_BIT CONCAT(GPIO_Pin_, IRSND_BIT_NUMBER) # define IRSND_TIMER CONCAT(TIM, IRSND_TIMER_NUMBER) # define IRSND_TIMER_CHANNEL CONCAT(TIM_Channel_, IRSND_TIMER_CHANNEL_NUMBER) # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) # define IRSND_TIMER_RCC CONCAT(RCC_APB1Periph_TIM, IRSND_TIMER_NUMBER) # elif (IRSND_TIMER_NUMBER == 1) || ((IRSND_TIMER_NUMBER >= 8) && (IRSND_TIMER_NUMBER <= 11)) # define IRSND_TIMER_RCC CONCAT(RCC_APB2Periph_TIM, IRSND_TIMER_NUMBER) # else # error IRSND_TIMER_NUMBER not valid. # endif # if !defined(USE_STDPERIPH_DRIVER) # warning The STM32 port of IRSND uses the ST standard peripheral drivers which are not enabled in your build configuration. # endif #elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3 # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRSND_PORT CONCAT(GPIO, IRSND_PORT_LETTER) # if defined (ARM_STM32L1) # define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER) # define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER) # elif defined (STM32F1) # define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER) # elif defined (ARM_STM32F3) # define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER) # elif defined (ARM_STM32F4) # define IRSND_PORT_RCC CONCAT(RCC_GPIO, IRSND_PORT_LETTER) # define IRSND_GPIO_AF CONCAT(GPIO_AF_TIM, IRSND_TIMER_NUMBER) # endif # define IRSND_BIT CONCAT(GPIO, IRSND_BIT_NUMBER) # define IRSND_TIMER CONCAT(TIM, IRSND_TIMER_NUMBER) # define IRSND_TIMER_CHANNEL CONCAT(TIM_OC, IRSND_TIMER_CHANNEL_NUMBER) # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) # define IRSND_TIMER_RCC CONCAT(RCC_TIM, IRSND_TIMER_NUMBER) # elif (IRSND_TIMER_NUMBER == 1) || ((IRSND_TIMER_NUMBER >= 8) && (IRSND_TIMER_NUMBER <= 11)) # define IRSND_TIMER_RCC CONCAT(RCC_TIM, IRSND_TIMER_NUMBER) # else # error IRSND_TIMER_NUMBER not valid. # endif #elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 # define IRSND_BIT IRSND_BIT_NUMBER #elif defined(PIC_C18) # if defined(__12F1840) // Do not change lines below unless you have a different HW. This example is for 12F1840 // setup macro for PWM used PWM module //~ # define PWMon() TMR2=0,IRSND_PIN=1 //~ # define PWMoff() CCP1CON &=(~0b1100) //~ # define PWMon() TMR2ON=1 //~ # define PWMoff() TMR2ON=0 #if defined(IRSND_DEBUG) #define PWMon() LATA0=1 #define PWMoff() LATA0=0 #define IRSND_PIN LATA0 #else # define PWMon() TMR2=0,CCP1CON |=0b1100 # define PWMoff() CCP1CON &=(~0b1100) # define IRSND_PIN RA2 #endif #else // Do not change lines below until you have a different HW. Example is for 18F2550/18F4550 // setup macro for PWM used PWM module # if IRSND_OCx == IRSND_PIC_CCP2 # define PWMon() TMR2=0,CCP2CON |=0b1100 # define PWMoff() CCP2CON &=(~0b1100) # define IRSND_PIN TRISCbits.TRISC1 // RC1 = PWM2 # define SetDCPWM(x) SetDCPWM2(x) # define ClosePWM ClosePWM2 # define OpenPWM(x) OpenPWM2(x) # endif # if IRSND_OCx == IRSND_PIC_CCP1 # define PWMon() TMR2=0,CCP1CON |=0b1100 # define PWMoff() CCP1CON &=(~0b1100) # define IRSND_PIN TRISCbits.TRISC2 // RC2 = PWM1 # define SetDCPWM(x) SetDCPWM1(x) # define ClosePWM ClosePWM1 # define OpenPWM(x) OpenPWM1(x) # endif # endif # endif // PIC_C18 #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, SIEMENS protocol disabled (should be at least 15000) # undef IRSND_SUPPORT_SIEMENS_PROTOCOL # define IRSND_SUPPORT_SIEMENS_PROTOCOL 0 #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, A1TVBOX protocol disabled (should be at least 15000) # undef IRSND_SUPPORT_A1TVBOX_PROTOCOL # define IRSND_SUPPORT_A1TVBOX_PROTOCOL 0 #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, RECS80 protocol disabled (should be at least 15000) # undef IRSND_SUPPORT_RECS80_PROTOCOL # define IRSND_SUPPORT_RECS80_PROTOCOL 0 #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 && F_INTERRUPTS < 15000 # warning F_INTERRUPTS too low, RECS80EXT protocol disabled (should be at least 15000) # undef IRSND_SUPPORT_RECS80EXT_PROTOCOL # define IRSND_SUPPORT_RECS80EXT_PROTOCOL 0 #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 && F_INTERRUPTS < 19000 # warning F_INTERRUPTS too low, LEGO protocol disabled (should be at least 19000) # undef IRSND_SUPPORT_LEGO_PROTOCOL # define IRSND_SUPPORT_LEGO_PROTOCOL 0 #endif #include "irmpprotocols.h" #define IRSND_NO_REPETITIONS 0 // no repetitions #define IRSND_MAX_REPETITIONS 14 // max # of repetitions #define IRSND_ENDLESS_REPETITION 15 // endless repetitions #define IRSND_REPETITION_MASK 0x0F // lower nibble of flags #define IRSND_RAW_REPETITION_FRAME 0x10 // send one or more raw repetition frames, yet only used for NEC #define IRSND_SUPPRESS_TRAILER 0x20 // suppress trailer #ifdef __cplusplus extern "C" { #endif extern void irsnd_init (void); # ifdef __cplusplus extern bool irsnd_is_busy (void); extern bool irsnd_send_data (IRMP_DATA *, uint8_t); extern bool irsnd_ISR (void); #else extern uint8_t irsnd_is_busy (void); extern uint8_t irsnd_send_data (IRMP_DATA *, uint8_t); extern uint8_t irsnd_ISR (void); #endif extern void irsnd_stop (void); #if IRSND_USE_CALLBACK == 1 extern void irsnd_set_callback_ptr (void (*cb)(uint8_t)); #endif // IRSND_USE_CALLBACK == 1 #ifdef __cplusplus } #endif #endif /* _IRSND_H_ */ ================================================ FILE: src/irsnd.hpp ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * @file irsnd.c * * Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de * * Supported AVR mikrocontrollers: * * ATtiny87, ATtiny167 * ATtiny45, ATtiny85 * ATtiny44 ATtiny84 * ATtiny2313 ATtiny4313 * ATmega8, ATmega16, ATmega32 * ATmega162 * ATmega164, ATmega324, ATmega644, ATmega644P, ATmega1284, ATmega1284P * ATmega88, ATmega88P, ATmega168, ATmega168P, ATmega328P * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #include "irsnd.h" #if !defined(F_CPU) # error F_CPU unkown #endif #define IRMP_NEC_REPETITION_PROTOCOL 0xFF // pseudo protocol: NEC repetition frame /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ATtiny pin definition of OC0A / OC0B * ATmega pin definition of OC2 / OC2A / OC2B / OC0 / OC0A / OC0B *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined (__AVR_ATtiny44__) || defined (__AVR_ATtiny84__) // ATtiny44/84 uses OC0A = PB2 or OC0B = PA7 # if IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 2 # elif IRSND_OCx == IRSND_OC0B // OC0B # define IRSND_PORT_LETTER A # define IRSND_BIT_NUMBER 7 # else # error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATtiny45__) || defined (__AVR_ATtiny85__) // ATtiny45/85 uses OC0A = PB0 or OC0B = PB1 # if IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 0 # elif IRSND_OCx == IRSND_OC0B // OC0B # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 1 # else # error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATtiny2313__) || defined (__AVR_ATtiny4313__) // ATtiny2313/4313 uses OC0A = PB2 or OC0B = PD5 # if IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 2 # elif IRSND_OCx == IRSND_OC0B // OC0B # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 5 # else # error Wrong value for IRSND_OCx, choose IRSND_OC0A or IRSND_OC0B in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATtiny87__) || defined (__AVR_ATtiny167__) // ATtiny87/167 uses OC0A = PA2 # if IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER A # define IRSND_BIT_NUMBER 2 # else # error Wrong value for IRSND_OCx, choose IRSND_OC0A in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega8__) // ATmega8 uses only OC2 = PB3 # if IRSND_OCx == IRSND_OC2 // OC2 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 3 # else # error Wrong value for IRSND_OCx, choose IRSND_OC2 in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega16__) || defined (__AVR_ATmega32__) // ATmega16|32 uses OC0 = PB3 or OC2 = PD7 # if IRSND_OCx == IRSND_OC2 // OC2 # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 7 # elif IRSND_OCx == IRSND_OC0 // OC0 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 3 # else # error Wrong value for IRSND_OCx, choose IRSND_OC2 or IRSND_OC0 in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega162__) // ATmega162 uses OC2 = PB1 or OC0 = PB0 # if IRSND_OCx == IRSND_OC2 // OC2 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 1 # elif IRSND_OCx == IRSND_OC0 // OC0 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 0 # else # error Wrong value for IRSND_OCx, choose IRSND_OC2 or IRSND_OC0 in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega164__) \ || defined (__AVR_ATmega324__) \ || defined (__AVR_ATmega644__) \ || defined (__AVR_ATmega644P__) \ || defined (__AVR_ATmega1284__) \ || defined (__AVR_ATmega1284P__) // ATmega164|324|644|644P|1284 uses OC2A = PD7 or OC2B = PD6 or OC0A = PB3 or OC0B = PB4 # if IRSND_OCx == IRSND_OC2A // OC2A # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 7 # elif IRSND_OCx == IRSND_OC2B // OC2B # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 6 # elif IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 3 # elif IRSND_OCx == IRSND_OC0B // OC0B # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 4 # else # error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega48__) \ || defined (__AVR_ATmega88__) \ || defined (__AVR_ATmega88P__) \ || defined (__AVR_ATmega168__) \ || defined (__AVR_ATmega168P__) \ || defined (__AVR_ATmega328P__) // ATmega48|88|168|168|328 uses OC2A = PB3 or OC2B = PD3 or OC0A = PD6 or OC0B = PD5 # if IRSND_OCx == IRSND_OC2A // OC2A # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 3 # elif IRSND_OCx == IRSND_OC2B // OC2B # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 3 # elif IRSND_OCx == IRSND_OC0A // OC0A # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 6 # elif IRSND_OCx == IRSND_OC0B // OC0B # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 5 # else # error Wrong value for IRSND_OCx, choose IRSND_OC2A, IRSND_OC2B, IRSND_OC0A, or IRSND_OC0B in irsndconfig.h # endif // IRSND_OCx #elif defined (__AVR_ATmega8515__) // ATmega8515 uses OC0 = PB0 or OC1A = PD5 or OC1B = PE2 # if IRSND_OCx == IRSND_OC0 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 0 # elif IRSND_OCx == IRSND_OC1A # define IRSND_PORT_LETTER D # define IRSND_BIT_NUMBER 5 # elif IRSND_OCx == IRSND_OC1B # define IRSND_PORT_LETTER E # define IRSND_BIT_NUMBER 2 # endif // IRSND_OCx #elif defined (__AVR_XMEGA__) // ATxmega # if IRSND_OCx == IRSND_XMEGA_OC0A # define IRSND_BIT_NUMBER 0 # elif IRSND_OCx == IRSND_XMEGA_OC0B # define IRSND_BIT_NUMBER 1 # elif IRSND_OCx == IRSND_XMEGA_OC0C # define IRSND_BIT_NUMBER 2 # elif IRSND_OCx == IRSND_XMEGA_OC0D # define IRSND_BIT_NUMBER 3 # elif IRSND_OCx == IRSND_XMEGA_OC1A # define IRSND_BIT_NUMBER 4 # elif IRSND_OCx == IRSND_XMEGA_OC1B # define IRSND_BIT_NUMBER 5 # else # error Wrong value for IRSND_OCx, choose IRSND_XMEGA_OC0A, IRSND_XMEGA_OC0B, IRSND_XMEGA_OC0C, IRSND_XMEGA_OC0D, IRSND_XMEGA_OC1A, or IRSND_XMEGA_OC1B in irsndconfig.h # endif // IRSND_OCx #elif defined (PIC_C18) // Microchip C18 compiler //Nothing here to do here -> See irsndconfig.h #elif defined (ARM_STM32) // STM32 //Nothing here to do here -> See irsndconfig.h #elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3 //Nothing here to do here -> See irsndconfig.h #elif defined (ARM_STM32_HAL) // STM32 with Hal Library //Nothing here to do here -> See irsndconfig.h #elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 uint slice_num; #elif defined (__xtensa__) // ESP8266 //Nothing here to do here -> See irsndconfig.h /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Macro digitalPinHasPWM bothers PIC_C18 compiler, but why? * * #elif defined (TEENSY_ARM_CORTEX_M4) // Teensy3 * # if !digitalPinHasPWM(IRSND_PIN) * # error need pin with PWM output. * # endif *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined(ARDUINO) // specified here to avoid else case #else # if !defined (unix) && !defined (WIN32) # error mikrocontroller not defined, please fill in definitions here. # endif // unix, WIN32 #endif // __AVR... #if defined(__AVR_XMEGA__) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRSND_PORT IRSND_PORT_PRE.OUT # define IRSND_DDR IRSND_PORT_PRE.DIR # define IRSND_PIN IRSND_PORT_PRE.IN # define IRSND_BIT IRSND_BIT_NUMBER #elif defined(ATMEL_AVR) # define _CONCAT(a,b) a##b # define CONCAT(a,b) _CONCAT(a,b) # define IRSND_PORT CONCAT(PORT, IRSND_PORT_LETTER) # define IRSND_DDR CONCAT(DDR, IRSND_PORT_LETTER) # define IRSND_BIT IRSND_BIT_NUMBER #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 typedef uint16_t IRSND_PAUSE_LEN; #else typedef uint8_t IRSND_PAUSE_LEN; #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * IR timings *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRSND_SIRCS_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PULSE_TIME + 0.5) #define IRSND_SIRCS_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_START_BIT_PAUSE_TIME + 0.5) #define IRSND_SIRCS_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_1_PULSE_TIME + 0.5) #define IRSND_SIRCS_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_0_PULSE_TIME + 0.5) #define IRSND_SIRCS_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIRCS_PAUSE_TIME + 0.5) #define IRSND_SIRCS_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SIRCS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIRCS_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_NEC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PULSE_TIME + 0.5) #define IRSND_NEC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_START_BIT_PAUSE_TIME + 0.5) #define IRSND_NEC_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_NEC_PULSE_LEN (uint8_t)(F_INTERRUPTS * NEC_PULSE_TIME + 0.5) #define IRSND_NEC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_1_PAUSE_TIME + 0.5) #define IRSND_NEC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NEC_0_PAUSE_TIME + 0.5) #define IRSND_NEC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NEC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_MELINERA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_START_BIT_PULSE_TIME + 0.5) #define IRSND_MELINERA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_START_BIT_PAUSE_TIME + 0.5) #define IRSND_MELINERA_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_MELINERA_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_1_PULSE_TIME + 0.5) #define IRSND_MELINERA_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_0_PULSE_TIME + 0.5) #define IRSND_MELINERA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_1_PAUSE_TIME + 0.5) #define IRSND_MELINERA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MELINERA_0_PAUSE_TIME + 0.5) #define IRSND_MELINERA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MELINERA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SAMSUNG_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PULSE_TIME + 0.5) #define IRSND_SAMSUNG_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_START_BIT_PAUSE_TIME + 0.5) #define IRSND_SAMSUNG_PULSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_PULSE_TIME + 0.5) #define IRSND_SAMSUNG_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_1_PAUSE_TIME + 0.5) #define IRSND_SAMSUNG_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SAMSUNG_0_PAUSE_TIME + 0.5) #define IRSND_SAMSUNG_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SAMSUNG32_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SAMSUNG32_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG32_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SAMSUNG48_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG48_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SAMSUNG48_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SAMSUNG48_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_MATSUSHITA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PULSE_TIME + 0.5) #define IRSND_MATSUSHITA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_START_BIT_PAUSE_TIME + 0.5) #define IRSND_MATSUSHITA_PULSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_PULSE_TIME + 0.5) #define IRSND_MATSUSHITA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_1_PAUSE_TIME + 0.5) #define IRSND_MATSUSHITA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MATSUSHITA_0_PAUSE_TIME + 0.5) #define IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MATSUSHITA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_KASEIKYO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PULSE_TIME + 0.5) #define IRSND_KASEIKYO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_START_BIT_PAUSE_TIME + 0.5) #define IRSND_KASEIKYO_PULSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_PULSE_TIME + 0.5) #define IRSND_KASEIKYO_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_1_PAUSE_TIME + 0.5) #define IRSND_KASEIKYO_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * KASEIKYO_0_PAUSE_TIME + 0.5) #define IRSND_KASEIKYO_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * KASEIKYO_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_KASEIKYO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * KASEIKYO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_PANASONIC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PULSE_TIME + 0.5) #define IRSND_PANASONIC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_START_BIT_PAUSE_TIME + 0.5) #define IRSND_PANASONIC_PULSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_PULSE_TIME + 0.5) #define IRSND_PANASONIC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_1_PAUSE_TIME + 0.5) #define IRSND_PANASONIC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PANASONIC_0_PAUSE_TIME + 0.5) #define IRSND_PANASONIC_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PANASONIC_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_PANASONIC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PANASONIC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_MITSU_HEAVY_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PULSE_TIME + 0.5) #define IRSND_MITSU_HEAVY_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_START_BIT_PAUSE_TIME + 0.5) #define IRSND_MITSU_HEAVY_PULSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_PULSE_TIME + 0.5) #define IRSND_MITSU_HEAVY_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_1_PAUSE_TIME + 0.5) #define IRSND_MITSU_HEAVY_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * MITSU_HEAVY_0_PAUSE_TIME + 0.5) #define IRSND_MITSU_HEAVY_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * MITSU_HEAVY_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RECS80_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PULSE_TIME + 0.5) #define IRSND_RECS80_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_START_BIT_PAUSE_TIME + 0.5) #define IRSND_RECS80_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_PULSE_TIME + 0.5) #define IRSND_RECS80_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_1_PAUSE_TIME + 0.5) #define IRSND_RECS80_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80_0_PAUSE_TIME + 0.5) #define IRSND_RECS80_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RC5_START_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5) #define IRSND_RC5_BIT_LEN (uint8_t)(F_INTERRUPTS * RC5_BIT_TIME + 0.5) #define IRSND_RC5_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC5_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RC6_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PULSE_TIME + 0.5) #define IRSND_RC6_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RC6_START_BIT_PAUSE_TIME + 0.5) #define IRSND_RC6_BIT_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_TIME + 0.5) #define IRSND_RC6_BIT_2_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_2_TIME + 0.5) #define IRSND_RC6_BIT_3_LEN (uint8_t)(F_INTERRUPTS * RC6_BIT_3_TIME + 0.5) #define IRSND_RC6_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RC6_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_DENON_PULSE_LEN (uint8_t)(F_INTERRUPTS * DENON_PULSE_TIME + 0.5) #define IRSND_DENON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_1_PAUSE_TIME + 0.5) #define IRSND_DENON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * DENON_0_PAUSE_TIME + 0.5) #define IRSND_DENON_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_DENON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * DENON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_THOMSON_PULSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_PULSE_TIME + 0.5) #define IRSND_THOMSON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_1_PAUSE_TIME + 0.5) #define IRSND_THOMSON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * THOMSON_0_PAUSE_TIME + 0.5) #define IRSND_THOMSON_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * THOMSON_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_THOMSON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * THOMSON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RECS80EXT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PULSE_TIME + 0.5) #define IRSND_RECS80EXT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_RECS80EXT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_PULSE_TIME + 0.5) #define IRSND_RECS80EXT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_1_PAUSE_TIME + 0.5) #define IRSND_RECS80EXT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RECS80EXT_0_PAUSE_TIME + 0.5) #define IRSND_RECS80EXT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RECS80EXT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_TELEFUNKEN_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PULSE_TIME + 0.5) #define IRSND_TELEFUNKEN_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_START_BIT_PAUSE_TIME + 0.5) #define IRSND_TELEFUNKEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_PULSE_TIME + 0.5) #define IRSND_TELEFUNKEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_1_PAUSE_TIME + 0.5) #define IRSND_TELEFUNKEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * TELEFUNKEN_0_PAUSE_TIME + 0.5) #define IRSND_TELEFUNKEN_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * TELEFUNKEN_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * TELEFUNKEN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_BOSE_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PULSE_TIME + 0.5) #define IRSND_BOSE_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_START_BIT_PAUSE_TIME + 0.5) #define IRSND_BOSE_PULSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_PULSE_TIME + 0.5) #define IRSND_BOSE_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_1_PAUSE_TIME + 0.5) #define IRSND_BOSE_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BOSE_0_PAUSE_TIME + 0.5) #define IRSND_BOSE_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BOSE_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_BOSE_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BOSE_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_NUBERT_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PULSE_TIME + 0.5) #define IRSND_NUBERT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_NUBERT_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PULSE_TIME + 0.5) #define IRSND_NUBERT_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_1_PAUSE_TIME + 0.5) #define IRSND_NUBERT_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PULSE_TIME + 0.5) #define IRSND_NUBERT_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NUBERT_0_PAUSE_TIME + 0.5) #define IRSND_NUBERT_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_NUBERT_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NUBERT_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_FAN_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_START_BIT_PULSE_TIME + 0.5) #define IRSND_FAN_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_START_BIT_PAUSE_TIME + 0.5) #define IRSND_FAN_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_1_PULSE_TIME + 0.5) #define IRSND_FAN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_1_PAUSE_TIME + 0.5) #define IRSND_FAN_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * FAN_0_PULSE_TIME + 0.5) #define IRSND_FAN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FAN_0_PAUSE_TIME + 0.5) #define IRSND_FAN_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FAN_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_FAN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FAN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SPEAKER_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PULSE_TIME + 0.5) #define IRSND_SPEAKER_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_START_BIT_PAUSE_TIME + 0.5) #define IRSND_SPEAKER_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_1_PULSE_TIME + 0.5) #define IRSND_SPEAKER_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_1_PAUSE_TIME + 0.5) #define IRSND_SPEAKER_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_0_PULSE_TIME + 0.5) #define IRSND_SPEAKER_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SPEAKER_0_PAUSE_TIME + 0.5) #define IRSND_SPEAKER_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SPEAKER_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SPEAKER_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SPEAKER_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_BANG_OLUFSEN_START_BIT1_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PULSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_START_BIT1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT1_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PULSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT2_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_START_BIT3_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PULSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_START_BIT3_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_START_BIT3_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_PULSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_PULSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_1_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_0_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_R_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_R_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * BANG_OLUFSEN_TRAILER_BIT_PAUSE_TIME + 0.5) #define IRSND_BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * BANG_OLUFSEN_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_PRE_PAUSE_TIME + 0.5) #define IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN (uint8_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_BIT_TIME + 0.5) #define IRSND_GRUNDIG_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_NOKIA_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NOKIA_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_IR60_AUTO_REPETITION_PAUSE_LEN (uint16_t)(F_INTERRUPTS * IR60_AUTO_REPETITION_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_SIEMENS_START_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME + 0.5) #define IRSND_SIEMENS_BIT_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME + 0.5) #define IRSND_SIEMENS_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RUWIDO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PULSE_TIME + 0.5) #define IRSND_RUWIDO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_START_BIT_PAUSE_TIME + 0.5) #define IRSND_RUWIDO_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PULSE_TIME + 0.5) #define IRSND_RUWIDO_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_BIT_PAUSE_TIME + 0.5) #define IRSND_RUWIDO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * SIEMENS_OR_RUWIDO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_FDC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * FDC_START_BIT_PULSE_TIME + 0.5) #define IRSND_FDC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_START_BIT_PAUSE_TIME + 0.5) #define IRSND_FDC_PULSE_LEN (uint8_t)(F_INTERRUPTS * FDC_PULSE_TIME + 0.5) #define IRSND_FDC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_1_PAUSE_TIME + 0.5) #define IRSND_FDC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * FDC_0_PAUSE_TIME + 0.5) #define IRSND_FDC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * FDC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_RCCAR_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PULSE_TIME + 0.5) #define IRSND_RCCAR_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_START_BIT_PAUSE_TIME + 0.5) #define IRSND_RCCAR_PULSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_PULSE_TIME + 0.5) #define IRSND_RCCAR_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_1_PAUSE_TIME + 0.5) #define IRSND_RCCAR_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * RCCAR_0_PAUSE_TIME + 0.5) #define IRSND_RCCAR_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * RCCAR_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_JVC_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * JVC_START_BIT_PULSE_TIME + 0.5) #define IRSND_JVC_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_START_BIT_PAUSE_TIME + 0.5) #define IRSND_JVC_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_JVC_PULSE_LEN (uint8_t)(F_INTERRUPTS * JVC_PULSE_TIME + 0.5) #define IRSND_JVC_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_1_PAUSE_TIME + 0.5) #define IRSND_JVC_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * JVC_0_PAUSE_TIME + 0.5) #define IRSND_JVC_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * JVC_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_NIKON_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_START_BIT_PULSE_TIME + 0.5) #define IRSND_NIKON_START_BIT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NIKON_START_BIT_PAUSE_TIME + 0.5) #define IRSND_NIKON_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_NIKON_PULSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_PULSE_TIME + 0.5) #define IRSND_NIKON_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_1_PAUSE_TIME + 0.5) #define IRSND_NIKON_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * NIKON_0_PAUSE_TIME + 0.5) #define IRSND_NIKON_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * NIKON_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_LEGO_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PULSE_TIME + 0.5) #define IRSND_LEGO_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_START_BIT_PAUSE_TIME + 0.5) #define IRSND_LEGO_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_LEGO_PULSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_PULSE_TIME + 0.5) #define IRSND_LEGO_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_1_PAUSE_TIME + 0.5) #define IRSND_LEGO_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * LEGO_0_PAUSE_TIME + 0.5) #define IRSND_LEGO_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * LEGO_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_IRMP16_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_START_BIT_PULSE_TIME + 0.5) #define IRSND_IRMP16_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_START_BIT_PAUSE_TIME + 0.5) #define IRSND_IRMP16_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_IRMP16_PULSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_PULSE_TIME + 0.5) #define IRSND_IRMP16_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_1_PAUSE_TIME + 0.5) #define IRSND_IRMP16_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * IRMP16_0_PAUSE_TIME + 0.5) #define IRSND_IRMP16_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * IRMP16_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_A1TVBOX_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PULSE_TIME + 0.5) #define IRSND_A1TVBOX_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_START_BIT_PAUSE_TIME + 0.5) #define IRSND_A1TVBOX_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_BIT_PULSE_TIME + 0.5) #define IRSND_A1TVBOX_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * A1TVBOX_BIT_PAUSE_TIME + 0.5) #define IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * A1TVBOX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * A1TVBOX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_ROOMBA_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PULSE_TIME + 0.5) #define IRSND_ROOMBA_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_START_BIT_PAUSE_TIME + 0.5) #define IRSND_ROOMBA_1_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_1_PULSE_TIME + 0.5) #define IRSND_ROOMBA_0_PULSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_0_PULSE_TIME + 0.5) #define IRSND_ROOMBA_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_1_PAUSE_TIME + 0.5) #define IRSND_ROOMBA_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ROOMBA_0_PAUSE_TIME + 0.5) #define IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * ROOMBA_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_PENTAX_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_START_BIT_PULSE_TIME + 0.5) #define IRSND_PENTAX_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_START_BIT_PAUSE_TIME + 0.5) #define IRSND_PENTAX_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_PENTAX_PULSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_PULSE_TIME + 0.5) #define IRSND_PENTAX_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_1_PAUSE_TIME + 0.5) #define IRSND_PENTAX_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * PENTAX_0_PAUSE_TIME + 0.5) #define IRSND_PENTAX_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * PENTAX_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #define IRSND_ACP24_START_BIT_PULSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_START_BIT_PULSE_TIME + 0.5) #define IRSND_ACP24_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_START_BIT_PAUSE_TIME + 0.5) #define IRSND_ACP24_REPEAT_START_BIT_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_REPEAT_START_BIT_PAUSE_TIME + 0.5) #define IRSND_ACP24_PULSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_PULSE_TIME + 0.5) #define IRSND_ACP24_1_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_1_PAUSE_TIME + 0.5) #define IRSND_ACP24_0_PAUSE_LEN (uint8_t)(F_INTERRUPTS * ACP24_0_PAUSE_TIME + 0.5) #define IRSND_ACP24_FRAME_REPEAT_PAUSE_LEN (uint16_t)(F_INTERRUPTS * ACP24_FRAME_REPEAT_PAUSE_TIME + 0.5) // use uint16_t! #if defined(PIC_C18) // PIC C18 # define IRSND_FREQ_TYPE uint8_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / 2 / Pre_Scaler / PIC_Scaler) - 1) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / 2 / Pre_Scaler / PIC_Scaler) - 1) #elif defined (ARM_STM32) // STM32 # define IRSND_FREQ_TYPE uint32_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3 # define IRSND_FREQ_TYPE uint32_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #elif defined (ARM_STM32_HAL) // STM32 with Hal Library # define IRSND_FREQ_TYPE uint32_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 # define IRSND_FREQ_TYPE uint32_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY # define IRSND_FREQ_TYPE float # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #elif defined (__xtensa__) // ESP8266 # define IRSND_FREQ_TYPE float # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) (30000) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) (32000) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) (36000) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) (38000) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) (40000) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) (56000) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) (455000) #else // AVR # if F_CPU >= 16000000L # define AVR_PRESCALER 8 # else # define AVR_PRESCALER 1 # endif # define IRSND_FREQ_TYPE uint8_t # define IRSND_FREQ_30_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 30000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_32_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 32000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_36_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 36000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_38_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 38000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_40_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 40000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_56_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 56000 / AVR_PRESCALER / 2) - 1) # define IRSND_FREQ_455_KHZ (IRSND_FREQ_TYPE) ((F_CPU / 455000 / AVR_PRESCALER / 2) - 1) #endif // @formatter:off // Used for Arduino by IRTimer.hpp volatile uint8_t irsnd_busy = 0; volatile uint8_t irsnd_is_on = FALSE; static volatile uint8_t irsnd_protocol = 0; static volatile uint8_t irsnd_buffer[11] = { 0 }; static volatile uint8_t irsnd_repeat = 0; static volatile uint8_t irsnd_suppress_trailer = 0; // @formatter:on #if defined(ARDUINO) #include "irsndArduinoExt.hpp" // must be after the declarations of irsnd_busy etc. #else #if IRSND_USE_CALLBACK == 1 static void (*irsnd_callback_ptr) (uint8_t); #endif // IRSND_USE_CALLBACK == 1 /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Switch PWM on *--------------------------------------------------------------------------------------------------------------------------------------------------- */ static void irsnd_on (void) { if (! irsnd_is_on) { #if !defined(ANALYZE) # if defined(PIC_C18) // PIC C18 PWMon(); // IRSND_PIN = 0; // output mode -> enable PWM outout pin (0=PWM on, 1=PWM off) # elif defined (ARM_STM32) // STM32 IRSND_TIMER->EGR = TIM_PSCReloadMode_Immediate; // Generate an update event to reload the Prescaler and the Repetition counter values immediately TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Enable); // enable OC-output (is being disabled in TIM_SelectOCxM()) TIM_Cmd(IRSND_TIMER, ENABLE); // enable counter # elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3 TIM_EGR(IRSND_TIMER) = TIM_EGR_UG; // Generate an update event to reload the Prescaler and the Repetition counter values immediately timer_enable_oc_output(IRSND_TIMER, IRSND_TIMER_CHANNEL); // enable OC-output timer_enable_counter(IRSND_TIMER); // enable counter # elif defined (ARM_STM32_HAL) // STM32 with Hal Library IRSND_TIMER->EGR = TIM_EGR_UG; // Generate an update event to reload the Prescaler and the Repetition counter values immediately HAL_TIM_PWM_Start(&IRSND_TIMER_HANDLER, IRSND_TIMER_CHANNEL_NUMBER); # elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 pwm_set_counter(slice_num, 0); // reset counter pwm_set_enabled(slice_num, true); // enable counter gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_NORMAL); # elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY analogWrite(IRSND_PIN, 33 * 255 / 100); // pwm 33% # elif defined (__xtensa__) // ESP8266 (Arduino) analogWrite(IRSND_PIN, 33 * 1023 / 100); // pwm 33% # elif defined (__AVR_XMEGA__) # if (IRSND_OCx == IRSND_XMEGA_OC0A) // use OC0A XMEGA_Timer.CTRLB |= (1< disbale PWM output pin (0=PWM on, 1=PWM off) # elif defined (ARM_STM32) // STM32 TIM_CCxCmd(IRSND_TIMER, IRSND_TIMER_CHANNEL, TIM_CCx_Disable); // disable OC-output TIM_Cmd(IRSND_TIMER, DISABLE); // disable counter # elif defined (ARM_STM32_OPENCM3) // STM32_OPENCM3 timer_disable_oc_output(IRSND_TIMER, IRSND_TIMER_CHANNEL); // disable OC-output timer_disable_counter(IRSND_TIMER); // disable counter # elif defined (ARM_STM32_HAL) // STM32 HAL_TIM_PWM_Stop(&IRSND_TIMER_HANDLER, IRSND_TIMER_CHANNEL_NUMBER); # elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 pwm_set_enabled(slice_num, false); // disable counter gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_LOW); // set IRSND_BIT to low # elif defined (TEENSY_ARM_CORTEX_M4) // TEENSY analogWrite(IRSND_PIN, 0); // pwm off, LOW level # elif defined (__xtensa__) // ESP8266 analogWrite(IRSND_PIN, 0); // pwm off, LOW level # elif defined (__AVR_XMEGA__) # if (IRSND_OCx == IRSND_XMEGA_OC0A) // use OC0A XMEGA_Timer.CTRLB &= ~(1< #endif static void irsnd_set_freq (IRSND_FREQ_TYPE freq) { #if !defined(ANALYZE) # if defined(PIC_C18) // PIC C18 or XC8 # if defined(__12F1840) // XC8 TRISA2=0; PR2=freq; CCP1M0=1; CCP1M1=1; CCP1M2=1; CCP1M3=1; DC1B0=1; DC1B1=0; CCPR1L = 0b01101001; TMR2IF = 0; TMR2ON=1; CCP1CON &=(~0b0011); // p 197 "active high" # else // PIC C18 OpenPWM(freq); SetDCPWM( (uint16_t) (freq * 2) + 1); // freq*2 = Duty cycles 50% # endif PWMoff(); # elif defined (ARM_STM32) // STM32 static uint32_t TimeBaseFreq = 0; if (TimeBaseFreq == 0) { RCC_ClocksTypeDef RCC_ClocksStructure; /* Get system clocks and store timer clock in variable */ RCC_GetClocksFreq(&RCC_ClocksStructure); # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) if (RCC_ClocksStructure.PCLK1_Frequency == RCC_ClocksStructure.HCLK_Frequency) { TimeBaseFreq = RCC_ClocksStructure.PCLK1_Frequency; } else { TimeBaseFreq = RCC_ClocksStructure.PCLK1_Frequency * 2; } # else if (RCC_ClocksStructure.PCLK2_Frequency == RCC_ClocksStructure.HCLK_Frequency) { TimeBaseFreq = RCC_ClocksStructure.PCLK2_Frequency; } else { TimeBaseFreq = RCC_ClocksStructure.PCLK2_Frequency * 2; } # endif } freq = TimeBaseFreq/freq; /* Set frequency */ TIM_SetAutoreload(IRSND_TIMER, freq - 1); /* Set duty cycle */ TIM_SetCompare1(IRSND_TIMER, freq / 2); # elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3 static uint32_t TimeBaseFreq = 0; if (TimeBaseFreq == 0) { # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) if (rcc_apb1_frequency == rcc_ahb_frequency) { TimeBaseFreq = rcc_apb1_frequency; } else { TimeBaseFreq = rcc_apb1_frequency * 2; } # else if (rcc_apb2_frequency == rcc_ahb_frequency) { TimeBaseFreq = rcc_apb2_frequency; } else { TimeBaseFreq = rcc_apb2_frequency * 2; } # endif } freq = TimeBaseFreq/freq; /* Set frequency */ timer_set_period(IRSND_TIMER, freq - 1); /* Set duty cycle */ timer_set_oc_value(IRSND_TIMER, TIM_OC1, freq / 2); # elif defined (ARM_STM32_HAL) // STM32 with Hal Library TIM_MasterConfigTypeDef sMasterConfig; TIM_OC_InitTypeDef sConfigOC; uint32_t uwPrescalerValue = (uint32_t) ((IRSND_TIMER_SPEED_APBX) / (freq*10)) - 1; //1kHz //IRSND_TIMER_HANDLER.Instance = TIM2; IRSND_TIMER_HANDLER.Init.Prescaler = uwPrescalerValue; IRSND_TIMER_HANDLER.Init.CounterMode = TIM_COUNTERMODE_UP; IRSND_TIMER_HANDLER.Init.Period = 10 -1; IRSND_TIMER_HANDLER.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; IRSND_TIMER_HANDLER.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_PWM_Init(&IRSND_TIMER_HANDLER) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&IRSND_TIMER_HANDLER, &sMasterConfig) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = IRSND_TIMER_HANDLER.Init.Period / 2; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; if (HAL_TIM_PWM_ConfigChannel(&IRSND_TIMER_HANDLER, &sConfigOC, IRSND_TIMER_CHANNEL_NUMBER ) != HAL_OK) { _Error_Handler(__FILE__, __LINE__); } # elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 static uint32_t TimeBaseFreq = 0; if (TimeBaseFreq == 0) { TimeBaseFreq = F_CPU; } freq = TimeBaseFreq/freq; /* Set frequency */ pwm_set_wrap(slice_num, freq - 1); /* Set duty cycle */ pwm_set_gpio_level(IRSND_BIT, freq / 2); # elif defined (TEENSY_ARM_CORTEX_M4) analogWriteResolution(8); // 8 bit analogWriteFrequency(IRSND_PIN, freq); analogWrite(IRSND_PIN, 0); // pwm off, LOW level #elif defined (__xtensa__) // analogWriteRange(255); analogWriteFreq(freq); analogWrite(IRSND_PIN, 0); // pwm off, LOW level # elif defined (__AVR_XMEGA__) XMEGA_Timer.CCA = freq; # else // AVR # if IRSND_OCx == IRSND_OC2 OCR2 = freq; // use register OCR2 for OC2 # elif IRSND_OCx == IRSND_OC2A // use OC2A OCR2A = freq; // use register OCR2A for OC2A and OC2B! # elif IRSND_OCx == IRSND_OC2B // use OC2B OCR2A = freq; // use register OCR2A for OC2A and OC2B! # elif IRSND_OCx == IRSND_OC0 // use OC0 OCR0 = freq; // use register OCR2 for OC2 # elif IRSND_OCx == IRSND_OC0A // use OC0A OCR0A = freq; // use register OCR0A for OC0A and OC0B! # elif IRSND_OCx == IRSND_OC0B // use OC0B OCR0A = freq; // use register OCR0A for OC0A and OC0B! # else # error wrong value of IRSND_OCx # endif # endif //PIC_C18 #endif // ANALYZE } /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Initialize the PWM * @details Configures 0CR0A, 0CR0B and 0CR2B as PWM channels *--------------------------------------------------------------------------------------------------------------------------------------------------- */ void irsnd_init (void) { #if !defined(ANALYZE) # if defined(PIC_C18) // PIC C18 or XC8 compiler # if ! defined(__12F1840) // only C18: OpenTimer; # endif irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency IRSND_PIN = 0; // set IO to outout PWMoff(); # elif defined (ARM_STM32) // STM32 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; /* GPIOx clock enable */ # if defined (ARM_STM32L1XX) RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE); # elif defined (ARM_STM32F10X) RCC_APB2PeriphClockCmd(IRSND_PORT_RCC, ENABLE); // RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); // only in case of remapping, not necessary for default port-timer mapping # elif defined (ARM_STM32F30X) RCC_AHBPeriphClockCmd(IRSND_PORT_RCC, ENABLE); # elif defined (ARM_STM32F4XX) RCC_AHB1PeriphClockCmd(IRSND_PORT_RCC, ENABLE); # endif /* GPIO Configuration */ GPIO_InitStructure.GPIO_Pin = IRSND_BIT; # if defined (ARM_STM32L1XX) || defined (ARM_STM32F4XX) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(IRSND_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(IRSND_PORT, (uint8_t)IRSND_BIT_NUMBER, IRSND_GPIO_AF); # elif defined (ARM_STM32F10X) GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(IRSND_PORT, &GPIO_InitStructure); // GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], ENABLE); // only in case of remapping, not necessary for default port-timer mapping # elif defined (ARM_STM32F30X) GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(IRSND_PORT, &GPIO_InitStructure); // GPIO_PinRemapConfig(GPIO_*Remap*_TIM[IRSND_TIMER_NUMBER], ENABLE); // only in case of remapping, not necessary for default port-timer mapping # endif /* TIMx clock enable */ # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) RCC_APB1PeriphClockCmd(IRSND_TIMER_RCC, ENABLE); # else RCC_APB2PeriphClockCmd(IRSND_TIMER_RCC, ENABLE); # endif /* Time base configuration */ TIM_TimeBaseStructure.TIM_Period = -1; // set dummy value (don't set to 0), will be initialized later TIM_TimeBaseStructure.TIM_Prescaler = 0; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(IRSND_TIMER, &TIM_TimeBaseStructure); /* PWM1 Mode configuration */ TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse = 0; // will be initialized later TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC1Init(IRSND_TIMER, &TIM_OCInitStructure); /* Preload configuration */ TIM_ARRPreloadConfig(IRSND_TIMER, ENABLE); TIM_OC1PreloadConfig(IRSND_TIMER, TIM_OCPreload_Enable); irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency # elif defined (ARM_STM32_OPENCM3) // ARM_STM32_OPENCM3 /* GPIOx clock enable */ # if defined (STM32L1) || defined (STM32F1) || defined (STM32F3) || defined (STM32F4) rcc_periph_clock_enable(IRSND_PORT_RCC); # endif /* GPIO Configuration */ # if defined (STM32L) || defined (STM32F4) gpio_mode_setup(IRSND_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IRSND_BIT); gpio_set_output_options(IRSND_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRSND_BIT); gpio_set_af(IRSND_PORT, IRSND_GPIO_AF, (uint8_t)IRSND_BIT_NUMBER); # elif defined (STM32F1) gpio_set_mode(IRSND_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, IRSND_BIT); # elif defined (STM32F3) gpio_mode_setup(IRSND_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IRSND_BIT); gpio_set_output_options(IRSND_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, IRSND_BIT); //gpio_set_af(IRSND_PORT, IRSND_GPIO_AF, (uint8_t)IRSND_BIT_NUMBER); # endif /* TIMx clock enable */ # if ((IRSND_TIMER_NUMBER >= 2) && (IRSND_TIMER_NUMBER <= 5)) || ((IRSND_TIMER_NUMBER >= 12) && (IRSND_TIMER_NUMBER <= 14)) rcc_periph_clock_enable(IRSND_TIMER_RCC); # else rcc_periph_clock_enable(IRSND_TIMER_RCC); # endif /* Time base configuration */ timer_set_mode(IRSND_TIMER, 0, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); timer_set_period(IRSND_TIMER, -1); // set dummy value (don't set to 0), will be initialized later timer_set_prescaler(IRSND_TIMER, 0); /* PWM1 Mode configuration */ timer_set_oc_mode(IRSND_TIMER, TIM_OC1, TIM_OCM_PWM1); timer_enable_oc_output(IRSND_TIMER, TIM_OC1); timer_set_oc_value(IRSND_TIMER, TIM_OC1, 0); // will be initialized later timer_set_oc_polarity_high(IRSND_TIMER, TIM_OC1); /* Preload configuration */ timer_enable_preload(IRSND_TIMER); timer_enable_oc_preload(IRSND_TIMER, TIM_OC1); irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency # elif defined (ARM_STM32_HAL) irsnd_set_freq (IRSND_FREQ_36_KHZ); // default frequency # elif defined (ARDUINO_ARCH_RP2040) // ARDUINO_ARCH_RP2040 /* GPIO Configuration */ gpio_set_function(IRSND_BIT, GPIO_FUNC_PWM); slice_num = pwm_gpio_to_slice_num(IRSND_BIT); pwm_set_output_polarity(slice_num, true, true); gpio_set_outover(IRSND_BIT, GPIO_OVERRIDE_LOW); irsnd_set_freq (IRSND_FREQ_36_KHZ); // set default frequency # elif defined (TEENSY_ARM_CORTEX_M4) if (!digitalPinHasPWM(IRSND_PIN)) { return; } # elif defined (__xtensa__) pinMode(IRSND_PIN, OUTPUT); irsnd_set_freq (IRSND_FREQ_36_KHZ); # elif defined (__AVR_XMEGA__) IRSND_PORT &= ~(1<>= 1; len--; } return xx; } #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 static uint8_t sircs_additional_bitlen; #endif // IRSND_SUPPORT_SIRCS_PROTOCOL == 1 /** * @param do_wait - true: Wait for last command to have ended sending its trailing space before start of new sending. * For Arduino: Additionally wait for sent command to have ended (including trailing gap). * false: Return directly and do sending in background. * Keep in mind not to send next frame in background before this frame and its trailing space has ended! * @return false if protocol was not found or do_wait was false and sending (of former frame and its trailing space) is still in progress. */ # ifdef __cplusplus bool #else uint8_t #endif irsnd_send_data(IRMP_DATA *irmp_data_p, uint8_t do_wait) { #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 static uint8_t toggle_bit_recs80; #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 static uint8_t toggle_bit_recs80ext; #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 static uint8_t toggle_bit_rc5; #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1 static uint8_t toggle_bit_rc6; #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 static uint8_t toggle_bit_thomson; #endif uint16_t address; uint16_t command; // to avoid [-Wunused-variable] compiler warnings, e.g. if only NUBERT is activated. (void) address; (void) command; if (do_wait) { while (irsnd_busy) { // wait for last command to have ended } } else if (irsnd_busy) { // Here we do not want to wait, but sending is still in progress and we may overwrite current frame data if not returning here. return (FALSE); } irsnd_protocol = irmp_data_p->protocol; irsnd_repeat = irmp_data_p->flags & IRSND_REPETITION_MASK; #if !defined(ARDUINO) // never send a trailing space for Arduino irsnd_suppress_trailer = (irmp_data_p->flags & IRSND_SUPPRESS_TRAILER) ? TRUE : FALSE; #endif switch (irsnd_protocol) { #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 case IRMP_SIRCS_PROTOCOL: { // uint8_t sircs_additional_command_len; uint8_t sircs_additional_address_len; sircs_additional_bitlen = (irmp_data_p->address & 0xFF00) >> 8; // additional bitlen if (sircs_additional_bitlen > 15 - SIRCS_MINIMUM_DATA_LEN) { // sircs_additional_command_len = 15 - SIRCS_MINIMUM_DATA_LEN; sircs_additional_address_len = sircs_additional_bitlen - (15 - SIRCS_MINIMUM_DATA_LEN); } else { // sircs_additional_command_len = sircs_additional_bitlen; sircs_additional_address_len = 0; } command = bitsrevervse (irmp_data_p->command, 15); irsnd_buffer[0] = (command & 0x7F80) >> 7; // CCCCCCCC irsnd_buffer[1] = (command & 0x007F) << 1; // CCCC**** if (sircs_additional_address_len > 0) { address = bitsrevervse (irmp_data_p->address, 5); irsnd_buffer[1] |= (address & 0x0010) >> 4; irsnd_buffer[2] = (address & 0x000F) << 4; } irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 case IRMP_APPLE_PROTOCOL: { command = irmp_data_p->command | (irmp_data_p->address << 8); // store address as ID in upper byte of command address = 0x87EE; // set fixed NEC-lookalike address (customer ID of apple) address = bitsrevervse (address, NEC_ADDRESS_LEN); command = bitsrevervse (command, NEC_COMMAND_LEN); irsnd_protocol = IRMP_NEC_PROTOCOL; // APPLE protocol is NEC with id instead of inverted command irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[3] = (command & 0x00FF); // cccccccc (ID) irsnd_busy = TRUE; break; } case IRMP_NEC_PROTOCOL: { if (irmp_data_p->flags & IRSND_RAW_REPETITION_FRAME) { irsnd_protocol = IRMP_NEC_REPETITION_PROTOCOL; // send a raw repetition frame irsnd_buffer[0] = 0x00; // no address, no command } else { address = bitsrevervse (irmp_data_p->address, NEC_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, NEC_COMMAND_LEN); irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[3] = ~((command & 0xFF00) >> 8); // cccccccc } irsnd_busy = TRUE; break; } case IRMP_ONKYO_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, NEC_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, NEC_COMMAND_LEN); irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[3] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 case IRMP_NEC16_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, NEC16_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, NEC16_COMMAND_LEN); irsnd_buffer[0] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NEC42_PROTOCOL == 1 case IRMP_NEC42_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, NEC42_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, NEC42_COMMAND_LEN); irsnd_buffer[0] = ( (address & 0x1FE0) >> 5); // AAAAAAAA irsnd_buffer[1] = ( (address & 0x001F) << 3) | ((~address & 0x1C00) >> 10); // AAAAAaaa irsnd_buffer[2] = ((~address & 0x03FC) >> 2); // aaaaaaaa irsnd_buffer[3] = ((~address & 0x0003) << 6) | ( (command & 0x00FC) >> 2); // aaCCCCCC irsnd_buffer[4] = ( (command & 0x0003) << 6) | ((~command & 0x00FC) >> 2); // CCcccccc irsnd_buffer[5] = ((~command & 0x0003) << 6); // cc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_MELINERA_PROTOCOL == 1 case IRMP_MELINERA_PROTOCOL: { command = irmp_data_p->command; irsnd_buffer[0] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_LGAIR_PROTOCOL == 1 case IRMP_LGAIR_PROTOCOL: { address = irmp_data_p->address; command = irmp_data_p->command; irsnd_buffer[0] = ( (address & 0x00FF)); // AAAAAAAA irsnd_buffer[1] = ( (command & 0xFF00) >> 8); // CCCCCCCC irsnd_buffer[2] = ( (command & 0x00FF)); // CCCCCCCC irsnd_buffer[3] = (( ((command & 0xF000) >> 12) + // checksum ((command & 0x0F00) >> 8) + ((command & 0x00F0) >>4 ) + ((command & 0x000F))) & 0x000F) << 4; irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 case IRMP_SAMSUNG_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, SAMSUNG_COMMAND_LEN); irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = (command & 0x00F0) | ((command & 0xF000) >> 12); // IIIICCCC irsnd_buffer[3] = ((command & 0x0F00) >> 4) | ((~(command & 0xF000) >> 12) & 0x0F); // CCCCcccc irsnd_buffer[4] = (~(command & 0x0F00) >> 4) & 0xF0; // cccc0000 irsnd_busy = TRUE; break; } case IRMP_SAMSUNG32_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, SAMSUNG32_COMMAND_LEN); irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[3] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1 case IRMP_SAMSUNG48_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, SAMSUNG_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, 16); irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = ((command & 0xFF00) >> 8); // CCCCCCCC irsnd_buffer[3] = ~((command & 0xFF00) >> 8); // cccccccc irsnd_buffer[4] = (command & 0x00FF); // CCCCCCCC irsnd_buffer[5] = ~(command & 0x00FF); // cccccccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 case IRMP_MATSUSHITA_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, MATSUSHITA_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, MATSUSHITA_COMMAND_LEN); irsnd_buffer[0] = (command & 0x0FF0) >> 4; // CCCCCCCC irsnd_buffer[1] = ((command & 0x000F) << 4) | ((address & 0x0F00) >> 8); // CCCCAAAA irsnd_buffer[2] = (address & 0x00FF); // AAAAAAAA irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 case IRMP_TECHNICS_PROTOCOL: { command = bitsrevervse (irmp_data_p->command, TECHNICS_COMMAND_LEN); irsnd_buffer[0] = (command & 0x07FC) >> 3; // CCCCCCCC irsnd_buffer[1] = ((command & 0x0007) << 5) | ((~command & 0x07C0) >> 6); // CCCccccc irsnd_buffer[2] = (~command & 0x003F) << 2; // cccccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 case IRMP_KASEIKYO_PROTOCOL: { uint8_t xor_value; uint16_t genre2; address = bitsrevervse (irmp_data_p->address, KASEIKYO_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, KASEIKYO_COMMAND_LEN + 4); genre2 = bitsrevervse ((irmp_data_p->flags & ~IRSND_REPETITION_MASK) >> 4, 4); xor_value = ((address & 0x000F) ^ ((address & 0x00F0) >> 4) ^ ((address & 0x0F00) >> 8) ^ ((address & 0xF000) >> 12)) & 0x0F; irsnd_buffer[0] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[1] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[2] = xor_value << 4 | (command & 0x000F); // XXXXCCCC irsnd_buffer[3] = (genre2 << 4) | (command & 0xF000) >> 12; // ggggCCCC irsnd_buffer[4] = (command & 0x0FF0) >> 4; // CCCCCCCC xor_value = irsnd_buffer[2] ^ irsnd_buffer[3] ^ irsnd_buffer[4]; irsnd_buffer[5] = xor_value; irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 case IRMP_PANASONIC_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, PANASONIC_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, PANASONIC_COMMAND_LEN); irsnd_buffer[0] = 0x40; // 01000000 irsnd_buffer[1] = 0x04; // 00000100 irsnd_buffer[2] = 0x01; // 00000001 irsnd_buffer[3] = (address & 0xFF00) >> 8; // AAAAAAAA irsnd_buffer[4] = (address & 0x00FF); // AAAAAAAA irsnd_buffer[5] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[6] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 case IRMP_MITSU_HEAVY_PROTOCOL: { address = irmp_data_p->address; command = irmp_data_p->command; irsnd_buffer[0] = 0x4A; irsnd_buffer[1] = 0x75; irsnd_buffer[2] = 0xC3; irsnd_buffer[3] = 0x64; irsnd_buffer[4] = 0x9B; irsnd_buffer[5] = ~(address & 0xFF00) >> 8; irsnd_buffer[6] = (address & 0xFF00) >> 8; irsnd_buffer[7] = ~(address & 0x00FF); irsnd_buffer[8] = (address & 0x00FF); irsnd_buffer[9] = ~(command & 0x00FF); irsnd_buffer[10] = (command & 0x00FF); irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 case IRMP_RECS80_PROTOCOL: { toggle_bit_recs80 = toggle_bit_recs80 ? 0x00 : 0x80; irsnd_buffer[0] = toggle_bit_recs80 | ((irmp_data_p->address & 0x000F) << 4) | ((irmp_data_p->command & 0x003C) >> 2); // TAAACCCC irsnd_buffer[1] = (irmp_data_p->command & 0x03) << 6; // CC000000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 case IRMP_RECS80EXT_PROTOCOL: { toggle_bit_recs80ext = toggle_bit_recs80ext ? 0x00 : 0x40; irsnd_buffer[0] = 0x80 | toggle_bit_recs80ext | ((irmp_data_p->address & 0x000F) << 2) | ((irmp_data_p->command & 0x0030) >> 4); // STAAAACC irsnd_buffer[1] = (irmp_data_p->command & 0x0F) << 4; // CCCC0000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 case IRMP_RC5_PROTOCOL: { toggle_bit_rc5 = toggle_bit_rc5 ? 0x00 : 0x40; irsnd_buffer[0] = ((irmp_data_p->command & 0x40) ? 0x00 : 0x80) | toggle_bit_rc5 | ((irmp_data_p->address & 0x001F) << 1) | ((irmp_data_p->command & 0x20) >> 5); // CTAAAAAC irsnd_buffer[1] = (irmp_data_p->command & 0x1F) << 3; // CCCCC000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 case IRMP_RC6_PROTOCOL: { toggle_bit_rc6 = toggle_bit_rc6 ? 0x00 : 0x08; irsnd_buffer[0] = 0x80 | toggle_bit_rc6 | ((irmp_data_p->address & 0x00E0) >> 5); // 1MMMTAAA, MMM = 000 irsnd_buffer[1] = ((irmp_data_p->address & 0x001F) << 3) | ((irmp_data_p->command & 0xE0) >> 5); // AAAAACCC irsnd_buffer[2] = (irmp_data_p->command & 0x1F) << 3; // CCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RC6A_PROTOCOL == 1 case IRMP_RC6A_PROTOCOL: { toggle_bit_rc6 = toggle_bit_rc6 ? 0x00 : 0x08; irsnd_buffer[0] = 0x80 | 0x60 | ((irmp_data_p->address & 0x3000) >> 12); // 1MMMT0AA, MMM = 110 irsnd_buffer[1] = ((irmp_data_p->address & 0x0FFF) >> 4) ; // AAAAAAAA irsnd_buffer[2] = ((irmp_data_p->address & 0x000F) << 4) | ((irmp_data_p->command & 0xF000) >> 12) | toggle_bit_rc6; // AAAACCCC irsnd_buffer[3] = (irmp_data_p->command & 0x0FF0) >> 4; // CCCCCCCC irsnd_buffer[4] = (irmp_data_p->command & 0x000F) << 4; // CCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_DENON_PROTOCOL == 1 case IRMP_DENON_PROTOCOL: { irsnd_buffer[0] = ((irmp_data_p->address & 0x1F) << 3) | ((irmp_data_p->command & 0x0380) >> 7); // AAAAACCC (1st frame) irsnd_buffer[1] = (irmp_data_p->command & 0x7F) << 1; // CCCCCCC irsnd_buffer[2] = ((irmp_data_p->address & 0x1F) << 3) | (((~irmp_data_p->command) & 0x0380) >> 7); // AAAAAccc (2nd frame) irsnd_buffer[3] = (~(irmp_data_p->command) & 0x7F) << 1; // ccccccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 case IRMP_THOMSON_PROTOCOL: { toggle_bit_thomson = toggle_bit_thomson ? 0x00 : 0x08; irsnd_buffer[0] = ((irmp_data_p->address & 0x0F) << 4) | toggle_bit_thomson | ((irmp_data_p->command & 0x0070) >> 4); // AAAATCCC (1st frame) irsnd_buffer[1] = (irmp_data_p->command & 0x0F) << 4; // CCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_BOSE_PROTOCOL == 1 case IRMP_BOSE_PROTOCOL: { command = bitsrevervse (irmp_data_p->command, BOSE_COMMAND_LEN); irsnd_buffer[0] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[1] = ~((command & 0xFF00) >> 8); // cccccccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1 case IRMP_NUBERT_PROTOCOL: { irsnd_buffer[0] = irmp_data_p->command >> 2; // CCCCCCCC irsnd_buffer[1] = (irmp_data_p->command & 0x0003) << 6; // CC000000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_FAN_PROTOCOL == 1 case IRMP_FAN_PROTOCOL: { irsnd_buffer[0] = irmp_data_p->command >> 3; // CCCCCCCC irsnd_buffer[1] = (irmp_data_p->command & 0x0007) << 5; // CCC00000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 case IRMP_SPEAKER_PROTOCOL: { irsnd_buffer[0] = irmp_data_p->command >> 2; // CCCCCCCC irsnd_buffer[1] = (irmp_data_p->command & 0x0003) << 6; // CC000000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 case IRMP_BANG_OLUFSEN_PROTOCOL: { irsnd_buffer[0] = irmp_data_p->command >> 11; // SXSCCCCC irsnd_buffer[1] = irmp_data_p->command >> 3; // CCCCCCCC irsnd_buffer[2] = (irmp_data_p->command & 0x0007) << 5; // CCC00000 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 case IRMP_GRUNDIG_PROTOCOL: { command = bitsrevervse (irmp_data_p->command, GRUNDIG_COMMAND_LEN); irsnd_buffer[0] = 0xFF; // S1111111 (1st frame) irsnd_buffer[1] = 0xC0; // 11 irsnd_buffer[2] = 0x80 | (command >> 2); // SCCCCCCC (2nd frame) irsnd_buffer[3] = (command << 6) & 0xC0; // CC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 case IRMP_TELEFUNKEN_PROTOCOL: { irsnd_buffer[0] = irmp_data_p->command >> 7; // CCCCCCCC irsnd_buffer[1] = (irmp_data_p->command << 1) & 0xff; // CCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 case IRMP_IR60_PROTOCOL: { command = (bitsrevervse (0x7d, IR60_COMMAND_LEN) << 7) | bitsrevervse (irmp_data_p->command, IR60_COMMAND_LEN); #if 1 irsnd_buffer[0] = command >> 6 | 0x01; // 1011111S (start instruction frame) irsnd_buffer[1] = (command & 0x7F) << 1; // CCCCCCC_ (2nd frame) #else irsnd_buffer[0] = ((command & 0x7F) << 1) | 0x01; // CCCCCCCS (1st frame) irsnd_buffer[1] = command >> 6; // 1011111_ (start instruction frame) #endif irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 case IRMP_NOKIA_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, NOKIA_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, NOKIA_COMMAND_LEN); irsnd_buffer[0] = 0xBF; // S0111111 (1st + 3rd frame) irsnd_buffer[1] = 0xFF; // 11111111 irsnd_buffer[2] = 0x80; // 1 irsnd_buffer[3] = 0x80 | command >> 1; // SCCCCCCC (2nd frame) irsnd_buffer[4] = (command << 7) | (address >> 1); // CAAAAAAA irsnd_buffer[5] = (address << 7); // A irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 case IRMP_SIEMENS_PROTOCOL: { irsnd_buffer[0] = ((irmp_data_p->address & 0x07FF) >> 3); // AAAAAAAA irsnd_buffer[1] = ((irmp_data_p->address & 0x0007) << 5) | ((irmp_data_p->command >> 5) & 0x1F); // AAACCCCC irsnd_buffer[2] = ((irmp_data_p->command & 0x001F) << 3) | ((~irmp_data_p->command & 0x01) << 2); // CCCCCc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 case IRMP_RUWIDO_PROTOCOL: { irsnd_buffer[0] = ((irmp_data_p->address & 0x01FF) >> 1); // AAAAAAAA irsnd_buffer[1] = ((irmp_data_p->address & 0x0001) << 7) | ((irmp_data_p->command & 0x7F)); // ACCCCCCC irsnd_buffer[2] = ((~irmp_data_p->command & 0x01) << 7); // c irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_FDC_PROTOCOL == 1 case IRMP_FDC_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, FDC_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, FDC_COMMAND_LEN); irsnd_buffer[0] = (address & 0xFF); // AAAAAAAA irsnd_buffer[1] = 0; // 00000000 irsnd_buffer[2] = 0; // 0000RRRR irsnd_buffer[3] = (command & 0xFF); // CCCCCCCC irsnd_buffer[4] = ~(command & 0xFF); // cccccccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_RCCAR_PROTOCOL == 1 case IRMP_RCCAR_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, 2); // A0 A1 command = bitsrevervse (irmp_data_p->command, RCCAR_COMMAND_LEN - 2); // D0 D1 D2 D3 D4 D5 D6 D7 C0 C1 V irsnd_buffer[0] = ((command & 0x06) << 5) | ((address & 0x0003) << 4) | ((command & 0x0780) >> 7); // C0 C1 A0 A1 D0 D1 D2 D3 irsnd_buffer[1] = ((command & 0x78) << 1) | ((command & 0x0001) << 3); // D4 D5 D6 D7 V 0 0 0 irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_JVC_PROTOCOL == 1 case IRMP_JVC_PROTOCOL: { address = bitsrevervse (irmp_data_p->address, JVC_ADDRESS_LEN); command = bitsrevervse (irmp_data_p->command, JVC_COMMAND_LEN); irsnd_buffer[0] = ((address & 0x000F) << 4) | (command & 0x0F00) >> 8; // AAAACCCC irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 case IRMP_NIKON_PROTOCOL: { irsnd_buffer[0] = (irmp_data_p->command & 0x0003) << 6; // CC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 case IRMP_LEGO_PROTOCOL: { uint8_t crc = 0x0F ^ ((irmp_data_p->command & 0x0F00) >> 8) ^ ((irmp_data_p->command & 0x00F0) >> 4) ^ (irmp_data_p->command & 0x000F); irsnd_buffer[0] = (irmp_data_p->command & 0x0FF0) >> 4; // CCCCCCCC irsnd_buffer[1] = ((irmp_data_p->command & 0x000F) << 4) | crc; // CCCCcccc irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_IRMP16_PROTOCOL == 1 case IRMP_IRMP16_PROTOCOL: { command = bitsrevervse (irmp_data_p->command, IRMP16_COMMAND_LEN); irsnd_buffer[0] = (command & 0xFF00) >> 8; // CCCCCCCC irsnd_buffer[1] = (command & 0x00FF); // CCCCCCCC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 case IRMP_A1TVBOX_PROTOCOL: { irsnd_buffer[0] = 0x80 | (irmp_data_p->address >> 2); // 10AAAAAA irsnd_buffer[1] = (irmp_data_p->address << 6) | (irmp_data_p->command >> 2); // AACCCCCC irsnd_buffer[2] = (irmp_data_p->command << 6); // CC irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 case IRMP_ROOMBA_PROTOCOL: { irsnd_buffer[0] = (irmp_data_p->command & 0x7F) << 1; // CCCCCCC. irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_PENTAX_PROTOCOL == 1 case IRMP_PENTAX_PROTOCOL: { irsnd_buffer[0] = (irmp_data_p->command & 0x3F) << 2; // CCCCCC.. irsnd_busy = TRUE; break; } #endif #if IRSND_SUPPORT_ACP24_PROTOCOL == 1 # define ACP_SET_BIT(acp24_bitno, c, irmp_bitno) \ do \ { \ if ((c) & (1<<(irmp_bitno))) \ { \ irsnd_buffer[((acp24_bitno)>>3)] |= 1 << (((7 - (acp24_bitno)) & 0x07)); \ } \ } while (0) case IRMP_ACP24_PROTOCOL: { uint16_t cmd = irmp_data_p->command; uint8_t i; address = bitsrevervse (irmp_data_p->address, ACP24_ADDRESS_LEN); for (i = 0; i < 8; i++) { irsnd_buffer[i] = 0x00; // CCCCCCCC } // ACP24-Frame: // 1 2 3 4 5 6 // 0123456789012345678901234567890123456789012345678901234567890123456789 // N VVMMM ? ??? t vmA x y TTTT // // irmp_data_p->command: // // 5432109876543210 // NAVVvMMMmtxyTTTT ACP_SET_BIT( 0, cmd, 15); ACP_SET_BIT(24, cmd, 14); ACP_SET_BIT( 2, cmd, 13); ACP_SET_BIT( 3, cmd, 12); ACP_SET_BIT(22, cmd, 11); ACP_SET_BIT( 4, cmd, 10); ACP_SET_BIT( 5, cmd, 9); ACP_SET_BIT( 6, cmd, 8); ACP_SET_BIT(23, cmd, 7); ACP_SET_BIT(20, cmd, 6); ACP_SET_BIT(26, cmd, 5); ACP_SET_BIT(44, cmd, 4); ACP_SET_BIT(66, cmd, 3); ACP_SET_BIT(67, cmd, 2); ACP_SET_BIT(68, cmd, 1); ACP_SET_BIT(69, cmd, 0); irsnd_busy = TRUE; break; } #endif // @formatter:off default: { return (FALSE); // Error here: we called irsnd_send_data with a non enabled protocol! break; } // @formatter:on } #if defined(ARDUINO) storeIRTimer(); // store current timer state to enable alternately send and receive with the same timer initIRTimerForSend(); // Setup timer and interrupts for sending if (do_wait) { while (irsnd_busy) { // Wait for frame and leading space to be sent; } } return true; // next frame may start immediately if do_wait was true #else return irsnd_busy; #endif } void irsnd_stop(void) { irsnd_repeat = 0; } /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ISR routine * @details ISR routine, called from 10000 to 20000, typically 15000 times per second * If new frame starts, check for autorepeat gap, then check for trailing space gap, then initialize frame. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ # ifdef __cplusplus bool #else uint8_t #endif irsnd_ISR(void) { // @formatter:off #if !defined(ARDUINO) // never send a trailing space for Arduino static uint8_t send_last_trailer = FALSE; // Only for last trailer after n repeats. if TRUE, we send the trailing space as defined in repeat_frame_pause_len #endif static uint8_t current_bit = 0xFF; // 0xFF => send start bit static uint8_t pulse_counter = 0; static IRSND_PAUSE_LEN pause_counter = 0; static uint8_t startbit_pulse_len = 0; static IRSND_PAUSE_LEN startbit_pause_len = 0; static uint8_t pulse_1_len = 0; static uint8_t pause_1_len = 0; static uint8_t pulse_0_len = 0; static uint8_t pause_0_len = 0; static uint8_t has_stop_bit = 0; static uint8_t new_frame = TRUE; static uint8_t complete_data_len = 0; static uint8_t n_repeat_frames = 0; // number of repetition frames static uint8_t n_auto_repetitions = 0; // number of frames inclusive auto_repetition frames static uint8_t auto_repetition_counter = 0; // auto_repetition counter static uint16_t auto_repetition_pause_len = 0; // pause before auto_repetition, uint16_t! static uint16_t auto_repetition_pause_counter = 0; // pause before auto_repetition, uint16_t! static uint8_t repeat_counter = 0; // repeat counter static uint16_t repeat_frame_pause_len = 0; // pause before repeat, uint16_t! static uint16_t packet_repeat_pause_counter = 0; // pause before repeat, uint16_t! #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 static uint8_t last_bit_value; #endif static uint8_t pulse_len = 0xFF; static IRSND_PAUSE_LEN pause_len = 0xFF; // @formatter:on if (irsnd_busy) { if (current_bit == 0xFF && new_frame) // start of transmission... { // check for autorepeat gap, then check for trailing space gap, then initialize frame. if (auto_repetition_counter > 0) { /* * Send gap between auto repetitions */ auto_repetition_pause_counter++; // count gap duration if (auto_repetition_pause_counter >= auto_repetition_pause_len) { auto_repetition_pause_counter = 0; // end of auto repetition space #if IRSND_SUPPORT_DENON_PROTOCOL == 1 if (irsnd_protocol == IRMP_DENON_PROTOCOL) // n'th denon frame { current_bit = 16; complete_data_len = 2 * DENON_COMPLETE_DATA_LEN + 1; } else #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL) // n'th grundig frame { current_bit = 15; complete_data_len = 16 + GRUNDIG_COMPLETE_DATA_LEN; } else #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 if (irsnd_protocol == IRMP_IR60_PROTOCOL) // n'th IR60 frame { current_bit = 7; complete_data_len = 2 * IR60_COMPLETE_DATA_LEN + 1; } else #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 if (irsnd_protocol == IRMP_NOKIA_PROTOCOL) // n'th nokia frame { if (auto_repetition_counter + 1 < n_auto_repetitions) { current_bit = 23; complete_data_len = 24 + NOKIA_COMPLETE_DATA_LEN; } else // nokia stop frame { current_bit = 0xFF; complete_data_len = NOKIA_COMPLETE_DATA_LEN; } } else #endif { ; } } else { #if defined(ANALYZE) if (irsnd_is_on) { putchar('0'); } else { putchar('1'); } #endif // auto repetition pause here return irsnd_busy; } } /* * Send trailing space */ else if (packet_repeat_pause_counter < repeat_frame_pause_len) { /* * Send trailing space, especially for repeats */ packet_repeat_pause_counter++; // count trailing space duration #if defined(ANALYZE) if (irsnd_is_on) { putchar ('0'); } else { putchar ('1'); } #endif return irsnd_busy; } else { // End of trailing space here => initialize new frame #if !defined(ARDUINO) // never send a trailing space for Arduino if (send_last_trailer) { irsnd_busy = FALSE; // Trailing space sent complete, stop sending send_last_trailer = FALSE; return irsnd_busy; } #endif n_repeat_frames = irsnd_repeat; if (n_repeat_frames == IRSND_ENDLESS_REPETITION) { n_repeat_frames = 255; } packet_repeat_pause_counter = 0; pulse_counter = 0; pause_counter = 0; /* * Initialize new frame for selected protocol */ switch (irsnd_protocol) { #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 case IRMP_SIRCS_PROTOCOL: { startbit_pulse_len = IRSND_SIRCS_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_SIRCS_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_SIRCS_1_PULSE_LEN; pause_1_len = IRSND_SIRCS_PAUSE_LEN - 1; pulse_0_len = IRSND_SIRCS_0_PULSE_LEN; pause_0_len = IRSND_SIRCS_PAUSE_LEN - 1; has_stop_bit = SIRCS_STOP_BIT; complete_data_len = SIRCS_MINIMUM_DATA_LEN + sircs_additional_bitlen; n_auto_repetitions = (repeat_counter == 0) ? SIRCS_FRAMES : 1; // 3 frames auto repetition if first frame auto_repetition_pause_len = IRSND_SIRCS_AUTO_REPETITION_PAUSE_LEN; // 25ms pause repeat_frame_pause_len = IRSND_SIRCS_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_40_KHZ); break; } #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 case IRMP_NEC_PROTOCOL: case IRMP_NEC_REPETITION_PROTOCOL: case IRMP_ONKYO_PROTOCOL: { startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN; if (repeat_counter > 0 || irsnd_protocol == IRMP_NEC_REPETITION_PROTOCOL) { startbit_pause_len = IRSND_NEC_REPEAT_START_BIT_PAUSE_LEN - 1; complete_data_len = 0; } else { startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1; complete_data_len = NEC_COMPLETE_DATA_LEN; } pulse_1_len = IRSND_NEC_PULSE_LEN; pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NEC_PULSE_LEN; pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1; has_stop_bit = NEC_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 case IRMP_NEC16_PROTOCOL: { startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_NEC_PULSE_LEN; pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NEC_PULSE_LEN; pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1; has_stop_bit = NEC_STOP_BIT; complete_data_len = NEC16_COMPLETE_DATA_LEN + 1; // 1 more: sync bit n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_NEC42_PROTOCOL == 1 case IRMP_NEC42_PROTOCOL: { startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_NEC_PULSE_LEN; pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NEC_PULSE_LEN; pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1; has_stop_bit = NEC_STOP_BIT; complete_data_len = NEC42_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_MELINERA_PROTOCOL == 1 case IRMP_MELINERA_PROTOCOL: { startbit_pulse_len = IRSND_MELINERA_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_MELINERA_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_MELINERA_1_PULSE_LEN; pause_1_len = IRSND_MELINERA_1_PAUSE_LEN - 1; pulse_0_len = IRSND_MELINERA_0_PULSE_LEN; pause_0_len = IRSND_MELINERA_0_PAUSE_LEN - 1; has_stop_bit = MELINERA_STOP_BIT; complete_data_len = MELINERA_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_MELINERA_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_LGAIR_PROTOCOL == 1 case IRMP_LGAIR_PROTOCOL: { startbit_pulse_len = IRSND_NEC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_NEC_PULSE_LEN; pause_1_len = IRSND_NEC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NEC_PULSE_LEN; pause_0_len = IRSND_NEC_0_PAUSE_LEN - 1; has_stop_bit = NEC_STOP_BIT; complete_data_len = LGAIR_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_NEC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 case IRMP_SAMSUNG_PROTOCOL: { startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_SAMSUNG_PULSE_LEN; pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1; pulse_0_len = IRSND_SAMSUNG_PULSE_LEN; pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1; has_stop_bit = SAMSUNG_STOP_BIT; complete_data_len = SAMSUNG_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_SAMSUNG_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } case IRMP_SAMSUNG32_PROTOCOL: { startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_SAMSUNG_PULSE_LEN; pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1; pulse_0_len = IRSND_SAMSUNG_PULSE_LEN; pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1; has_stop_bit = SAMSUNG_STOP_BIT; complete_data_len = SAMSUNG32_COMPLETE_DATA_LEN; n_auto_repetitions = SAMSUNG32_FRAMES; // 1 frame auto_repetition_pause_len = IRSND_SAMSUNG32_AUTO_REPETITION_PAUSE_LEN; // 47 ms pause repeat_frame_pause_len = IRSND_SAMSUNG32_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1 case IRMP_SAMSUNG48_PROTOCOL: { startbit_pulse_len = IRSND_SAMSUNG_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_SAMSUNG_PULSE_LEN; pause_1_len = IRSND_SAMSUNG_1_PAUSE_LEN - 1; pulse_0_len = IRSND_SAMSUNG_PULSE_LEN; pause_0_len = IRSND_SAMSUNG_0_PAUSE_LEN - 1; has_stop_bit = SAMSUNG_STOP_BIT; complete_data_len = SAMSUNG48_COMPLETE_DATA_LEN; n_auto_repetitions = SAMSUNG48_FRAMES; // 1 frame auto_repetition_pause_len = IRSND_SAMSUNG48_AUTO_REPETITION_PAUSE_LEN; // 47 ms pause repeat_frame_pause_len = IRSND_SAMSUNG48_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 case IRMP_MATSUSHITA_PROTOCOL: { startbit_pulse_len = IRSND_MATSUSHITA_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_MATSUSHITA_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_MATSUSHITA_PULSE_LEN; pause_1_len = IRSND_MATSUSHITA_1_PAUSE_LEN - 1; pulse_0_len = IRSND_MATSUSHITA_PULSE_LEN; pause_0_len = IRSND_MATSUSHITA_0_PAUSE_LEN - 1; has_stop_bit = MATSUSHITA_STOP_BIT; complete_data_len = MATSUSHITA_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 case IRMP_TECHNICS_PROTOCOL: { startbit_pulse_len = IRSND_MATSUSHITA_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_MATSUSHITA_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_MATSUSHITA_PULSE_LEN; pause_1_len = IRSND_MATSUSHITA_1_PAUSE_LEN - 1; pulse_0_len = IRSND_MATSUSHITA_PULSE_LEN; pause_0_len = IRSND_MATSUSHITA_0_PAUSE_LEN - 1; has_stop_bit = MATSUSHITA_STOP_BIT; complete_data_len = TECHNICS_COMPLETE_DATA_LEN; // here TECHNICS n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_MATSUSHITA_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 case IRMP_KASEIKYO_PROTOCOL: { startbit_pulse_len = IRSND_KASEIKYO_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_KASEIKYO_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_KASEIKYO_PULSE_LEN; pause_1_len = IRSND_KASEIKYO_1_PAUSE_LEN - 1; pulse_0_len = IRSND_KASEIKYO_PULSE_LEN; pause_0_len = IRSND_KASEIKYO_0_PAUSE_LEN - 1; has_stop_bit = KASEIKYO_STOP_BIT; complete_data_len = KASEIKYO_COMPLETE_DATA_LEN; n_auto_repetitions = KASEIKYO_FRAMES; // 1 frame auto_repetition_pause_len = IRSND_KASEIKYO_AUTO_REPETITION_PAUSE_LEN; // 75 ms pause repeat_frame_pause_len = IRSND_KASEIKYO_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 case IRMP_PANASONIC_PROTOCOL: { startbit_pulse_len = IRSND_PANASONIC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_PANASONIC_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_PANASONIC_PULSE_LEN; pause_1_len = IRSND_PANASONIC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_PANASONIC_PULSE_LEN; pause_0_len = IRSND_PANASONIC_0_PAUSE_LEN - 1; has_stop_bit = PANASONIC_STOP_BIT; complete_data_len = PANASONIC_COMPLETE_DATA_LEN; n_auto_repetitions = PANASONIC_FRAMES; // 1 frame auto_repetition_pause_len = IRSND_PANASONIC_AUTO_REPETITION_PAUSE_LEN; // 40 ms pause repeat_frame_pause_len = IRSND_PANASONIC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 case IRMP_MITSU_HEAVY_PROTOCOL: { startbit_pulse_len = IRSND_MITSU_HEAVY_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_MITSU_HEAVY_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_MITSU_HEAVY_PULSE_LEN; pause_1_len = IRSND_MITSU_HEAVY_1_PAUSE_LEN - 1; pulse_0_len = IRSND_MITSU_HEAVY_PULSE_LEN; pause_0_len = IRSND_MITSU_HEAVY_0_PAUSE_LEN - 1; has_stop_bit = MITSU_HEAVY_STOP_BIT; complete_data_len = MITSU_HEAVY_COMPLETE_DATA_LEN; n_auto_repetitions = MITSU_HEAVY_FRAMES; // 1 frame auto_repetition_pause_len = 0;; repeat_frame_pause_len = IRSND_MITSU_HEAVY_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_40_KHZ); break; } #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 case IRMP_RECS80_PROTOCOL: { startbit_pulse_len = IRSND_RECS80_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RECS80_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_RECS80_PULSE_LEN; pause_1_len = IRSND_RECS80_1_PAUSE_LEN - 1; pulse_0_len = IRSND_RECS80_PULSE_LEN; pause_0_len = IRSND_RECS80_0_PAUSE_LEN - 1; has_stop_bit = RECS80_STOP_BIT; complete_data_len = RECS80_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RECS80_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 case IRMP_RECS80EXT_PROTOCOL: { startbit_pulse_len = IRSND_RECS80EXT_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RECS80EXT_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_RECS80EXT_PULSE_LEN; pause_1_len = IRSND_RECS80EXT_1_PAUSE_LEN - 1; pulse_0_len = IRSND_RECS80EXT_PULSE_LEN; pause_0_len = IRSND_RECS80EXT_0_PAUSE_LEN - 1; has_stop_bit = RECS80EXT_STOP_BIT; complete_data_len = RECS80EXT_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RECS80EXT_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 case IRMP_TELEFUNKEN_PROTOCOL: { startbit_pulse_len = IRSND_TELEFUNKEN_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_TELEFUNKEN_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_TELEFUNKEN_PULSE_LEN; pause_1_len = IRSND_TELEFUNKEN_1_PAUSE_LEN - 1; pulse_0_len = IRSND_TELEFUNKEN_PULSE_LEN; pause_0_len = IRSND_TELEFUNKEN_0_PAUSE_LEN - 1; has_stop_bit = TELEFUNKEN_STOP_BIT; complete_data_len = TELEFUNKEN_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frames auto_repetition_pause_len = 0; // IRSND_TELEFUNKEN_AUTO_REPETITION_PAUSE_LEN; xx ms pause repeat_frame_pause_len = IRSND_TELEFUNKEN_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 case IRMP_RC5_PROTOCOL: { startbit_pulse_len = IRSND_RC5_BIT_LEN; startbit_pause_len = IRSND_RC5_BIT_LEN; pulse_len = IRSND_RC5_BIT_LEN; pause_len = IRSND_RC5_BIT_LEN; has_stop_bit = RC5_STOP_BIT; complete_data_len = RC5_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RC5_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 case IRMP_RC6_PROTOCOL: { startbit_pulse_len = IRSND_RC6_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RC6_START_BIT_PAUSE_LEN - 1; pulse_len = IRSND_RC6_BIT_LEN; pause_len = IRSND_RC6_BIT_LEN; has_stop_bit = RC6_STOP_BIT; complete_data_len = RC6_COMPLETE_DATA_LEN_SHORT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RC6_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_RC6A_PROTOCOL == 1 case IRMP_RC6A_PROTOCOL: { startbit_pulse_len = IRSND_RC6_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RC6_START_BIT_PAUSE_LEN - 1; pulse_len = IRSND_RC6_BIT_LEN; pause_len = IRSND_RC6_BIT_LEN; has_stop_bit = RC6_STOP_BIT; complete_data_len = RC6_COMPLETE_DATA_LEN_LONG; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RC6_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_DENON_PROTOCOL == 1 case IRMP_DENON_PROTOCOL: { startbit_pulse_len = 0x00; startbit_pause_len = 0x00; pulse_1_len = IRSND_DENON_PULSE_LEN; pause_1_len = IRSND_DENON_1_PAUSE_LEN - 1; pulse_0_len = IRSND_DENON_PULSE_LEN; pause_0_len = IRSND_DENON_0_PAUSE_LEN - 1; has_stop_bit = DENON_STOP_BIT; complete_data_len = DENON_COMPLETE_DATA_LEN; n_auto_repetitions = DENON_FRAMES; // 2 frames, 2nd with inverted command auto_repetition_pause_len = IRSND_DENON_AUTO_REPETITION_PAUSE_LEN; // 65 ms pause after 1st frame repeat_frame_pause_len = IRSND_DENON_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); // in theory 32kHz, in practice 36kHz is better break; } #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 case IRMP_THOMSON_PROTOCOL: { startbit_pulse_len = 0x00; startbit_pause_len = 0x00; pulse_1_len = IRSND_THOMSON_PULSE_LEN; pause_1_len = IRSND_THOMSON_1_PAUSE_LEN - 1; pulse_0_len = IRSND_THOMSON_PULSE_LEN; pause_0_len = IRSND_THOMSON_0_PAUSE_LEN - 1; has_stop_bit = THOMSON_STOP_BIT; complete_data_len = THOMSON_COMPLETE_DATA_LEN; n_auto_repetitions = THOMSON_FRAMES; // only 1 frame auto_repetition_pause_len = IRSND_THOMSON_AUTO_REPETITION_PAUSE_LEN; repeat_frame_pause_len = IRSND_THOMSON_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_BOSE_PROTOCOL == 1 case IRMP_BOSE_PROTOCOL: { startbit_pulse_len = IRSND_BOSE_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_BOSE_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_BOSE_PULSE_LEN; pause_1_len = IRSND_BOSE_1_PAUSE_LEN - 1; pulse_0_len = IRSND_BOSE_PULSE_LEN; pause_0_len = IRSND_BOSE_0_PAUSE_LEN - 1; has_stop_bit = BOSE_STOP_BIT; complete_data_len = BOSE_COMPLETE_DATA_LEN; n_auto_repetitions = BOSE_FRAMES; // 1 frame auto_repetition_pause_len = IRSND_BOSE_AUTO_REPETITION_PAUSE_LEN; // 40 ms pause repeat_frame_pause_len = IRSND_BOSE_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1 case IRMP_NUBERT_PROTOCOL: { startbit_pulse_len = IRSND_NUBERT_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_NUBERT_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_NUBERT_1_PULSE_LEN; pause_1_len = IRSND_NUBERT_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NUBERT_0_PULSE_LEN; pause_0_len = IRSND_NUBERT_0_PAUSE_LEN - 1; has_stop_bit = NUBERT_STOP_BIT; complete_data_len = NUBERT_COMPLETE_DATA_LEN; n_auto_repetitions = NUBERT_FRAMES; // 2 frames auto_repetition_pause_len = IRSND_NUBERT_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause repeat_frame_pause_len = IRSND_NUBERT_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_FAN_PROTOCOL == 1 case IRMP_FAN_PROTOCOL: { startbit_pulse_len = IRSND_FAN_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_FAN_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_FAN_1_PULSE_LEN; pause_1_len = IRSND_FAN_1_PAUSE_LEN - 1; pulse_0_len = IRSND_FAN_0_PULSE_LEN; pause_0_len = IRSND_FAN_0_PAUSE_LEN - 1; has_stop_bit = FAN_STOP_BIT; complete_data_len = FAN_COMPLETE_DATA_LEN; n_auto_repetitions = FAN_FRAMES; // only 1 frame auto_repetition_pause_len = IRSND_FAN_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause repeat_frame_pause_len = IRSND_FAN_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 case IRMP_SPEAKER_PROTOCOL: { startbit_pulse_len = IRSND_SPEAKER_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_SPEAKER_START_BIT_PAUSE_LEN - 1; pulse_1_len = IRSND_SPEAKER_1_PULSE_LEN; pause_1_len = IRSND_SPEAKER_1_PAUSE_LEN - 1; pulse_0_len = IRSND_SPEAKER_0_PULSE_LEN; pause_0_len = IRSND_SPEAKER_0_PAUSE_LEN - 1; has_stop_bit = SPEAKER_STOP_BIT; complete_data_len = SPEAKER_COMPLETE_DATA_LEN; n_auto_repetitions = SPEAKER_FRAMES; // 2 frames auto_repetition_pause_len = IRSND_SPEAKER_AUTO_REPETITION_PAUSE_LEN; // 35 ms pause repeat_frame_pause_len = IRSND_SPEAKER_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 case IRMP_BANG_OLUFSEN_PROTOCOL: { startbit_pulse_len = IRSND_BANG_OLUFSEN_START_BIT1_PULSE_LEN; startbit_pause_len = IRSND_BANG_OLUFSEN_START_BIT1_PAUSE_LEN - 1; pulse_1_len = IRSND_BANG_OLUFSEN_PULSE_LEN; pause_1_len = IRSND_BANG_OLUFSEN_1_PAUSE_LEN - 1; pulse_0_len = IRSND_BANG_OLUFSEN_PULSE_LEN; pause_0_len = IRSND_BANG_OLUFSEN_0_PAUSE_LEN - 1; has_stop_bit = BANG_OLUFSEN_STOP_BIT; complete_data_len = BANG_OLUFSEN_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_BANG_OLUFSEN_FRAME_REPEAT_PAUSE_LEN; last_bit_value = 0; irsnd_set_freq (IRSND_FREQ_455_KHZ); break; } #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 case IRMP_GRUNDIG_PROTOCOL: { startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1; pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT; complete_data_len = GRUNDIG_COMPLETE_DATA_LEN; n_auto_repetitions = GRUNDIG_FRAMES; // 2 frames auto_repetition_pause_len = IRSND_GRUNDIG_AUTO_REPETITION_PAUSE_LEN; // 20m sec pause repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 case IRMP_IR60_PROTOCOL: { startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1; pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT; complete_data_len = IR60_COMPLETE_DATA_LEN; n_auto_repetitions = IR60_FRAMES; // 2 frames auto_repetition_pause_len = IRSND_IR60_AUTO_REPETITION_PAUSE_LEN; // 20m sec pause repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause irsnd_set_freq (IRSND_FREQ_30_KHZ); break; } #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 case IRMP_NOKIA_PROTOCOL: { startbit_pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; startbit_pause_len = IRSND_GRUNDIG_NOKIA_IR60_PRE_PAUSE_LEN - 1; pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; has_stop_bit = GRUNDIG_NOKIA_IR60_STOP_BIT; complete_data_len = NOKIA_COMPLETE_DATA_LEN; n_auto_repetitions = NOKIA_FRAMES; // 2 frames auto_repetition_pause_len = IRSND_NOKIA_AUTO_REPETITION_PAUSE_LEN; // 20 msec pause repeat_frame_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; // 117 msec pause irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 case IRMP_SIEMENS_PROTOCOL: { startbit_pulse_len = IRSND_SIEMENS_BIT_LEN; startbit_pause_len = IRSND_SIEMENS_BIT_LEN; pulse_len = IRSND_SIEMENS_BIT_LEN; pause_len = IRSND_SIEMENS_BIT_LEN; has_stop_bit = SIEMENS_OR_RUWIDO_STOP_BIT; complete_data_len = SIEMENS_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_SIEMENS_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 case IRMP_RUWIDO_PROTOCOL: { startbit_pulse_len = IRSND_RUWIDO_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RUWIDO_START_BIT_PAUSE_LEN; pulse_len = IRSND_RUWIDO_BIT_PULSE_LEN; pause_len = IRSND_RUWIDO_BIT_PAUSE_LEN; has_stop_bit = SIEMENS_OR_RUWIDO_STOP_BIT; complete_data_len = RUWIDO_COMPLETE_DATA_LEN; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RUWIDO_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_36_KHZ); break; } #endif #if IRSND_SUPPORT_FDC_PROTOCOL == 1 case IRMP_FDC_PROTOCOL: { startbit_pulse_len = IRSND_FDC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_FDC_START_BIT_PAUSE_LEN - 1; complete_data_len = FDC_COMPLETE_DATA_LEN; pulse_1_len = IRSND_FDC_PULSE_LEN; pause_1_len = IRSND_FDC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_FDC_PULSE_LEN; pause_0_len = IRSND_FDC_0_PAUSE_LEN - 1; has_stop_bit = FDC_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_FDC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_RCCAR_PROTOCOL == 1 case IRMP_RCCAR_PROTOCOL: { startbit_pulse_len = IRSND_RCCAR_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_RCCAR_START_BIT_PAUSE_LEN - 1; complete_data_len = RCCAR_COMPLETE_DATA_LEN; pulse_1_len = IRSND_RCCAR_PULSE_LEN; pause_1_len = IRSND_RCCAR_1_PAUSE_LEN - 1; pulse_0_len = IRSND_RCCAR_PULSE_LEN; pause_0_len = IRSND_RCCAR_0_PAUSE_LEN - 1; has_stop_bit = RCCAR_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_RCCAR_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_JVC_PROTOCOL == 1 case IRMP_JVC_PROTOCOL: { if (repeat_counter != 0) // skip start bit if repetition frame { current_bit = 0; } startbit_pulse_len = IRSND_JVC_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_JVC_START_BIT_PAUSE_LEN - 1; complete_data_len = JVC_COMPLETE_DATA_LEN; pulse_1_len = IRSND_JVC_PULSE_LEN; pause_1_len = IRSND_JVC_1_PAUSE_LEN - 1; pulse_0_len = IRSND_JVC_PULSE_LEN; pause_0_len = IRSND_JVC_0_PAUSE_LEN - 1; has_stop_bit = JVC_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_JVC_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 case IRMP_NIKON_PROTOCOL: { startbit_pulse_len = IRSND_NIKON_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_NIKON_START_BIT_PAUSE_LEN; complete_data_len = NIKON_COMPLETE_DATA_LEN; pulse_1_len = IRSND_NIKON_PULSE_LEN; pause_1_len = IRSND_NIKON_1_PAUSE_LEN - 1; pulse_0_len = IRSND_NIKON_PULSE_LEN; pause_0_len = IRSND_NIKON_0_PAUSE_LEN - 1; has_stop_bit = NIKON_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_NIKON_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 case IRMP_LEGO_PROTOCOL: { startbit_pulse_len = IRSND_LEGO_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_LEGO_START_BIT_PAUSE_LEN - 1; complete_data_len = LEGO_COMPLETE_DATA_LEN; pulse_1_len = IRSND_LEGO_PULSE_LEN; pause_1_len = IRSND_LEGO_1_PAUSE_LEN - 1; pulse_0_len = IRSND_LEGO_PULSE_LEN; pause_0_len = IRSND_LEGO_0_PAUSE_LEN - 1; has_stop_bit = LEGO_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_LEGO_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_IRMP16_PROTOCOL == 1 case IRMP_IRMP16_PROTOCOL: { startbit_pulse_len = IRSND_IRMP16_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_IRMP16_START_BIT_PAUSE_LEN - 1; complete_data_len = IRMP16_COMPLETE_DATA_LEN; pulse_1_len = IRSND_IRMP16_PULSE_LEN; pause_1_len = IRSND_IRMP16_1_PAUSE_LEN - 1; pulse_0_len = IRSND_IRMP16_PULSE_LEN; pause_0_len = IRSND_IRMP16_0_PAUSE_LEN - 1; has_stop_bit = IRMP16_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_IRMP16_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 case IRMP_A1TVBOX_PROTOCOL: { startbit_pulse_len = IRSND_A1TVBOX_BIT_PULSE_LEN; // don't use A1TVBOX_START_BIT_PULSE_LEN startbit_pause_len = IRSND_A1TVBOX_BIT_PAUSE_LEN; // don't use A1TVBOX_START_BIT_PAUSE_LEN pulse_len = IRSND_A1TVBOX_BIT_PULSE_LEN; pause_len = IRSND_A1TVBOX_BIT_PAUSE_LEN; has_stop_bit = A1TVBOX_STOP_BIT; complete_data_len = A1TVBOX_COMPLETE_DATA_LEN + 1; // we send stop bit as data n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_A1TVBOX_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 case IRMP_ROOMBA_PROTOCOL: { startbit_pulse_len = IRSND_ROOMBA_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_ROOMBA_START_BIT_PAUSE_LEN; pulse_1_len = IRSND_ROOMBA_1_PULSE_LEN; pause_1_len = IRSND_ROOMBA_1_PAUSE_LEN - 1; pulse_0_len = IRSND_ROOMBA_0_PULSE_LEN; pause_0_len = IRSND_ROOMBA_0_PAUSE_LEN - 1; has_stop_bit = ROOMBA_STOP_BIT; complete_data_len = ROOMBA_COMPLETE_DATA_LEN; n_auto_repetitions = ROOMBA_FRAMES; // 8 frames auto_repetition_pause_len = IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN; repeat_frame_pause_len = IRSND_ROOMBA_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_PENTAX_PROTOCOL == 1 case IRMP_PENTAX_PROTOCOL: { startbit_pulse_len = IRSND_PENTAX_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_PENTAX_START_BIT_PAUSE_LEN; complete_data_len = PENTAX_COMPLETE_DATA_LEN; pulse_1_len = IRSND_PENTAX_PULSE_LEN; pause_1_len = IRSND_PENTAX_1_PAUSE_LEN - 1; pulse_0_len = IRSND_PENTAX_PULSE_LEN; pause_0_len = IRSND_PENTAX_0_PAUSE_LEN - 1; has_stop_bit = PENTAX_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_PENTAX_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif #if IRSND_SUPPORT_ACP24_PROTOCOL == 1 case IRMP_ACP24_PROTOCOL: { startbit_pulse_len = IRSND_ACP24_START_BIT_PULSE_LEN; startbit_pause_len = IRSND_ACP24_START_BIT_PAUSE_LEN - 1; complete_data_len = ACP24_COMPLETE_DATA_LEN; pulse_1_len = IRSND_ACP24_PULSE_LEN; pause_1_len = IRSND_ACP24_1_PAUSE_LEN - 1; pulse_0_len = IRSND_ACP24_PULSE_LEN; pause_0_len = IRSND_ACP24_0_PAUSE_LEN - 1; has_stop_bit = ACP24_STOP_BIT; n_auto_repetitions = 1; // 1 frame auto_repetition_pause_len = 0; repeat_frame_pause_len = IRSND_ACP24_FRAME_REPEAT_PAUSE_LEN; irsnd_set_freq (IRSND_FREQ_38_KHZ); break; } #endif // @formatter:off default: { irsnd_busy = FALSE; // no enabled protocol is selected -> stop immediately break; } // @formatter:on } } } // if (current_bit == 0xFF && new_frame) if (irsnd_busy) { new_frame = FALSE; // we just have sent start bit here switch (irsnd_protocol) { #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 case IRMP_SIRCS_PROTOCOL: #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 case IRMP_NEC_PROTOCOL: case IRMP_NEC_REPETITION_PROTOCOL: case IRMP_ONKYO_PROTOCOL: #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 case IRMP_NEC16_PROTOCOL: #endif #if IRSND_SUPPORT_NEC42_PROTOCOL == 1 case IRMP_NEC42_PROTOCOL: #endif #if IRSND_SUPPORT_LGAIR_PROTOCOL == 1 case IRMP_LGAIR_PROTOCOL: #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 case IRMP_SAMSUNG_PROTOCOL: case IRMP_SAMSUNG32_PROTOCOL: #endif #if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1 case IRMP_SAMSUNG48_PROTOCOL: #endif #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 case IRMP_MATSUSHITA_PROTOCOL: #endif #if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 case IRMP_TECHNICS_PROTOCOL: #endif #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 case IRMP_KASEIKYO_PROTOCOL: #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 case IRMP_RECS80_PROTOCOL: #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 case IRMP_RECS80EXT_PROTOCOL: #endif #if IRSND_SUPPORT_DENON_PROTOCOL == 1 case IRMP_DENON_PROTOCOL: #endif #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1 case IRMP_NUBERT_PROTOCOL: #endif #if IRSND_SUPPORT_FAN_PROTOCOL == 1 case IRMP_FAN_PROTOCOL: #endif #if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 case IRMP_SPEAKER_PROTOCOL: #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 case IRMP_BANG_OLUFSEN_PROTOCOL: #endif #if IRSND_SUPPORT_FDC_PROTOCOL == 1 case IRMP_FDC_PROTOCOL: #endif #if IRSND_SUPPORT_RCCAR_PROTOCOL == 1 case IRMP_RCCAR_PROTOCOL: #endif #if IRSND_SUPPORT_JVC_PROTOCOL == 1 case IRMP_JVC_PROTOCOL: #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 case IRMP_NIKON_PROTOCOL: #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 case IRMP_LEGO_PROTOCOL: #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 case IRMP_THOMSON_PROTOCOL: #endif #if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 case IRMP_ROOMBA_PROTOCOL: #endif #if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 case IRMP_TELEFUNKEN_PROTOCOL: #endif #if IRSND_SUPPORT_PENTAX_PROTOCOL == 1 case IRMP_PENTAX_PROTOCOL: #endif #if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 case IRMP_PANASONIC_PROTOCOL: #endif #if IRSND_SUPPORT_ACP24_PROTOCOL == 1 case IRMP_ACP24_PROTOCOL: #endif #if IRSND_SUPPORT_BOSE_PROTOCOL == 1 case IRMP_BOSE_PROTOCOL: #endif #if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 case IRMP_MITSU_HEAVY_PROTOCOL: #endif #if IRSND_SUPPORT_IRMP16_PROTOCOL == 1 case IRMP_IRMP16_PROTOCOL: #endif #if IRSND_SUPPORT_MELINERA_PROTOCOL == 1 case IRMP_MELINERA_PROTOCOL: #endif #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 || IRSND_SUPPORT_NEC_PROTOCOL == 1 || IRSND_SUPPORT_NEC16_PROTOCOL == 1 || IRSND_SUPPORT_NEC42_PROTOCOL == 1 || \ IRSND_SUPPORT_LGAIR_PROTOCOL == 1 || IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 || IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 || IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 || \ IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 || IRSND_SUPPORT_RECS80_PROTOCOL == 1 || IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 || IRSND_SUPPORT_DENON_PROTOCOL == 1 || \ IRSND_SUPPORT_NUBERT_PROTOCOL == 1 || IRSND_SUPPORT_FAN_PROTOCOL == 1 || IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 || IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 || \ IRSND_SUPPORT_FDC_PROTOCOL == 1 || IRSND_SUPPORT_RCCAR_PROTOCOL == 1 || IRSND_SUPPORT_JVC_PROTOCOL == 1 || IRSND_SUPPORT_NIKON_PROTOCOL == 1 || \ IRSND_SUPPORT_LEGO_PROTOCOL == 1 || IRSND_SUPPORT_THOMSON_PROTOCOL == 1 || IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 || IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 || \ IRSND_SUPPORT_PENTAX_PROTOCOL == 1 || IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 || IRSND_SUPPORT_ACP24_PROTOCOL == 1 || IRSND_SUPPORT_BOSE_PROTOCOL == 1 || \ IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 || IRSND_SUPPORT_IRMP16_PROTOCOL == 1 || IRSND_SUPPORT_MELINERA_PROTOCOL // guard for content of case { if (pulse_counter == 0) { if (current_bit == 0xFF) // send start bit { pulse_len = startbit_pulse_len; pause_len = startbit_pause_len; } else if (current_bit < complete_data_len) // send n'th bit { #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 if (irsnd_protocol == IRMP_SAMSUNG_PROTOCOL) { if (current_bit < SAMSUNG_ADDRESS_LEN) // send address bits { pulse_len = IRSND_SAMSUNG_PULSE_LEN; pause_len = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? (IRSND_SAMSUNG_1_PAUSE_LEN - 1) : (IRSND_SAMSUNG_0_PAUSE_LEN - 1); } else if (current_bit == SAMSUNG_ADDRESS_LEN) // send SYNC bit (16th bit) { pulse_len = IRSND_SAMSUNG_PULSE_LEN; pause_len = IRSND_SAMSUNG_START_BIT_PAUSE_LEN - 1; } else if (current_bit < SAMSUNG_COMPLETE_DATA_LEN) // send n'th bit { uint8_t cur_bit = current_bit - 1; // sync skipped, offset = -1 ! pulse_len = IRSND_SAMSUNG_PULSE_LEN; pause_len = (irsnd_buffer[cur_bit >> 3] & (1<<(7-(cur_bit & 7)))) ? (IRSND_SAMSUNG_1_PAUSE_LEN - 1) : (IRSND_SAMSUNG_0_PAUSE_LEN - 1); } } else #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 if (irsnd_protocol == IRMP_NEC16_PROTOCOL) { if (current_bit < NEC16_ADDRESS_LEN) // send address bits { pulse_len = IRSND_NEC_PULSE_LEN; pause_len = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? (IRSND_NEC_1_PAUSE_LEN - 1) : (IRSND_NEC_0_PAUSE_LEN - 1); } else if (current_bit == NEC16_ADDRESS_LEN) // send SYNC bit (8th bit) { pulse_len = IRSND_NEC_PULSE_LEN; pause_len = IRSND_NEC_START_BIT_PAUSE_LEN - 1; } else if (current_bit < NEC16_COMPLETE_DATA_LEN + 1) // send n'th bit { uint8_t cur_bit = current_bit - 1; // sync skipped, offset = -1 ! pulse_len = IRSND_NEC_PULSE_LEN; pause_len = (irsnd_buffer[cur_bit >> 3] & (1<<(7-(cur_bit & 7)))) ? (IRSND_NEC_1_PAUSE_LEN - 1) : (IRSND_NEC_0_PAUSE_LEN - 1); } } else #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 if (irsnd_protocol == IRMP_BANG_OLUFSEN_PROTOCOL) { if (current_bit == 0) // send 2nd start bit { pulse_len = IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN; pause_len = IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN - 1; } else if (current_bit == 1) // send 3rd start bit { pulse_len = IRSND_BANG_OLUFSEN_START_BIT3_PULSE_LEN; pause_len = IRSND_BANG_OLUFSEN_START_BIT3_PAUSE_LEN - 1; } else if (current_bit == 2) // send 4th start bit { pulse_len = IRSND_BANG_OLUFSEN_START_BIT2_PULSE_LEN; pause_len = IRSND_BANG_OLUFSEN_START_BIT2_PAUSE_LEN - 1; } else if (current_bit == 19) // send trailer bit { pulse_len = IRSND_BANG_OLUFSEN_PULSE_LEN; pause_len = IRSND_BANG_OLUFSEN_TRAILER_BIT_PAUSE_LEN - 1; } else if (current_bit < BANG_OLUFSEN_COMPLETE_DATA_LEN) // send n'th bit { uint8_t cur_bit_value = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? 1 : 0; pulse_len = IRSND_BANG_OLUFSEN_PULSE_LEN; if (cur_bit_value == last_bit_value) { pause_len = IRSND_BANG_OLUFSEN_R_PAUSE_LEN - 1; } else { pause_len = cur_bit_value ? (IRSND_BANG_OLUFSEN_1_PAUSE_LEN - 1) : (IRSND_BANG_OLUFSEN_0_PAUSE_LEN - 1); last_bit_value = cur_bit_value; } } } else #endif if (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) { pulse_len = pulse_1_len; pause_len = pause_1_len; } else { pulse_len = pulse_0_len; pause_len = pause_0_len; } } else if (has_stop_bit) // send stop bit { pulse_len = pulse_0_len; if (auto_repetition_counter < n_auto_repetitions) { pause_len = pause_0_len; } else { pause_len = 255; // last frame: pause of 255 } } } if (pulse_counter < pulse_len) { if (pulse_counter == 0) { irsnd_on (); } pulse_counter++; } else if (pause_counter < pause_len) { if (pause_counter == 0) { irsnd_off (); } pause_counter++; } else { current_bit++; if (current_bit >= complete_data_len + has_stop_bit) { /* * End of current frame, prepare for a new frame */ current_bit = 0xFF; new_frame = TRUE; auto_repetition_counter++; if (auto_repetition_counter == n_auto_repetitions) { irsnd_busy = FALSE; auto_repetition_counter = 0; } } pulse_counter = 0; pause_counter = 0; } break; } #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 case IRMP_RC5_PROTOCOL: #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 case IRMP_RC6_PROTOCOL: #endif #if IRSND_SUPPORT_RC6A_PROTOCOL == 1 case IRMP_RC6A_PROTOCOL: #endif #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 case IRMP_SIEMENS_PROTOCOL: #endif #if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 case IRMP_RUWIDO_PROTOCOL: #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 case IRMP_GRUNDIG_PROTOCOL: #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 case IRMP_IR60_PROTOCOL: #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 case IRMP_NOKIA_PROTOCOL: #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 case IRMP_A1TVBOX_PROTOCOL: #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 || \ IRSND_SUPPORT_RC6_PROTOCOL == 1 || \ IRSND_SUPPORT_RC6A_PROTOCOL == 1 || \ IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 || \ IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 || \ IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || \ IRSND_SUPPORT_IR60_PROTOCOL == 1 || \ IRSND_SUPPORT_NOKIA_PROTOCOL == 1 || \ IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 // guard for content of case { if (pulse_counter == pulse_len && pause_counter == pause_len) { current_bit++; if (current_bit >= complete_data_len) { current_bit = 0xFF; #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1 if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_IR60_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL) { auto_repetition_counter++; if (repeat_counter > 0) { // set 117 msec pause time auto_repetition_pause_len = IRSND_GRUNDIG_NOKIA_IR60_FRAME_REPEAT_PAUSE_LEN; } if (repeat_counter < n_repeat_frames) // tricky: repeat n info frames per auto repetition before sending last stop frame { n_auto_repetitions++; // increment number of auto repetitions repeat_counter++; } else if (auto_repetition_counter == n_auto_repetitions) { irsnd_busy = FALSE; auto_repetition_counter = 0; } } else #endif { irsnd_busy = FALSE; } new_frame = TRUE; irsnd_off (); } pulse_counter = 0; pause_counter = 0; } if (! new_frame) { uint8_t first_pulse; #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1 if (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL || irsnd_protocol == IRMP_IR60_PROTOCOL || irsnd_protocol == IRMP_NOKIA_PROTOCOL) { if (current_bit == 0xFF || // start bit of start-frame (irsnd_protocol == IRMP_GRUNDIG_PROTOCOL && current_bit == 15) || // start bit of info-frame (Grundig) (irsnd_protocol == IRMP_IR60_PROTOCOL && current_bit == 7) || // start bit of data frame (IR60) (irsnd_protocol == IRMP_NOKIA_PROTOCOL && (current_bit == 23 || current_bit == 47))) // start bit of info- or stop-frame (Nokia) { pulse_len = startbit_pulse_len; pause_len = startbit_pause_len; first_pulse = TRUE; } else // send n'th bit { pulse_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; pause_len = IRSND_GRUNDIG_NOKIA_IR60_BIT_LEN; first_pulse = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? TRUE : FALSE; } } else // if (irsnd_protocol == IRMP_RC5_PROTOCOL || irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL || // irsnd_protocol == IRMP_SIEMENS_PROTOCOL || irsnd_protocol == IRMP_RUWIDO_PROTOCOL) #endif { if (current_bit == 0xFF) // 1 start bit { #if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1 if (irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL) { pulse_len = startbit_pulse_len; pause_len = startbit_pause_len; } else #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 if (irsnd_protocol == IRMP_A1TVBOX_PROTOCOL) { current_bit = 0; } else #endif { ; } first_pulse = TRUE; } else // send n'th bit { #if IRSND_SUPPORT_RC6_PROTOCOL == 1 || IRSND_SUPPORT_RC6A_PROTOCOL == 1 if (irsnd_protocol == IRMP_RC6_PROTOCOL || irsnd_protocol == IRMP_RC6A_PROTOCOL) { pulse_len = IRSND_RC6_BIT_LEN; pause_len = IRSND_RC6_BIT_LEN; if (irsnd_protocol == IRMP_RC6_PROTOCOL) { if (current_bit == 4) // toggle bit (double len) { pulse_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC_BIT_LEN pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC_BIT_LEN } } else // if (irsnd_protocol == IRMP_RC6A_PROTOCOL) { if (current_bit == 4) // toggle bit (double len) { pulse_len = IRSND_RC6_BIT_3_LEN; // = 3 * RC6_BIT_LEN pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC6_BIT_LEN } else if (current_bit == 5) // toggle bit (double len) { pause_len = IRSND_RC6_BIT_2_LEN; // = 2 * RC6_BIT_LEN } } } #endif first_pulse = (irsnd_buffer[current_bit >> 3] & (1<<(7-(current_bit & 7)))) ? TRUE : FALSE; } if (irsnd_protocol == IRMP_RC5_PROTOCOL) { first_pulse = first_pulse ? FALSE : TRUE; } } if (first_pulse) { // printf ("first_pulse: current_bit: %d %d < %d %d < %d\n", current_bit, pause_counter, pause_len, pulse_counter, pulse_len); if (pulse_counter < pulse_len) { if (pulse_counter == 0) { irsnd_on (); } pulse_counter++; } else // if (pause_counter < pause_len) { if (pause_counter == 0) { irsnd_off (); } pause_counter++; } } else { // printf ("first_pause: current_bit: %d %d < %d %d < %d\n", current_bit, pause_counter, pause_len, pulse_counter, pulse_len); if (pause_counter < pause_len) { if (pause_counter == 0) { irsnd_off (); } pause_counter++; } else // if (pulse_counter < pulse_len) { if (pulse_counter == 0) { irsnd_on (); } pulse_counter++; } } } break; } #endif // IRSND_SUPPORT_RC5_PROTOCOL == 1 || IRSND_SUPPORT_RC6_PROTOCOL == 1 || || IRSND_SUPPORT_RC6A_PROTOCOL == 1 || IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 || // IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 || IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 || IRSND_SUPPORT_IR60_PROTOCOL == 1 || IRSND_SUPPORT_NOKIA_PROTOCOL == 1 // @formatter:off default: { // Just in case ... irsnd_busy = FALSE; break; } // @formatter:on } } if (!irsnd_busy) { /* * Check if we are really finished or if we must send a repeat or a trailing space */ if (repeat_counter < n_repeat_frames) { // repeat again #if IRSND_SUPPORT_FDC_PROTOCOL == 1 if (irsnd_protocol == IRMP_FDC_PROTOCOL) { irsnd_buffer[2] |= 0x0F; } #endif repeat_counter++; irsnd_busy = TRUE; } else { #if !defined(ARDUINO) // never send a trailing space for Arduino if (!irsnd_suppress_trailer) { /* * Switch to mode: send last trailing space */ irsnd_busy = TRUE; send_last_trailer = TRUE; } #endif // cleanup for ending transmission n_repeat_frames = 0; repeat_counter = 0; repeat_frame_pause_len = 0; } } } #if defined(ANALYZE) if (irsnd_is_on) { putchar ('0'); } else { putchar ('1'); } #endif return irsnd_busy; } #if defined(ANALYZE) // main function - for unix/linux + windows only! // AVR: see main.c! // Compile it under linux with: // cc irsnd.c -o irsnd // // usage: ./irsnd protocol hex-address hex-command >filename int main (int argc, char ** argv) { int protocol; int address; int command; IRMP_DATA irmp_data; if (argc != 4 && argc != 5) { fprintf (stderr, "usage: %s protocol hex-address hex-command [repeat] > filename\n", argv[0]); return 1; } if (sscanf (argv[1], "%d", &protocol) == 1 && sscanf (argv[2], "%x", &address) == 1 && sscanf (argv[3], "%x", &command) == 1) { irmp_data.protocol = protocol; irmp_data.address = address; irmp_data.command = command; if (argc == 5) { irmp_data.flags = atoi (argv[4]); } else { irmp_data.flags = 0; } irsnd_init (); (void) irsnd_send_data (&irmp_data, TRUE); while (irsnd_busy) { irsnd_ISR (); } putchar ('\n'); #if 0 // enable here to send twice (void) irsnd_send_data (&irmp_data, TRUE); while (irsnd_busy) { irsnd_ISR (); } putchar ('\n'); #endif } else { fprintf (stderr, "%s: wrong arguments\n", argv[0]); return 1; } return 0; } #endif // ANALYZE ================================================ FILE: src/irsndArduinoExt.h ================================================ /* * irsndArduinoExt.h Arduino extensions to the original irsnd.h * * Copyright (C) 2020 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 . * */ #if defined(ARDUINO) #ifndef _IRSND_ARDUINO_EXT_H #define _IRSND_ARDUINO_EXT_H #include "irmpVersion.h" #include "digitalWriteFast.h" // we use pinModeFast() and digitalReadFast() and digitalWriteFast() in turn #if defined(IR_OUTPUT_IS_ACTIVE_LOW) || defined(IRSND_GENERATE_NO_SEND_RF) #define IR_OUTPUT_ACTIVE_LEVEL LOW #define IR_OUTPUT_INACTIVE_LEVEL HIGH #else #define IR_OUTPUT_ACTIVE_LEVEL HIGH #define IR_OUTPUT_INACTIVE_LEVEL LOW #endif // /* * Set hardware pin defaults for Arduino IDE if no IRSND_OUTPUT_PIN specified */ #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) extern uint_fast8_t irsnd_output_pin; #undef IRSND_OUTPUT_PIN #define IRSND_OUTPUT_PIN irsnd_output_pin void irsnd_init(uint_fast8_t aIrsndOutputPin); void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin); void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow); #else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) # if !defined(IRSND_OUTPUT_PIN) // Arduino IDE uses IRSND_OUTPUT_PIN instead of PORT and BIT #define IRSND_OUTPUT_PIN 4 # endif #endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) void irsnd_data_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr); #if defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3 #include "mbed.h" #define F_CPU 0 // dummy definition to avoid warning at irsnd.hpp:27 #error F_CPU unkown #endif #if !defined(IR_TIMING_TEST_PIN) // Only for test purposes #define IR_TIMING_TEST_PIN 5 #endif #if ! defined(IRSND_IR_FREQUENCY) #define IRSND_IR_FREQUENCY 38000 #endif #define IRSND_INTERRUPT_FREQUENCY (IRSND_IR_FREQUENCY * 2) // *2 to toggle output pin at each interrupt /* * For Arduino AVR use timer 2 with FIXED 38000 * 2 = 76000 interrupts per second to toggle output pin. * ISR is called each 4. interrupt at a rate of 19000 interrupts per second. * (Re)define F_INTERRUPTS to the resulting call value in order to generate correct values for all the protocols. */ # undef F_INTERRUPTS # define F_INTERRUPTS (IRSND_IR_FREQUENCY / 2) // 19000 interrupts per second extern volatile uint8_t irsnd_is_on; // Used by IRTimer.hpp extern volatile uint8_t irsnd_busy; // Used by IRTimer.hpp #endif /* _IRSND_ARDUINO_EXT_H */ #endif // ARDUINO ================================================ FILE: src/irsndArduinoExt.hpp ================================================ /* * irsndArduinoExt.hpp - Arduino extensions to the original irsnd.c * * Copyright (C) 2020 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 . * */ #if defined(ARDUINO) #undef _IRMP_H_ // We are in IRSND now! Remove old symbol set from former including irmp.hpp if we use receive and send in the same user program. #include "IRTimer.hpp" // include code for timer #include "IRFeedbackLED.hpp" // include code for Feedback LED #include "irmpprotocols.hpp" // include protocol strings and array of strings #if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) uint_fast8_t irsnd_output_pin; /* * Initialize, and activate feedback LED function * @param aFeedbackLedPin - if 0 feedback function is disabled */ void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin, bool aIrmpLedFeedbackPinIsActiveLow) { irsnd_output_pin = aIrsndOutputPin; #if !defined(NO_LED_FEEDBACK_CODE) irmp_irsnd_LedFeedbackPin = aFeedbackLedPin; irmp_irsnd_LedFeedbackPinIsActiveLow = aIrmpLedFeedbackPinIsActiveLow; /* * enable feedback LED if (aFeedbackLedPin != 0) */ irmp_irsnd_LEDFeedback(aFeedbackLedPin); #else (void) aFeedbackLedPin; // to avoid compiler warnings (void) aIrmpLedFeedbackPinIsActiveLow; // to avoid compiler warnings #endif // Do not call irsnd_init_and_store_timer() here, it is done at irsnd_send_data(). pinMode(irsnd_output_pin, OUTPUT); # if defined(IRMP_MEASURE_TIMING) pinModeFast(IR_TIMING_TEST_PIN, OUTPUT); # endif } /* * Initialize, and activate feedback LED function * @param aFeedbackLedPin - if 0 feedback function is disabled */ void irsnd_init(uint_fast8_t aIrsndOutputPin, uint_fast8_t aFeedbackLedPin) { #if defined(NO_LED_FEEDBACK_CODE) irsnd_init(aIrsndOutputPin, aFeedbackLedPin, false); #else irsnd_init(aIrsndOutputPin, aFeedbackLedPin, irmp_irsnd_LedFeedbackPinIsActiveLow); #endif } /* * Initialize, use feedback LED by using 0 as led pin */ void irsnd_init(uint_fast8_t aIrsndOutputPin) { #if defined(NO_LED_FEEDBACK_CODE) irsnd_init(aIrsndOutputPin, 0, false); #else irsnd_init(aIrsndOutputPin, irmp_irsnd_LedFeedbackPin, irmp_irsnd_LedFeedbackPinIsActiveLow); #endif # if defined(IRMP_FEEDBACK_LED_PIN) // set pin if we have one at hand irmp_irsnd_LedFeedbackPin = IRMP_FEEDBACK_LED_PIN; # endif } #else // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) /* * Init function for defined pins */ void irsnd_init(void) { // Do not call irsnd_init_and_store_timer() here, it is done at irsnd_send_data(). pinModeFast(IRSND_OUTPUT_PIN, OUTPUT); # if defined(IRMP_MEASURE_TIMING) pinModeFast(IR_TIMING_TEST_PIN, OUTPUT); # endif } #endif // defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) static void irsnd_set_freq(IRSND_FREQ_TYPE freq __attribute__((unused))) { // not supported by now } /* * Called from irsnd_ISR to set the IR output */ #if defined(ESP8266) || defined(ESP32) void IRAM_ATTR irsnd_on(void) #else void irsnd_on(void) #endif { if (!irsnd_is_on) { #if !defined(NO_LED_FEEDBACK_CODE) if (irmp_irsnd_LedFeedbackEnabled) { # if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) irmp_irsnd_SetFeedbackLED(true); # else # if defined(IRMP_FEEDBACK_LED_PIN) # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) // If the built in LED on the board is active LOW digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW); # else digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH); # endif # endif # endif } #endif irsnd_is_on = TRUE; // evaluated at ISR } } #if defined(ESP8266) || defined(ESP32) void IRAM_ATTR irsnd_off(void) #else void irsnd_off(void) #endif { if (irsnd_is_on) { #if !defined(NO_LED_FEEDBACK_CODE) // Manage feedback LED if (irmp_irsnd_LedFeedbackEnabled) { # if defined(IRMP_IRSND_ALLOW_DYNAMIC_PINS) irmp_irsnd_SetFeedbackLED(false); # else # if defined(IRMP_FEEDBACK_LED_PIN) # if defined(FEEDBACK_LED_IS_ACTIVE_LOW) // If the built in LED on the board is active LOW digitalWriteFast(IRMP_FEEDBACK_LED_PIN, HIGH); # else digitalWriteFast(IRMP_FEEDBACK_LED_PIN, LOW); # endif # endif # endif } #endif irsnd_is_on = FALSE; // evaluated at ISR } } /* * irsnd_used_protocol_index holds the protocol numbers (from irsndprotocols.h) * for the included protocol name entries of the irsnd_used_protocol_names array below * E.g. irmp_used_protocol_index=2,7 and irmp_used_protocol_names="NEC","RC5". * * Both arrays together are generally smaller than the complete irmp_protocol_names array * allowing them to be used on ATtinies even if program code for access is bigger. * Flash size is more than 100 bytes less (for 15 protocols) using these arrays. */ const uint8_t irsnd_used_protocol_index[] PROGMEM = { #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 IRMP_SIRCS_PROTOCOL, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 IRMP_NEC_PROTOCOL, #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 IRMP_SAMSUNG_PROTOCOL, #endif #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 IRMP_MATSUSHITA_PROTOCOL, #endif #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 IRMP_KASEIKYO_PROTOCOL, #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 IRMP_RECS80_PROTOCOL, #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 IRMP_RC5_PROTOCOL, #endif #if IRSND_SUPPORT_DENON_PROTOCOL == 1 IRMP_DENON_PROTOCOL, #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 IRMP_RC6_PROTOCOL, #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 IRMP_SAMSUNG32_PROTOCOL, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 IRMP_APPLE_PROTOCOL, #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 IRMP_RECS80EXT_PROTOCOL, #endif #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1 IRMP_NUBERT_PROTOCOL, #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 IRMP_BANG_OLUFSEN_PROTOCOL, #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 IRMP_GRUNDIG_PROTOCOL, #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 IRMP_NOKIA_PROTOCOL, #endif #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 IRMP_SIEMENS_PROTOCOL, #endif #if IRSND_SUPPORT_FDC_PROTOCOL == 1 IRMP_FDC_PROTOCOL, #endif #if IRSND_SUPPORT_RCCAR_PROTOCOL == 1 IRMP_RCCAR_PROTOCOL, #endif #if IRSND_SUPPORT_JVC_PROTOCOL == 1 IRMP_JVC_PROTOCOL, #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 IRMP_RC6A_PROTOCOL, #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 IRMP_NIKON_PROTOCOL, #endif #if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 IRMP_RUWIDO_PROTOCOL, #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 IRMP_IR60_PROTOCOL, #endif #if IRSND_SUPPORT_KATHREIN_PROTOCOL == 1 IRMP_KATHREIN_PROTOCOL, #endif #if IRSND_SUPPORT_NETBOX_PROTOCOL == 1 IRMP_NETBOX_PROTOCOL, #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 IRMP_NEC16_PROTOCOL, #endif #if IRSND_SUPPORT_NEC42_PROTOCOL == 1 IRMP_NEC42_PROTOCOL, #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 IRMP_LEGO_PROTOCOL, #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 IRMP_THOMSON_PROTOCOL, #endif #if IRSND_SUPPORT_BOSE_PROTOCOL == 1 IRMP_BOSE_PROTOCOL, #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 IRMP_A1TVBOX_PROTOCOL, #endif #if IRSND_SUPPORT_ORTEK_PROTOCOL == 1 IRMP_ORTEK_PROTOCOL, #endif #if IRMP_SUPPORT_TELEFUNKEN_PROTOCOL == 1 IRMP_TELEFUNKEN_PROTOCOL, #endif #if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 IRMP_ROOMBA_PROTOCOL, #endif #if IRSND_SUPPORT_RCMM_PROTOCOL == 1 IRMP_RCMM12_PROTOCOL, #endif #if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 IRMP_SPEAKER_PROTOCOL, #endif #if IRSND_SUPPORT_LGAIR_PROTOCOL == 1 IRMP_LGAIR_PROTOCOL, #endif #if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1 IRMP_SAMSUNG48_PROTOCOL, #endif #if IRSND_SUPPORT_MERLIN_PROTOCOL == 1 IRMP_MERLIN_PROTOCOL, #endif #if IRSND_SUPPORT_PENTAX_PROTOCOL == 1 IRMP_PENTAX_PROTOCOL, #endif #if IRSND_SUPPORT_FAN_PROTOCOL == 1 IRMP_FAN_PROTOCOL, #endif #if IRSND_SUPPORT_S100_PROTOCOL == 1 IRMP_S100_PROTOCOL, #endif #if IRSND_SUPPORT_ACP24_PROTOCOL == 1 IRMP_ACP24_PROTOCOL, #endif #if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 IRMP_TECHNICS_PROTOCOL, #endif #if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 IRMP_PANASONIC_PROTOCOL, #endif #if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 IRMP_MITSU_HEAVY_PROTOCOL, #endif #if IRSND_SUPPORT_VINCENT_PROTOCOL == 1 IRMP_VINCENT_PROTOCOL, #endif #if IRSND_SUPPORT_SAMSUNGAH_PROTOCOL == 1 IRMP_SAMSUNGAH_PROTOCOL, #endif #if IRSND_SUPPORT_IRMP16_PROTOCOL == 1 IRMP_IRMP16_PROTOCOL, #endif #if IRSND_SUPPORT_GREE_PROTOCOL == 1 IRMP_GREE_PROTOCOL, #endif #if IRSND_SUPPORT_RCII_PROTOCOL == 1 IRMP_RCII_PROTOCOL, #endif #if IRSND_SUPPORT_METZ_PROTOCOL == 1 IRMP_METZ_PROTOCOL, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 IRMP_ONKYO_PROTOCOL, #endif #if IRSND_SUPPORT_RF_GEN24_PROTOCOL == 1 RF_GEN24_PROTOCOL, #endif #if IRMP_SUPPORT_RF_X10_PROTOCOL == 1 RF_X10_PROTOCOL, #endif #if IRMP_SUPPORT_RF_MEDION_PROTOCOL == 1 RF_MEDION_PROTOCOL #endif #if IRSND_SUPPORT_MELINERA_PROTOCOL == 1 IRMP_MELINERA_PROTOCOL #endif }; const char * const irsnd_used_protocol_names[] PROGMEM = { #if IRSND_SUPPORT_SIRCS_PROTOCOL == 1 proto_sircs, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 proto_nec, #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 proto_samsung, #endif #if IRSND_SUPPORT_MATSUSHITA_PROTOCOL == 1 proto_matsushita, #endif #if IRSND_SUPPORT_KASEIKYO_PROTOCOL == 1 proto_kaseikyo, #endif #if IRSND_SUPPORT_RECS80_PROTOCOL == 1 proto_recs80, #endif #if IRSND_SUPPORT_RC5_PROTOCOL == 1 proto_rc5, #endif #if IRSND_SUPPORT_DENON_PROTOCOL == 1 proto_denon, #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 proto_rc6, #endif #if IRSND_SUPPORT_SAMSUNG_PROTOCOL == 1 proto_samsung32, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 proto_apple, #endif #if IRSND_SUPPORT_RECS80EXT_PROTOCOL == 1 proto_recs80ext, #endif #if IRSND_SUPPORT_NUBERT_PROTOCOL == 1 proto_nubert, #endif #if IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL == 1 proto_bang_olufsen, #endif #if IRSND_SUPPORT_GRUNDIG_PROTOCOL == 1 proto_grundig, #endif #if IRSND_SUPPORT_NOKIA_PROTOCOL == 1 proto_nokia, #endif #if IRSND_SUPPORT_SIEMENS_PROTOCOL == 1 proto_siemens, #endif #if IRSND_SUPPORT_FDC_PROTOCOL == 1 proto_fdc, #endif #if IRSND_SUPPORT_RCCAR_PROTOCOL == 1 proto_rccar, #endif #if IRSND_SUPPORT_JVC_PROTOCOL == 1 proto_jvc, #endif #if IRSND_SUPPORT_RC6_PROTOCOL == 1 proto_rc6a, #endif #if IRSND_SUPPORT_NIKON_PROTOCOL == 1 proto_nikon, #endif #if IRSND_SUPPORT_RUWIDO_PROTOCOL == 1 proto_ruwido, #endif #if IRSND_SUPPORT_IR60_PROTOCOL == 1 proto_ir60, #endif #if IRSND_SUPPORT_KATHREIN_PROTOCOL == 1 proto_kathrein, #endif #if IRSND_SUPPORT_NETBOX_PROTOCOL == 1 proto_netbox, #endif #if IRSND_SUPPORT_NEC16_PROTOCOL == 1 proto_nec16, #endif #if IRSND_SUPPORT_NEC42_PROTOCOL == 1 proto_nec42, #endif #if IRSND_SUPPORT_LEGO_PROTOCOL == 1 proto_lego, #endif #if IRSND_SUPPORT_THOMSON_PROTOCOL == 1 proto_thomson, #endif #if IRSND_SUPPORT_BOSE_PROTOCOL == 1 proto_bose, #endif #if IRSND_SUPPORT_A1TVBOX_PROTOCOL == 1 proto_a1tvbox, #endif #if IRSND_SUPPORT_ORTEK_PROTOCOL == 1 proto_ortek, #endif #if IRSND_SUPPORT_TELEFUNKEN_PROTOCOL == 1 proto_telefunken, #endif #if IRSND_SUPPORT_ROOMBA_PROTOCOL == 1 proto_roomba, #endif #if IRSND_SUPPORT_RCMM_PROTOCOL == 1 proto_rcmm12, #endif #if IRSND_SUPPORT_SPEAKER_PROTOCOL == 1 proto_speaker, #endif #if IRSND_SUPPORT_LGAIR_PROTOCOL == 1 proto_lgair, #endif #if IRSND_SUPPORT_SAMSUNG48_PROTOCOL == 1 proto_samsung48, #endif #if IRSND_SUPPORT_MERLIN_PROTOCOL == 1 proto_merlin, #endif #if IRSND_SUPPORT_PENTAX_PROTOCOL == 1 proto_pentax, #endif #if IRSND_SUPPORT_FAN_PROTOCOL == 1 proto_fan, #endif #if IRSND_SUPPORT_S100_PROTOCOL == 1 proto_s100, #endif #if IRSND_SUPPORT_ACP24_PROTOCOL == 1 proto_acp24, #endif #if IRSND_SUPPORT_TECHNICS_PROTOCOL == 1 proto_technics, #endif #if IRSND_SUPPORT_PANASONIC_PROTOCOL == 1 proto_panasonic, #endif #if IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL == 1 proto_mitsu_heavy, #endif #if IRSND_SUPPORT_VINCENT_PROTOCOL == 1 proto_vincent, #endif #if IRSND_SUPPORT_SAMSUNGAH_PROTOCOL == 1 proto_samsungah, #endif #if IRSND_SUPPORT_IRMP16_PROTOCOL == 1 proto_irmp16, #endif #if IRSND_SUPPORT_GREE_PROTOCOL == 1 proto_gree, #endif #if IRSND_SUPPORT_RCII_PROTOCOL == 1 proto_rcii, #endif #if IRSND_SUPPORT_METZ_PROTOCOL == 1 proto_metz, #endif #if IRSND_SUPPORT_NEC_PROTOCOL == 1 proto_onkyo, #endif #if IRSND_SUPPORT_RF_GEN24_PROTOCOL == 1 proto_rf_gen24, #endif #if IRSND_SUPPORT_RF_X10_PROTOCOL == 1 proto_rf_x10, #endif #if IRSND_SUPPORT_RF_MEDION_PROTOCOL == 1 proto_rf_medion #endif #if IRSND_SUPPORT_MELINERA_PROTOCOL == 1 proto_melinera #endif }; void irsnd_print_protocol_name(Print *aSerial, uint8_t aProtocolNumber) { # if defined(__AVR__) for (uint_fast8_t i = 0; i < sizeof(irsnd_used_protocol_index); ++i) { if (pgm_read_byte(&irsnd_used_protocol_index[i]) == aProtocolNumber) { const char* tProtocolStringPtr = (char*) pgm_read_word(&irsnd_used_protocol_names[i]); aSerial->print((__FlashStringHelper *) (tProtocolStringPtr)); break; } } # else // no need to save space aSerial->print(irmp_protocol_names[aProtocolNumber]); # endif } void irsnd_data_print(Print *aSerial, IRMP_DATA *aIRMPDataPtr) { /* * Print protocol name or number */ aSerial->print(F("Protocol=")); #if IRSND_PROTOCOL_NAMES == 1 irsnd_print_protocol_name(aSerial, aIRMPDataPtr->protocol); aSerial->print(' '); #else aSerial->print(F("0x")); aSerial->print(aIRMPDataPtr->protocol, HEX); #endif /* * Print address, code and repetition flag */ aSerial->print(F(" Address=0x")); aSerial->print(aIRMPDataPtr->address, HEX); aSerial->print(F(" Command=0x")); aSerial->print(aIRMPDataPtr->command, HEX); if (aIRMPDataPtr->flags & IRSND_REPETITION_MASK) { aSerial->print(F(" Repeats=")); aSerial->print(aIRMPDataPtr->flags & IRSND_REPETITION_MASK); } aSerial->println(); } #endif // defined(ARDUINO) ================================================ FILE: src/irsndSelectAllProtocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irsndSelectAllProtocols.h * 39 protocols supported * * * Copyright (c) 2010-2019 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRSND_SELECT_PROTOCOLS_H #define _IRSND_SELECT_PROTOCOLS_H /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more encoders. * This saves program memory. * 1 enable encoder * 0 disable encoder *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes #define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes #define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes // more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~150 bytes #define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes #define IRSND_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~200 bytes #define IRSND_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~150 bytes #define IRSND_SUPPORT_RC6_PROTOCOL 1 // RC6 >= 10000 ~250 bytes #define IRSND_SUPPORT_RC6A_PROTOCOL 1 // RC6A >= 10000 ~250 bytes #define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes #define IRSND_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens, Gigaset >= 15000 ~150 bytes #define IRSND_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~400 bytes // exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~250 bytes // IR frequency 30 kHz #define IRSND_SUPPORT_BOSE_PROTOCOL 1 // BOSE >= 10000 ~100 bytes #define IRSND_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_NUBERT_PROTOCOL 1 // NUBERT >= 10000 ~100 bytes #define IRSND_SUPPORT_FAN_PROTOCOL 1 // FAN (ventilator) >= 10000 ~100 bytes #define IRSND_SUPPORT_SPEAKER_PROTOCOL 1 // SPEAKER >= 10000 ~100 bytes #define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang&Olufsen >= 10000 ~250 bytes // IR frequency 455 kHz #define IRSND_SUPPORT_RECS80_PROTOCOL 1 // RECS80 >= 15000 ~100 bytes #define IRSND_SUPPORT_RECS80EXT_PROTOCOL 1 // RECS80EXT >= 15000 ~100 bytes #define IRSND_SUPPORT_THOMSON_PROTOCOL 1 // Thomson >= 10000 ~250 bytes #define IRSND_SUPPORT_NIKON_PROTOCOL 1 // NIKON >= 10000 ~150 bytes #define IRSND_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 1 // Telefunken 1560 >= 10000 ~150 bytes #define IRSND_SUPPORT_FDC_PROTOCOL 1 // FDC IR keyboard >= 10000 (better 15000) ~150 bytes #define IRSND_SUPPORT_RCCAR_PROTOCOL 1 // RC CAR >= 10000 (better 15000) ~150 bytes #define IRSND_SUPPORT_ROOMBA_PROTOCOL 1 // iRobot Roomba >= 10000 ~150 bytes #define IRSND_SUPPORT_RUWIDO_PROTOCOL 1 // RUWIDO, T-Home >= 15000 ~250 bytes #define IRSND_SUPPORT_A1TVBOX_PROTOCOL 1 // A1 TV BOX >= 15000 (better 20000) ~200 bytes #define IRSND_SUPPORT_LEGO_PROTOCOL 1 // LEGO Power RC >= 20000 ~150 bytes #define IRSND_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_LGAIR_PROTOCOL 1 // LG Air Condition >= 10000 ~150 bytes. #define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 1 // Samsung48 >= 10000 ~100 bytes #define IRSND_SUPPORT_PENTAX_PROTOCOL 1 // Pentax >= 10000 ~150 bytes #define IRSND_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_ACP24_PROTOCOL 1 // ACP24 >= 10000 ~150 bytes #define IRSND_SUPPORT_TECHNICS_PROTOCOL 1 // TECHNICS >= 10000 ~200 bytes #define IRSND_SUPPORT_PANASONIC_PROTOCOL 1 // PANASONIC Beamer >= 10000 ~150 bytes #define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 1 // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer #define IRSND_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Protocols Part 2: RF decoders * If you use an IR sensor, deactivate all RF protocols! *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #define IRMP_SUPPORT_RF_GEN24_PROTOCOL 0 // RF GEN24 (generic) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_X10_PROTOCOL 0 // RF PC X10 (Medion) >= 15000 ~250 bytes #define IRMP_SUPPORT_RF_MEDION_PROTOCOL 0 // RF PC Medion >= 15000 ~250 bytes #endif // _IRSND_SELECT_PROTOCOLS_H ================================================ FILE: src/irsndSelectMain15Protocols.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irsndSelectMain15Protocols.h * * * Copyright (c) 2010-2019 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRSND_SELECT_PROTOCOLS_H #define _IRSND_SELECT_PROTOCOLS_H /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more encoders. * This saves program memory. * 1 enable decoder * 0 disable decoder *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes #define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes #define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes // more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_JVC_PROTOCOL 1 // JVC >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC16_PROTOCOL 1 // NEC16 >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC42_PROTOCOL 1 // NEC42 >= 10000 ~150 bytes #define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes #define IRSND_SUPPORT_DENON_PROTOCOL 1 // DENON, Sharp >= 10000 ~200 bytes #define IRSND_SUPPORT_RC5_PROTOCOL 1 // RC5 >= 10000 ~150 bytes #define IRSND_SUPPORT_RC6_PROTOCOL 1 // RC6 >= 10000 ~250 bytes #define IRSND_SUPPORT_RC6A_PROTOCOL 1 // RC6A >= 10000 ~250 bytes #define IRSND_SUPPORT_GRUNDIG_PROTOCOL 1 // Grundig >= 10000 ~300 bytes #define IRSND_SUPPORT_SIEMENS_PROTOCOL 1 // Siemens, Gigaset >= 15000 ~150 bytes #define IRSND_SUPPORT_NOKIA_PROTOCOL 1 // Nokia >= 10000 ~400 bytes #endif // _IRSND_SELECT_PROTOCOLS_H ================================================ FILE: src/irsndconfig.h ================================================ /*--------------------------------------------------------------------------------------------------------------------------------------------------- * irsndconfig.h * * DO NOT INCLUDE THIS FILE, WILL BE INCLUDED BY IRSND.H! * * Copyright (c) 2010-2020 Frank Meyer - frank(at)fli4l.de * * 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 2 of the License, or * (at your option) any later version. *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #ifndef _IRSNDCONFIG_H_ #define _IRSNDCONFIG_H_ #if !defined(_IRSND_H_) # error please include only irsnd.h, not irsndconfig.h #endif // #define IRSND_DEBUG 1 // activate debugging /*--------------------------------------------------------------------------------------------------------------------------------------------------- * F_INTERRUPTS: number of interrupts per second, should be in the range from 10000 to 20000, typically 15000 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(F_INTERRUPTS) # define F_INTERRUPTS 15000 // interrupts per second #endif #if ! defined(ARDUINO) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Change settings from 1 to 0 if you want to disable one or more encoders. * This saves program memory. * 1 enable encoder * 0 disable encoder *--------------------------------------------------------------------------------------------------------------------------------------------------- */ // typical protocols, disable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_SIRCS_PROTOCOL 1 // Sony SIRCS >= 10000 ~200 bytes #define IRSND_SUPPORT_NEC_PROTOCOL 1 // NEC + APPLE >= 10000 ~100 bytes #define IRSND_SUPPORT_SAMSUNG_PROTOCOL 1 // Samsung + Samsung32 >= 10000 ~300 bytes #define IRSND_SUPPORT_MATSUSHITA_PROTOCOL 1 // Matsushita >= 10000 ~200 bytes #define IRSND_SUPPORT_KASEIKYO_PROTOCOL 1 // Kaseikyo >= 10000 ~300 bytes // more protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_DENON_PROTOCOL 0 // DENON, Sharp >= 10000 ~200 bytes #define IRSND_SUPPORT_RC5_PROTOCOL 0 // RC5 >= 10000 ~150 bytes #define IRSND_SUPPORT_RC6_PROTOCOL 0 // RC6 >= 10000 ~250 bytes #define IRSND_SUPPORT_RC6A_PROTOCOL 0 // RC6A >= 10000 ~250 bytes #define IRSND_SUPPORT_JVC_PROTOCOL 0 // JVC >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC16_PROTOCOL 0 // NEC16 >= 10000 ~150 bytes #define IRSND_SUPPORT_NEC42_PROTOCOL 0 // NEC42 >= 10000 ~150 bytes #define IRSND_SUPPORT_IR60_PROTOCOL 0 // IR60 (SDA2008) >= 10000 ~250 bytes #define IRSND_SUPPORT_GRUNDIG_PROTOCOL 0 // Grundig >= 10000 ~300 bytes #define IRSND_SUPPORT_SIEMENS_PROTOCOL 0 // Siemens, Gigaset >= 15000 ~150 bytes #define IRSND_SUPPORT_NOKIA_PROTOCOL 0 // Nokia >= 10000 ~400 bytes // exotic protocols, enable here! Enable Remarks F_INTERRUPTS program memory #define IRSND_SUPPORT_BOSE_PROTOCOL 0 // BOSE >= 10000 ~100 bytes #define IRSND_SUPPORT_KATHREIN_PROTOCOL 0 // Kathrein >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_NUBERT_PROTOCOL 0 // NUBERT >= 10000 ~100 bytes #define IRSND_SUPPORT_FAN_PROTOCOL 0 // FAN (ventilator) >= 10000 ~100 bytes #define IRSND_SUPPORT_SPEAKER_PROTOCOL 0 // SPEAKER >= 10000 ~100 bytes #define IRSND_SUPPORT_BANG_OLUFSEN_PROTOCOL 0 // Bang&Olufsen >= 10000 ~250 bytes #define IRSND_SUPPORT_RECS80_PROTOCOL 0 // RECS80 >= 15000 ~100 bytes #define IRSND_SUPPORT_RECS80EXT_PROTOCOL 0 // RECS80EXT >= 15000 ~100 bytes #define IRSND_SUPPORT_THOMSON_PROTOCOL 0 // Thomson >= 10000 ~250 bytes #define IRSND_SUPPORT_NIKON_PROTOCOL 0 // NIKON >= 10000 ~150 bytes #define IRSND_SUPPORT_NETBOX_PROTOCOL 0 // Netbox keyboard >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_ORTEK_PROTOCOL 0 // ORTEK (Hama) >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_TELEFUNKEN_PROTOCOL 0 // Telefunken 1560 >= 10000 ~150 bytes #define IRSND_SUPPORT_FDC_PROTOCOL 0 // FDC IR keyboard >= 10000 (better 15000) ~150 bytes #define IRSND_SUPPORT_RCCAR_PROTOCOL 0 // RC CAR >= 10000 (better 15000) ~150 bytes #define IRSND_SUPPORT_ROOMBA_PROTOCOL 0 // iRobot Roomba >= 10000 ~150 bytes #define IRSND_SUPPORT_RUWIDO_PROTOCOL 0 // RUWIDO, T-Home >= 15000 ~250 bytes #define IRSND_SUPPORT_A1TVBOX_PROTOCOL 0 // A1 TV BOX >= 15000 (better 20000) ~200 bytes #define IRSND_SUPPORT_LEGO_PROTOCOL 0 // LEGO Power RC >= 20000 ~150 bytes #define IRSND_SUPPORT_RCMM_PROTOCOL 0 // RCMM 12,24, or 32 >= 20000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_LGAIR_PROTOCOL 0 // LG Air Condition >= 10000 ~150 bytes. #define IRSND_SUPPORT_SAMSUNG48_PROTOCOL 0 // Samsung48 >= 10000 ~100 bytes #define IRSND_SUPPORT_PENTAX_PROTOCOL 0 // Pentax >= 10000 ~150 bytes #define IRSND_SUPPORT_S100_PROTOCOL 0 // S100 >= 10000 DON'T CHANGE, NOT SUPPORTED YET! #define IRSND_SUPPORT_ACP24_PROTOCOL 0 // ACP24 >= 10000 ~150 bytes #define IRSND_SUPPORT_TECHNICS_PROTOCOL 0 // TECHNICS >= 10000 ~200 bytes #define IRSND_SUPPORT_PANASONIC_PROTOCOL 0 // PANASONIC Beamer >= 10000 ~150 bytes #define IRSND_SUPPORT_MITSU_HEAVY_PROTOCOL 0 // Mitsubishi-Heavy Aircondition, similar Timing to Panasonic beamer #define IRSND_SUPPORT_IRMP16_PROTOCOL 0 // IRMP specific >= 15000 ~250 bytes #endif // ! defined(ARDUINO) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * AVR XMega section: * * Change hardware pin here: IRSND_XMEGA_OC0A = OC0A on ATxmegas supporting OC0A, e.g. ATxmega128A1U * IRSND_XMEGA_OC0B = OC0B on ATxmegas supporting OC0B, e.g. ATxmega128A1U * IRSND_XMEGA_OC0C = OC0C on ATxmegas supporting OC0C, e.g. ATxmega128A1U * IRSND_XMEGA_OC0D = OC0D on ATxmegas supporting OC0D, e.g. ATxmega128A1U * IRSND_XMEGA_OC1A = OC1A on ATxmegas supporting OC1A, e.g. ATxmega128A1U * IRSND_XMEGA_OC1B = OC1B on ATxmegas supporting OC1B, e.g. ATxmega128A1U *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if defined(__AVR_XMEGA__) // XMEGA # define IRSND_PORT_PRE PORTD # define XMEGA_Timer TCD0 # define IRSND_OCx IRSND_XMEGA_OC0B // use OC0B /*--------------------------------------------------------------------------------------------------------------------------------------------------- * AVR ATmega/ATTiny section: * * Change hardware pin here: IRSND_OC2 = OC2 on ATmegas supporting OC2, e.g. ATmega8 * IRSND_OC2A = OC2A on ATmegas supporting OC2A, e.g. ATmega88 * IRSND_OC2B = OC2B on ATmegas supporting OC2B, e.g. ATmega88 * IRSND_OC0 = OC0 on ATmegas supporting OC0, e.g. ATmega162 * IRSND_OC0A = OC0A on ATmegas/ATtinys supporting OC0A, e.g. ATtiny84, ATtiny85, ATtiny87/167 * IRSND_OC0B = OC0B on ATmegas/ATtinys supporting OC0B, e.g. ATtiny84, ATtiny85 *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined(ATMEL_AVR) # define IRSND_OCx IRSND_OC2B // use OC2B /*--------------------------------------------------------------------------------------------------------------------------------------------------- * PIC C18 or XC8 section: * * Change hardware pin here: IRSND_PIC_CCP1 = RC2 on PIC 18F2550/18F4550, ... * IRSND_PIC_CCP2 = RC1 on PIC 18F2550/18F4550, ... *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined(PIC_C18) // C18 or XC8 compiler # if defined(__12F1840) // XC8 compiler # define Pre_Scaler 1 // define prescaler for timer2 e.g. 1,4,16 # define F_CPU 32000000UL // PIC frequency: set your freq here # define PIC_Scaler 2 // PIC needs /2 extra in IRSND_FREQ_32_KHZ calculation for right value # else // C18 compiler # define IRSND_OCx IRSND_PIC_CCP2 // Use PWMx for PIC // change other PIC C18 specific settings: # define F_CPU 48000000UL // PIC frequency: set your freq here # define Pre_Scaler 4 // define prescaler for timer2 e.g. 1,4,16 # define PIC_Scaler 2 // PIC needs /2 extra in IRSND_FREQ_32_KHZ calculation for right value # endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ARM STM32 section: *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (ARM_STM32) // use B6 as IR output on STM32 # define IRSND_PORT_LETTER B # define IRSND_BIT_NUMBER 6 # define IRSND_TIMER_NUMBER 4 # define IRSND_TIMER_CHANNEL_NUMBER 1 // only channel 1 can be used at the moment, others won't work /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ARM STM32 with HAL section - don't change here, define IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin in STM32Cube (Main.h) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (ARM_STM32_HAL) // IRSND_Transmit_GPIO_Port & IRSND_Transmit_Pin must be defined in STM32Cube # define IRSND_PORT_LETTER IRSND_Transmit_GPIO_Port//Port of Transmit PWM Pin e.g. # define IRSND_BIT_NUMBER IRSND_Transmit_Pin //Pim of Transmit PWM Pin e.g. # define IRSND_TIMER_HANDLER htim2 //Handler of Timer e.g. htim (see tim.h) # define IRSND_TIMER_CHANNEL_NUMBER TIM_CHANNEL_2 //Channel of the used Timer PWM Pin e.g. TIM_CHANNEL_2 # define IRSND_TIMER_SPEED_APBX 64000000 //Speed of the corresponding APBx. (see STM32CubeMX: Clock Configuration) /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Teensy 3.x with teensyduino gcc compiler *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (TEENSY_ARM_CORTEX_M4) # define IRSND_PIN 5 // choose an arduino pin with PWM function! /*--------------------------------------------------------------------------------------------------------------------------------------------------- * ESP8266 (Arduino, see IRSEND.ino) *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif defined (__xtensa__) # define IRSND_PIN 0 // choose an arduino pin with PWM function! #elif defined(ARDUINO) // specified here to avoid else case /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Other target systems *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #elif !defined (UNIX_OR_WINDOWS) # error target system not defined. #endif /*--------------------------------------------------------------------------------------------------------------------------------------------------- * Use Callbacks to indicate output signal or something else *--------------------------------------------------------------------------------------------------------------------------------------------------- */ #if !defined(IRSND_USE_CALLBACK) # define IRSND_USE_CALLBACK 0 // flag: 0 = don't use callbacks, 1 = use callbacks, default is 0 #endif #endif // _IRSNDCONFIG_H_